?? frame.c
字號:
/***************************************************************************** * frame.c: h264 encoder library ***************************************************************************** * Copyright (C) 2003 Laurent Aimar * $Id: frame.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include "common.h"#define PADH 32#define PADV 32x264_frame_t *x264_frame_new( x264_t *h ){ x264_frame_t *frame = x264_malloc( sizeof(x264_frame_t) ); int i, j; int i_mb_count = h->mb.i_mb_count; int i_stride; int i_lines; int i_padv = PADV << h->param.b_interlaced; if( !frame ) return NULL; memset( frame, 0, sizeof(x264_frame_t) ); /* allocate frame data (+64 for extra data for me) */ i_stride = ( ( h->param.i_width + 15 ) & -16 )+ 2*PADH; i_lines = ( ( h->param.i_height + 15 ) & -16 ); if( h->param.b_interlaced ) i_lines = ( i_lines + 31 ) & -32; frame->i_plane = 3; for( i = 0; i < 3; i++ ) { int i_divh = 1; int i_divw = 1; if( i > 0 ) { if( h->param.i_csp == X264_CSP_I420 ) i_divh = i_divw = 2; else if( h->param.i_csp == X264_CSP_I422 ) i_divw = 2; } frame->i_stride[i] = i_stride / i_divw; frame->i_lines[i] = i_lines / i_divh; CHECKED_MALLOC( frame->buffer[i], frame->i_stride[i] * ( frame->i_lines[i] + 2*i_padv / i_divh ) ); frame->plane[i] = ((uint8_t*)frame->buffer[i]) + frame->i_stride[i] * i_padv / i_divh + PADH / i_divw; } frame->i_stride[3] = 0; frame->i_lines[3] = 0; frame->buffer[3] = NULL; frame->plane[3] = NULL; frame->filtered[0] = frame->plane[0]; for( i = 0; i < 3; i++ ) { CHECKED_MALLOC( frame->buffer[4+i], frame->i_stride[0] * ( frame->i_lines[0] + 2*i_padv ) ); frame->filtered[i+1] = ((uint8_t*)frame->buffer[4+i]) + frame->i_stride[0] * i_padv + PADH; } if( h->frames.b_have_lowres ) { frame->i_stride_lowres = frame->i_stride[0]/2 + PADH; frame->i_lines_lowres = frame->i_lines[0]/2; for( i = 0; i < 4; i++ ) { CHECKED_MALLOC( frame->buffer_lowres[i], frame->i_stride_lowres * ( frame->i_lines[0]/2 + 2*i_padv ) ); frame->lowres[i] = ((uint8_t*)frame->buffer_lowres[i]) + frame->i_stride_lowres * i_padv + PADH; } } if( h->param.analyse.i_me_method == X264_ME_ESA ) { CHECKED_MALLOC( frame->buffer[7], 2 * frame->i_stride[0] * (frame->i_lines[0] + 2*i_padv) * sizeof(uint16_t) ); frame->integral = (uint16_t*)frame->buffer[7] + frame->i_stride[0] * i_padv + PADH; } frame->i_poc = -1; frame->i_type = X264_TYPE_AUTO; frame->i_qpplus1 = 0; frame->i_pts = -1; frame->i_frame = -1; frame->i_frame_num = -1; frame->i_lines_completed = -1; CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t)); CHECKED_MALLOC( frame->mv[0], 2*16 * i_mb_count * sizeof(int16_t) ); CHECKED_MALLOC( frame->ref[0], 4 * i_mb_count * sizeof(int8_t) ); if( h->param.i_bframe ) { CHECKED_MALLOC( frame->mv[1], 2*16 * i_mb_count * sizeof(int16_t) ); CHECKED_MALLOC( frame->ref[1], 4 * i_mb_count * sizeof(int8_t) ); } else { frame->mv[1] = NULL; frame->ref[1] = NULL; } CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) ); CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) ); for( i = 0; i < h->param.i_bframe + 2; i++ ) for( j = 0; j < h->param.i_bframe + 2; j++ ) CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) ); x264_pthread_mutex_init( &frame->mutex, NULL ); x264_pthread_cond_init( &frame->cv, NULL ); return frame;fail: x264_frame_delete( frame ); return NULL;}void x264_frame_delete( x264_frame_t *frame ){ int i, j; for( i = 0; i < 8; i++ ) x264_free( frame->buffer[i] ); for( i = 0; i < 4; i++ ) x264_free( frame->buffer_lowres[i] ); for( i = 0; i < X264_BFRAME_MAX+2; i++ ) for( j = 0; j < X264_BFRAME_MAX+2; j++ ) x264_free( frame->i_row_satds[i][j] ); x264_free( frame->i_row_bits ); x264_free( frame->i_row_qp ); x264_free( frame->mb_type ); x264_free( frame->mv[0] ); x264_free( frame->mv[1] ); x264_free( frame->ref[0] ); x264_free( frame->ref[1] ); x264_pthread_mutex_destroy( &frame->mutex ); x264_pthread_cond_destroy( &frame->cv ); x264_free( frame );}void x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src ){ int i_csp = src->img.i_csp & X264_CSP_MASK; dst->i_type = src->i_type; dst->i_qpplus1 = src->i_qpplus1; dst->i_pts = src->i_pts; if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX ) x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" ); else h->csp.convert[i_csp]( &h->mc, dst, &src->img, h->param.i_width, h->param.i_height );}static void plane_expand_border( uint8_t *pix, int i_stride, int i_width, int i_height, int i_padh, int i_padv, int b_pad_top, int b_pad_bottom ){#define PPIXEL(x, y) ( pix + (x) + (y)*i_stride ) int y; for( y = 0; y < i_height; y++ ) { /* left band */ memset( PPIXEL(-i_padh, y), PPIXEL(0, y)[0], i_padh ); /* right band */ memset( PPIXEL(i_width, y), PPIXEL(i_width-1, y)[0], i_padh ); } /* upper band */ if( b_pad_top ) for( y = 0; y < i_padv; y++ ) memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), i_width+2*i_padh ); /* lower band */ if( b_pad_bottom ) for( y = 0; y < i_padv; y++ ) memcpy( PPIXEL(-i_padh, i_height+y), PPIXEL(-i_padh, i_height-1), i_width+2*i_padh );#undef PPIXEL}void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_end ){ int i; int b_start = !mb_y; if( mb_y & h->sh.b_mbaff ) return; for( i = 0; i < frame->i_plane; i++ ) { int stride = frame->i_stride[i]; int width = 16*h->sps->i_mb_width >> !!i; int height = (b_end ? 16*(h->sps->i_mb_height - mb_y) >> h->sh.b_mbaff : 16) >> !!i; int padh = PADH >> !!i; int padv = PADV >> !!i; // buffer: 2 chroma, 3 luma (rounded to 4) because deblocking goes beyond the top of the mb uint8_t *pix = frame->plane[i] + X264_MAX(0, (16*mb_y-4)*stride >> !!i); if( b_end && !b_start ) height += 4 >> (!!i + h->sh.b_mbaff); if( h->sh.b_mbaff ) { plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end ); plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end ); } else { plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end ); } }}void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame, int mb_y, int b_end ){ /* during filtering, 8 extra pixels were filtered on each edge. we want to expand border from the last filtered pixel */ int b_start = !mb_y; int stride = frame->i_stride[0]; int width = 16*h->sps->i_mb_width + 16; int height = b_end ? (16*(h->sps->i_mb_height - mb_y) >> h->sh.b_mbaff) + 16 : 16; int padh = PADH - 8; int padv = PADV - 8; int i; for( i = 1; i < 4; i++ ) { // buffer: 8 luma, to match the hpel filter uint8_t *pix = frame->filtered[i] + (16*mb_y - (8 << h->sh.b_mbaff)) * stride - 8; if( h->sh.b_mbaff ) { plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end ); plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end ); } else { plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end ); } }}void x264_frame_expand_border_lowres( x264_frame_t *frame ){ int i; for( i = 0; i < 4; i++ ) plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_stride_lowres - 2*PADH, frame->i_lines_lowres, PADH, PADV, 1, 1 );}void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame ){ int i, y; for( i = 0; i < frame->i_plane; i++ ) { int i_subsample = i ? 1 : 0; int i_width = h->param.i_width >> i_subsample; int i_height = h->param.i_height >> i_subsample; int i_padx = ( h->sps->i_mb_width * 16 - h->param.i_width ) >> i_subsample; int i_pady = ( h->sps->i_mb_height * 16 - h->param.i_height ) >> i_subsample; if( i_padx ) { for( y = 0; y < i_height; y++ ) memset( &frame->plane[i][y*frame->i_stride[i] + i_width], frame->plane[i][y*frame->i_stride[i] + i_width - 1], i_padx ); } if( i_pady ) { //FIXME interlace? or just let it pad using the wrong field for( y = i_height; y < i_height + i_pady; y++ ) memcpy( &frame->plane[i][y*frame->i_stride[i]], &frame->plane[i][(i_height-1)*frame->i_stride[i]], i_width + i_padx ); } }}/* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of * entropy coding, but per 64 coeffs for the purpose of deblocking */void munge_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] ){ uint32_t (*src)[6] = (uint32_t(*)[6])h->mb.non_zero_count + mb_y * h->sps->i_mb_width; int8_t *transform = h->mb.mb_transform_size + mb_y * h->sps->i_mb_width; int x; for( x=0; x<h->sps->i_mb_width; x++ ) { memcpy( buf+x, src+x, 16 ); if( transform[x] ) { if( src[x][0] ) src[x][0] = 0x01010101;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -