mpegvideo.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:238k
源码类别:
Windows CE
开发平台:
C/C++
- /* * The simplest mpeg encoder (well, it was the simplest!) * Copyright (c) 2000,2001 Fabrice Bellard. * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 4MV & hq & b-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at> */ /** * @file mpegvideo.c * The simplest mpeg encoder (well, it was the simplest!). */ #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" #include "faandct.h" #include <limits.h> #ifdef USE_FASTMEMCPY #include "fastmemcpy.h" #endif //#undef NDEBUG //#include <assert.h> #ifdef CONFIG_ENCODERS static void encode_picture(MpegEncContext *s, int picture_number); #endif //CONFIG_ENCODERS static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void dct_unquantize_h263_intra_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void dct_unquantize_h263_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void draw_edges_c(uint8_t *buf, int wrap, int width, int height, int w); #ifdef CONFIG_ENCODERS static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); static int dct_quantize_refine(MpegEncContext *s, DCTELEM *block, int16_t *weight, DCTELEM *orig, int n, int qscale); static int sse_mb(MpegEncContext *s); static void denoise_dct_c(MpegEncContext *s, DCTELEM *block); #endif //CONFIG_ENCODERS #ifdef HAVE_XVMC extern int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx); extern void XVMC_field_end(MpegEncContext *s); extern void XVMC_decode_mb(MpegEncContext *s); #endif void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w)= draw_edges_c; /* enable all paranoid tests for rounding, overflows, etc... */ //#define PARANOID //#define DEBUG /* for jpeg fast DCT */ #define CONST_BITS 14 static const uint16_t aanscales[64] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867 , 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520 , 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; static const uint8_t h263_chroma_roundtab[16] = { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, }; static const uint8_t ff_default_chroma_qscale_table[32]={ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 }; #ifdef CONFIG_ENCODERS static uint8_t (*default_mv_penalty)[MAX_MV*2+1]=NULL; static uint8_t default_fcode_tab[MAX_MV*2+1]; enum PixelFormat ff_yuv420p_list[2]= {PIX_FMT_YUV420P, -1}; static void convert_matrix(DSPContext *dsp, int (*qmat)[64], uint16_t (*qmat16)[2][64], const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra) { int qscale; int shift=0; for(qscale=qmin; qscale<=qmax; qscale++){ int i; if (dsp->fdct == ff_jpeg_fdct_islow #ifdef FAAN_POSTSCALE || dsp->fdct == ff_faandct #endif ) { for(i=0;i<64;i++) { const int j= dsp->idct_permutation[i]; /* 16 <= qscale * quant_matrix[i] <= 7905 */ /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ qmat[qscale][i] = (int)((uint64_t_C(1) << QMAT_SHIFT) / (qscale * quant_matrix[j])); } } else if (dsp->fdct == fdct_ifast #ifndef FAAN_POSTSCALE || dsp->fdct == ff_faandct #endif ) { for(i=0;i<64;i++) { const int j= dsp->idct_permutation[i]; /* 16 <= qscale * quant_matrix[i] <= 7905 */ /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ qmat[qscale][i] = (int)((uint64_t_C(1) << (QMAT_SHIFT + 14)) / (aanscales[i] * qscale * quant_matrix[j])); } } else { for(i=0;i<64;i++) { const int j= dsp->idct_permutation[i]; /* We can safely suppose that 16 <= quant_matrix[i] <= 255 So 16 <= qscale * quant_matrix[i] <= 7905 so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 */ qmat[qscale][i] = (int)((uint64_t_C(1) << QMAT_SHIFT) / (qscale * quant_matrix[j])); // qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[j]); if(qmat16[qscale][0][i]==0 || qmat16[qscale][0][i]==128*256) qmat16[qscale][0][i]=128*256-1; qmat16[qscale][1][i]= ROUNDED_DIV(bias<<(16-QUANT_BIAS_SHIFT), qmat16[qscale][0][i]); } } for(i=intra; i<64; i++){ int64_t max= 8191; if (dsp->fdct == fdct_ifast #ifndef FAAN_POSTSCALE || dsp->fdct == ff_faandct #endif ) { max= (8191LL*aanscales[i]) >> 14; } while(((max * qmat[qscale][i]) >> shift) > INT_MAX){ shift++; } } } if(shift){ av_log(NULL, AV_LOG_INFO, "Warning, QMAT_SHIFT is larger then %d, overflows possiblen", QMAT_SHIFT - shift); } } static inline void update_qscale(MpegEncContext *s){ s->qscale= (s->lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7); s->qscale= clip(s->qscale, s->avctx->qmin, s->avctx->qmax); s->lambda2= (s->lambda*s->lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT; } #endif //CONFIG_ENCODERS void ff_init_scantable(uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable){ int i; int end; st->scantable= src_scantable; for(i=0; i<64; i++){ int j; j = src_scantable[i]; st->permutated[i] = permutation[j]; #ifdef ARCH_POWERPC st->inverse[j] = i; #endif } end=-1; for(i=0; i<64; i++){ int j; j = st->permutated[i]; if(j>end) end=j; st->raster_end[i]= end; } } #ifdef CONFIG_ENCODERS void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix){ int i; if(matrix){ put_bits(pb, 1, 1); for(i=0;i<64;i++) { put_bits(pb, 8, matrix[ ff_zigzag_direct[i] ]); } }else put_bits(pb, 1, 0); } #endif //CONFIG_ENCODERS /* init common dct for both encoder and decoder */ int DCT_common_init(MpegEncContext *s) { s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c; s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c; s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c; s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c; s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; #ifdef CONFIG_ENCODERS s->dct_quantize= dct_quantize_c; s->denoise_dct= denoise_dct_c; #endif //CONFIG_ENCODERS #ifdef HAVE_MMX MPV_common_init_mmx(s); #endif #ifdef ARCH_ALPHA MPV_common_init_axp(s); #endif #ifdef HAVE_MLIB MPV_common_init_mlib(s); #endif #ifdef HAVE_MMI MPV_common_init_mmi(s); #endif #ifdef ARCH_ARMV4L MPV_common_init_armv4l(s); #endif #ifdef ARCH_POWERPC MPV_common_init_ppc(s); #endif #ifdef CONFIG_ENCODERS s->fast_dct_quantize= s->dct_quantize; if(s->flags&CODEC_FLAG_TRELLIS_QUANT){ s->dct_quantize= dct_quantize_trellis_c; //move before MPV_common_init_* } #endif //CONFIG_ENCODERS /* load & permutate scantables note: only wmv uses different ones */ if(s->alternate_scan){ ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_alternate_vertical_scan); ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_alternate_vertical_scan); }else{ ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_zigzag_direct); ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_zigzag_direct); } ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); return 0; } static void copy_picture(Picture *dst, Picture *src){ *dst = *src; dst->type= FF_BUFFER_TYPE_COPY; } static void copy_picture_attributes(MpegEncContext *s, AVFrame *dst, AVFrame *src){ int i; dst->pict_type = src->pict_type; dst->quality = src->quality; dst->coded_picture_number = src->coded_picture_number; dst->display_picture_number = src->display_picture_number; // dst->reference = src->reference; dst->pts = src->pts; dst->interlaced_frame = src->interlaced_frame; dst->top_field_first = src->top_field_first; if(s->avctx->me_threshold){ if(!src->motion_val[0]) av_log(s->avctx, AV_LOG_ERROR, "AVFrame.motion_val not set!n"); if(!src->mb_type) av_log(s->avctx, AV_LOG_ERROR, "AVFrame.mb_type not set!n"); if(!src->ref_index[0]) av_log(s->avctx, AV_LOG_ERROR, "AVFrame.ref_index not set!n"); if(src->motion_subsample_log2 != dst->motion_subsample_log2) av_log(s->avctx, AV_LOG_ERROR, "AVFrame.motion_subsample_log2 doesn't match! (%d!=%d)n", src->motion_subsample_log2, dst->motion_subsample_log2); memcpy(dst->mb_type, src->mb_type, s->mb_stride * s->mb_height * sizeof(dst->mb_type[0])); for(i=0; i<2; i++){ int stride= ((16*s->mb_width )>>src->motion_subsample_log2) + 1; int height= ((16*s->mb_height)>>src->motion_subsample_log2); if(src->motion_val[i] && src->motion_val[i] != dst->motion_val[i]){ memcpy(dst->motion_val[i], src->motion_val[i], 2*stride*height*sizeof(int16_t)); } if(src->ref_index[i] && src->ref_index[i] != dst->ref_index[i]){ memcpy(dst->ref_index[i], src->ref_index[i], s->b8_stride*2*s->mb_height*sizeof(int8_t)); } } } } /** * allocates a Picture * The pixels are allocated/set by calling get_buffer() if shared=0 */ static int alloc_picture(MpegEncContext *s, Picture *pic, int shared){ const int big_mb_num= s->mb_stride*(s->mb_height+1) + 1; //the +1 is needed so memset(,,stride*height) doesnt sig11 const int mb_array_size= s->mb_stride*s->mb_height; const int b8_array_size= s->b8_stride*s->mb_height*2; const int b4_array_size= s->b4_stride*s->mb_height*4; int i; if(shared){ assert(pic->data[0]); assert(pic->type == 0 || pic->type == FF_BUFFER_TYPE_SHARED); pic->type= FF_BUFFER_TYPE_SHARED; }else{ int r; assert(!pic->data[0]); r= s->avctx->get_buffer(s->avctx, (AVFrame*)pic); if(r<0 || !pic->age || !pic->type || !pic->data[0]){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %d %d %p)n", r, pic->age, pic->type, pic->data[0]); return -1; } if(s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1])){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (stride changed)n"); return -1; } if(pic->linesize[1] != pic->linesize[2]){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (uv stride mismatch)n"); return -1; } s->linesize = pic->linesize[0]; s->uvlinesize= pic->linesize[1]; } if(pic->qscale_table==NULL){ if (s->encoding) { CHECKED_ALLOCZ(pic->mb_var , mb_array_size * sizeof(int16_t)) CHECKED_ALLOCZ(pic->mc_mb_var, mb_array_size * sizeof(int16_t)) CHECKED_ALLOCZ(pic->mb_mean , mb_array_size * sizeof(int8_t)) } CHECKED_ALLOCZ(pic->mbskip_table , mb_array_size * sizeof(uint8_t)+2) //the +2 is for the slice end check CHECKED_ALLOCZ(pic->qscale_table , mb_array_size * sizeof(uint8_t)) CHECKED_ALLOCZ(pic->mb_type_base , big_mb_num * sizeof(uint32_t)) pic->mb_type= pic->mb_type_base + s->mb_stride+1; if(s->out_format == FMT_H264){ for(i=0; i<2; i++){ CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+4) * sizeof(int16_t)) pic->motion_val[i]= pic->motion_val_base[i]+4; CHECKED_ALLOCZ(pic->ref_index[i], b8_array_size * sizeof(uint8_t)) } pic->motion_subsample_log2= 2; }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){ for(i=0; i<2; i++){ CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+4) * sizeof(int16_t)) pic->motion_val[i]= pic->motion_val_base[i]+4; CHECKED_ALLOCZ(pic->ref_index[i], b8_array_size * sizeof(uint8_t)) } pic->motion_subsample_log2= 3; } if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { CHECKED_ALLOCZ(pic->dct_coeff, 64 * mb_array_size * sizeof(DCTELEM)*6) } pic->qstride= s->mb_stride; CHECKED_ALLOCZ(pic->pan_scan , 1 * sizeof(AVPanScan)) } //it might be nicer if the application would keep track of these but it would require a API change memmove(s->prev_pict_types+1, s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE-1); s->prev_pict_types[0]= s->pict_type; if(pic->age < PREV_PICT_TYPES_BUFFER_SIZE && s->prev_pict_types[pic->age] == B_TYPE) pic->age= INT_MAX; // skipped MBs in b frames are quite rare in mpeg1/2 and its a bit tricky to skip them anyway return 0; fail: //for the CHECKED_ALLOCZ macro return -1; } /** * deallocates a picture */ static void free_picture(MpegEncContext *s, Picture *pic){ int i; if(pic->data[0] && pic->type!=FF_BUFFER_TYPE_SHARED){ s->avctx->release_buffer(s->avctx, (AVFrame*)pic); } av_freep(&pic->mb_var); av_freep(&pic->mc_mb_var); av_freep(&pic->mb_mean); av_freep(&pic->mbskip_table); av_freep(&pic->qscale_table); av_freep(&pic->mb_type_base); av_freep(&pic->dct_coeff); av_freep(&pic->pan_scan); pic->mb_type= NULL; for(i=0; i<2; i++){ av_freep(&pic->motion_val_base[i]); av_freep(&pic->ref_index[i]); } if(pic->type == FF_BUFFER_TYPE_SHARED){ for(i=0; i<4; i++){ pic->base[i]= pic->data[i]= NULL; } pic->type= 0; } } static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){ int i; // edge emu needs blocksize + filter length - 1 (=17x17 for halfpel / 21x21 for h264) CHECKED_ALLOCZ(s->allocated_edge_emu_buffer, (s->width+64)*2*17*2); //(width + edge + align)*interlaced*MBsize*tolerance s->edge_emu_buffer= s->allocated_edge_emu_buffer + (s->width+64)*2*17; //FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer() CHECKED_ALLOCZ(s->me.scratchpad, (s->width+64)*4*16*2*sizeof(uint8_t)) s->rd_scratchpad= s->me.scratchpad; s->b_scratchpad= s->me.scratchpad; s->obmc_scratchpad= s->me.scratchpad + 16; if (s->encoding) { CHECKED_ALLOCZ(s->me.map , ME_MAP_SIZE*sizeof(uint32_t)) CHECKED_ALLOCZ(s->me.score_map, ME_MAP_SIZE*sizeof(uint32_t)) if(s->avctx->noise_reduction){ CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int)) } } CHECKED_ALLOCZ(s->blocks, 64*12*2 * sizeof(DCTELEM)) s->block= s->blocks[0]; for(i=0;i<12;i++){ s->pblocks[i] = (short *)(&s->block[i]); } return 0; fail: return -1; //free() through MPV_common_end() } static void free_duplicate_context(MpegEncContext *s){ if(s==NULL) return; av_freep(&s->allocated_edge_emu_buffer); s->edge_emu_buffer= NULL; av_freep(&s->me.scratchpad); s->rd_scratchpad= s->b_scratchpad= s->obmc_scratchpad= NULL; av_freep(&s->dct_error_sum); av_freep(&s->me.map); av_freep(&s->me.score_map); av_freep(&s->blocks); s->block= NULL; } static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src){ #define COPY(a) bak->a= src->a COPY(allocated_edge_emu_buffer); COPY(edge_emu_buffer); COPY(me.scratchpad); COPY(rd_scratchpad); COPY(b_scratchpad); COPY(obmc_scratchpad); COPY(me.map); COPY(me.score_map); COPY(blocks); COPY(block); COPY(start_mb_y); COPY(end_mb_y); COPY(me.map_generation); COPY(pb); COPY(dct_error_sum); COPY(dct_count[0]); COPY(dct_count[1]); #undef COPY } void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src){ MpegEncContext bak; int i; //FIXME copy only needed parts //START_TIMER backup_duplicate_context(&bak, dst); memcpy(dst, src, sizeof(MpegEncContext)); backup_duplicate_context(dst, &bak); for(i=0;i<12;i++){ dst->pblocks[i] = (short *)(&dst->block[i]); } //STOP_TIMER("update_duplicate_context") //about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads } static void update_duplicate_context_after_me(MpegEncContext *dst, MpegEncContext *src){ #define COPY(a) dst->a= src->a COPY(pict_type); COPY(current_picture); COPY(f_code); COPY(b_code); COPY(qscale); COPY(lambda); COPY(lambda2); COPY(picture_in_gop_number); COPY(gop_picture_number); COPY(frame_pred_frame_dct); //FIXME don't set in encode_header COPY(progressive_frame); //FIXME don't set in encode_header COPY(partitioned_frame); //FIXME don't set in encode_header #undef COPY } /** * sets the given MpegEncContext to common defaults (same for encoding and decoding). * the changed fields will not depend upon the prior state of the MpegEncContext. */ static void MPV_common_defaults(MpegEncContext *s){ s->y_dc_scale_table= s->c_dc_scale_table= ff_mpeg1_dc_scale_table; s->chroma_qscale_table= ff_default_chroma_qscale_table; s->progressive_frame= 1; s->progressive_sequence= 1; s->picture_structure= PICT_FRAME; s->coded_picture_number = 0; s->picture_number = 0; s->input_picture_number = 0; s->picture_in_gop_number = 0; s->f_code = 1; s->b_code = 1; } /** * sets the given MpegEncContext to defaults for decoding. * the changed fields will not depend upon the prior state of the MpegEncContext. */ void MPV_decode_defaults(MpegEncContext *s){ MPV_common_defaults(s); } /** * sets the given MpegEncContext to defaults for encoding. * the changed fields will not depend upon the prior state of the MpegEncContext. */ #ifdef CONFIG_ENCODERS static void MPV_encode_defaults(MpegEncContext *s){ static int done=0; MPV_common_defaults(s); if(!done){ int i; done=1; default_mv_penalty= av_mallocz( sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1) ); memset(default_fcode_tab , 0, sizeof(uint8_t)*(2*MAX_MV+1)); for(i=-16; i<16; i++){ default_fcode_tab[i + MAX_MV]= 1; } } s->me.mv_penalty= default_mv_penalty; s->fcode_tab= default_fcode_tab; } #endif //CONFIG_ENCODERS /** * init common structure for both encoder and decoder. * this assumes that some variables like width/height are already set */ int MPV_common_init(MpegEncContext *s) { int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; if(s->avctx->thread_count > MAX_THREADS || (16*s->avctx->thread_count > s->height && s->height)){ av_log(s->avctx, AV_LOG_ERROR, "too many threadsn"); return -1; } if((s->width || s->height) && avcodec_check_dimensions(s->avctx, s->width, s->height)) return -1; dsputil_init(&s->dsp, s->avctx); DCT_common_init(s); s->flags= s->avctx->flags; s->flags2= s->avctx->flags2; s->mb_width = (s->width + 15) / 16; s->mb_height = (s->height + 15) / 16; s->mb_stride = s->mb_width + 1; s->b8_stride = s->mb_width*2 + 1; s->b4_stride = s->mb_width*4 + 1; mb_array_size= s->mb_height * s->mb_stride; mv_table_size= (s->mb_height+2) * s->mb_stride + 1; /* set chroma shifts */ avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,&(s->chroma_x_shift), &(s->chroma_y_shift) ); /* set default edge pos, will be overriden in decode_header if needed */ s->h_edge_pos= s->mb_width*16; s->v_edge_pos= s->mb_height*16; s->mb_num = s->mb_width * s->mb_height; s->block_wrap[0]= s->block_wrap[1]= s->block_wrap[2]= s->block_wrap[3]= s->b8_stride; s->block_wrap[4]= s->block_wrap[5]= s->mb_stride; y_size = s->b8_stride * (2 * s->mb_height + 1); c_size = s->mb_stride * (s->mb_height + 1); yc_size = y_size + 2 * c_size; /* convert fourcc to upper case */ s->avctx->codec_tag= toupper( s->avctx->codec_tag &0xFF) + (toupper((s->avctx->codec_tag>>8 )&0xFF)<<8 ) + (toupper((s->avctx->codec_tag>>16)&0xFF)<<16) + (toupper((s->avctx->codec_tag>>24)&0xFF)<<24); s->avctx->stream_codec_tag= toupper( s->avctx->stream_codec_tag &0xFF) + (toupper((s->avctx->stream_codec_tag>>8 )&0xFF)<<8 ) + (toupper((s->avctx->stream_codec_tag>>16)&0xFF)<<16) + (toupper((s->avctx->stream_codec_tag>>24)&0xFF)<<24); s->avctx->coded_frame= (AVFrame*)&s->current_picture; CHECKED_ALLOCZ(s->mb_index2xy, (s->mb_num+1)*sizeof(int)) //error ressilience code looks cleaner with this for(y=0; y<s->mb_height; y++){ for(x=0; x<s->mb_width; x++){ s->mb_index2xy[ x + y*s->mb_width ] = x + y*s->mb_stride; } } s->mb_index2xy[ s->mb_height*s->mb_width ] = (s->mb_height-1)*s->mb_stride + s->mb_width; //FIXME really needed? if (s->encoding) { /* Allocate MV tables */ CHECKED_ALLOCZ(s->p_mv_table_base , mv_table_size * 2 * sizeof(int16_t)) CHECKED_ALLOCZ(s->b_forw_mv_table_base , mv_table_size * 2 * sizeof(int16_t)) CHECKED_ALLOCZ(s->b_back_mv_table_base , mv_table_size * 2 * sizeof(int16_t)) CHECKED_ALLOCZ(s->b_bidir_forw_mv_table_base , mv_table_size * 2 * sizeof(int16_t)) CHECKED_ALLOCZ(s->b_bidir_back_mv_table_base , mv_table_size * 2 * sizeof(int16_t)) CHECKED_ALLOCZ(s->b_direct_mv_table_base , mv_table_size * 2 * sizeof(int16_t)) s->p_mv_table = s->p_mv_table_base + s->mb_stride + 1; s->b_forw_mv_table = s->b_forw_mv_table_base + s->mb_stride + 1; s->b_back_mv_table = s->b_back_mv_table_base + s->mb_stride + 1; s->b_bidir_forw_mv_table= s->b_bidir_forw_mv_table_base + s->mb_stride + 1; s->b_bidir_back_mv_table= s->b_bidir_back_mv_table_base + s->mb_stride + 1; s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; if(s->msmpeg4_version){ CHECKED_ALLOCZ(s->ac_stats, 2*2*(MAX_LEVEL+1)*(MAX_RUN+1)*2*sizeof(int)); } CHECKED_ALLOCZ(s->avctx->stats_out, 256); /* Allocate MB type table */ CHECKED_ALLOCZ(s->mb_type , mb_array_size * sizeof(uint16_t)) //needed for encoding CHECKED_ALLOCZ(s->lambda_table, mb_array_size * sizeof(int)) CHECKED_ALLOCZ(s->q_intra_matrix, 64*32 * sizeof(int)) CHECKED_ALLOCZ(s->q_inter_matrix, 64*32 * sizeof(int)) CHECKED_ALLOCZ(s->q_intra_matrix16, 64*32*2 * sizeof(uint16_t)) CHECKED_ALLOCZ(s->q_inter_matrix16, 64*32*2 * sizeof(uint16_t)) CHECKED_ALLOCZ(s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*)) CHECKED_ALLOCZ(s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*)) if(s->avctx->noise_reduction){ CHECKED_ALLOCZ(s->dct_offset, 2 * 64 * sizeof(uint16_t)) } } CHECKED_ALLOCZ(s->picture, MAX_PICTURE_COUNT * sizeof(Picture)) CHECKED_ALLOCZ(s->error_status_table, mb_array_size*sizeof(uint8_t)) if(s->codec_id==CODEC_ID_MPEG4 || (s->flags & CODEC_FLAG_INTERLACED_ME)){ /* interlaced direct mode decoding tables */ for(i=0; i<2; i++){ int j, k; for(j=0; j<2; j++){ for(k=0; k<2; k++){ CHECKED_ALLOCZ(s->b_field_mv_table_base[i][j][k] , mv_table_size * 2 * sizeof(int16_t)) s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1; } CHECKED_ALLOCZ(s->b_field_select_table[i][j] , mb_array_size * 2 * sizeof(uint8_t)) CHECKED_ALLOCZ(s->p_field_mv_table_base[i][j] , mv_table_size * 2 * sizeof(int16_t)) s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; } CHECKED_ALLOCZ(s->p_field_select_table[i] , mb_array_size * 2 * sizeof(uint8_t)) } } if (s->out_format == FMT_H263) { /* ac values */ CHECKED_ALLOCZ(s->ac_val_base, yc_size * sizeof(int16_t) * 16); s->ac_val[0] = s->ac_val_base + s->b8_stride + 1; s->ac_val[1] = s->ac_val_base + y_size + s->mb_stride + 1; s->ac_val[2] = s->ac_val[1] + c_size; /* cbp values */ CHECKED_ALLOCZ(s->coded_block_base, y_size); s->coded_block= s->coded_block_base + s->b8_stride + 1; /* cbp, ac_pred, pred_dir */ CHECKED_ALLOCZ(s->cbp_table , mb_array_size * sizeof(uint8_t)) CHECKED_ALLOCZ(s->pred_dir_table, mb_array_size * sizeof(uint8_t)) } if (s->h263_pred || s->h263_plus || !s->encoding) { /* dc values */ //MN: we need these for error resilience of intra-frames CHECKED_ALLOCZ(s->dc_val_base, yc_size * sizeof(int16_t)); s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1; s->dc_val[2] = s->dc_val[1] + c_size; for(i=0;i<yc_size;i++) s->dc_val_base[i] = 1024; } /* which mb is a intra block */ CHECKED_ALLOCZ(s->mbintra_table, mb_array_size); memset(s->mbintra_table, 1, mb_array_size); /* init macroblock skip table */ CHECKED_ALLOCZ(s->mbskip_table, mb_array_size+2); //Note the +1 is for a quicker mpeg4 slice_end detection CHECKED_ALLOCZ(s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE); s->parse_context.state= -1; if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){ s->visualization_buffer[0] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH); s->visualization_buffer[1] = av_malloc((s->mb_width*8 + EDGE_WIDTH) * s->mb_height*8 + EDGE_WIDTH); s->visualization_buffer[2] = av_malloc((s->mb_width*8 + EDGE_WIDTH) * s->mb_height*8 + EDGE_WIDTH); } s->context_initialized = 1; s->thread_context[0]= s; for(i=1; i<s->avctx->thread_count; i++){ s->thread_context[i]= av_malloc(sizeof(MpegEncContext)); memcpy(s->thread_context[i], s, sizeof(MpegEncContext)); } for(i=0; i<s->avctx->thread_count; i++){ if(init_duplicate_context(s->thread_context[i], s) < 0) goto fail; s->thread_context[i]->start_mb_y= (s->mb_height*(i ) + s->avctx->thread_count/2) / s->avctx->thread_count; s->thread_context[i]->end_mb_y = (s->mb_height*(i+1) + s->avctx->thread_count/2) / s->avctx->thread_count; } return 0; fail: MPV_common_end(s); return -1; } /* init common structure for both encoder and decoder */ void MPV_common_end(MpegEncContext *s) { int i, j, k; for(i=0; i<s->avctx->thread_count; i++){ free_duplicate_context(s->thread_context[i]); } for(i=1; i<s->avctx->thread_count; i++){ av_freep(&s->thread_context[i]); } av_freep(&s->parse_context.buffer); s->parse_context.buffer_size=0; av_freep(&s->mb_type); av_freep(&s->p_mv_table_base); av_freep(&s->b_forw_mv_table_base); av_freep(&s->b_back_mv_table_base); av_freep(&s->b_bidir_forw_mv_table_base); av_freep(&s->b_bidir_back_mv_table_base); av_freep(&s->b_direct_mv_table_base); s->p_mv_table= NULL; s->b_forw_mv_table= NULL; s->b_back_mv_table= NULL; s->b_bidir_forw_mv_table= NULL; s->b_bidir_back_mv_table= NULL; s->b_direct_mv_table= NULL; for(i=0; i<2; i++){ for(j=0; j<2; j++){ for(k=0; k<2; k++){ av_freep(&s->b_field_mv_table_base[i][j][k]); s->b_field_mv_table[i][j][k]=NULL; } av_freep(&s->b_field_select_table[i][j]); av_freep(&s->p_field_mv_table_base[i][j]); s->p_field_mv_table[i][j]=NULL; } av_freep(&s->p_field_select_table[i]); } av_freep(&s->dc_val_base); av_freep(&s->ac_val_base); av_freep(&s->coded_block_base); av_freep(&s->mbintra_table); av_freep(&s->cbp_table); av_freep(&s->pred_dir_table); av_freep(&s->mbskip_table); av_freep(&s->prev_pict_types); av_freep(&s->bitstream_buffer); s->allocated_bitstream_buffer_size=0; av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); av_freep(&s->error_status_table); av_freep(&s->mb_index2xy); av_freep(&s->lambda_table); av_freep(&s->q_intra_matrix); av_freep(&s->q_inter_matrix); av_freep(&s->q_intra_matrix16); av_freep(&s->q_inter_matrix16); av_freep(&s->input_picture); av_freep(&s->reordered_input_picture); av_freep(&s->dct_offset); if(s->picture){ for(i=0; i<MAX_PICTURE_COUNT; i++){ free_picture(s, &s->picture[i]); } } av_freep(&s->picture); s->context_initialized = 0; s->last_picture_ptr= s->next_picture_ptr= s->current_picture_ptr= NULL; s->linesize= s->uvlinesize= 0; for(i=0; i<3; i++) av_freep(&s->visualization_buffer[i]); avcodec_default_free_buffers(s->avctx); } #ifdef CONFIG_ENCODERS /* init video encoder */ int MPV_encode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; int i; int chroma_h_shift, chroma_v_shift; MPV_encode_defaults(s); if(avctx->pix_fmt != PIX_FMT_YUVJ420P && avctx->pix_fmt != PIX_FMT_YUV420P){ av_log(avctx, AV_LOG_ERROR, "only YUV420 is supportedn"); return -1; } if(avctx->codec_id == CODEC_ID_MJPEG || avctx->codec_id == CODEC_ID_LJPEG){ if(avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL && avctx->pix_fmt != PIX_FMT_YUVJ420P){ av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpegn"); return -1; } }else{ if(avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL && avctx->pix_fmt != PIX_FMT_YUV420P){ av_log(avctx, AV_LOG_ERROR, "colorspace not supportedn"); return -1; } } s->bit_rate = avctx->bit_rate; s->width = avctx->width; s->height = avctx->height; if(avctx->gop_size > 600){ av_log(avctx, AV_LOG_ERROR, "Warning keyframe interval too large! reducing it ...n"); avctx->gop_size=600; } s->gop_size = avctx->gop_size; s->avctx = avctx; s->flags= avctx->flags; s->flags2= avctx->flags2; s->max_b_frames= avctx->max_b_frames; s->codec_id= avctx->codec->id; s->luma_elim_threshold = avctx->luma_elim_threshold; s->chroma_elim_threshold= avctx->chroma_elim_threshold; s->strict_std_compliance= avctx->strict_std_compliance; s->data_partitioning= avctx->flags & CODEC_FLAG_PART; s->quarter_sample= (avctx->flags & CODEC_FLAG_QPEL)!=0; s->mpeg_quant= avctx->mpeg_quant; s->rtp_mode= !!avctx->rtp_payload_size; s->intra_dc_precision= avctx->intra_dc_precision; s->user_specified_pts = AV_NOPTS_VALUE; if (s->gop_size <= 1) { s->intra_only = 1; s->gop_size = 12; } else { s->intra_only = 0; } s->me_method = avctx->me_method; /* Fixed QSCALE */ s->fixed_qscale = !!(avctx->flags & CODEC_FLAG_QSCALE); s->adaptive_quant= ( s->avctx->lumi_masking || s->avctx->dark_masking || s->avctx->temporal_cplx_masking || s->avctx->spatial_cplx_masking || s->avctx->p_masking || s->avctx->border_masking || (s->flags&CODEC_FLAG_QP_RD)) && !s->fixed_qscale; s->obmc= !!(s->flags & CODEC_FLAG_OBMC); s->loop_filter= !!(s->flags & CODEC_FLAG_LOOP_FILTER); s->alternate_scan= !!(s->flags & CODEC_FLAG_ALT_SCAN); if(avctx->rc_max_rate && !avctx->rc_buffer_size){ av_log(avctx, AV_LOG_ERROR, "a vbv buffer size is needed, for encoding with a maximum bitraten"); return -1; } if(avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate){ av_log(avctx, AV_LOG_INFO, "Warning min_rate > 0 but min_rate != max_rate isn't recommended!n"); } if(avctx->rc_min_rate && avctx->rc_min_rate > avctx->bit_rate){ av_log(avctx, AV_LOG_INFO, "bitrate below min bitraten"); return -1; } if(avctx->rc_max_rate && avctx->rc_max_rate < avctx->bit_rate){ av_log(avctx, AV_LOG_INFO, "bitrate above max bitraten"); return -1; } if( s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate && (s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO) && 90000LL * (avctx->rc_buffer_size-1) > s->avctx->rc_max_rate*0xFFFFLL){ av_log(avctx, AV_LOG_INFO, "Warning vbv_delay will be set to 0xFFFF (=VBR) as the specified vbv buffer is too large for the given bitrate!n"); } if((s->flags & CODEC_FLAG_4MV) && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P && s->codec_id != CODEC_ID_FLV1){ av_log(avctx, AV_LOG_ERROR, "4MV not supported by codecn"); return -1; } if(s->obmc && s->avctx->mb_decision != FF_MB_DECISION_SIMPLE){ av_log(avctx, AV_LOG_ERROR, "OBMC is only supported with simple mb decisionn"); return -1; } if(s->obmc && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P){ av_log(avctx, AV_LOG_ERROR, "OBMC is only supported with H263(+)n"); return -1; } if(s->quarter_sample && s->codec_id != CODEC_ID_MPEG4){ av_log(avctx, AV_LOG_ERROR, "qpel not supported by codecn"); return -1; } if(s->data_partitioning && s->codec_id != CODEC_ID_MPEG4){ av_log(avctx, AV_LOG_ERROR, "data partitioning not supported by codecn"); return -1; } if(s->max_b_frames && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_MPEG1VIDEO && s->codec_id != CODEC_ID_MPEG2VIDEO){ av_log(avctx, AV_LOG_ERROR, "b frames not supported by codecn"); return -1; } if((s->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME|CODEC_FLAG_ALT_SCAN)) && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_MPEG2VIDEO){ av_log(avctx, AV_LOG_ERROR, "interlacing not supported by codecn"); return -1; } if(s->mpeg_quant && s->codec_id != CODEC_ID_MPEG4){ //FIXME mpeg2 uses that too av_log(avctx, AV_LOG_ERROR, "mpeg2 style quantization not supported by codecn"); return -1; } if((s->flags & CODEC_FLAG_CBP_RD) && !(s->flags & CODEC_FLAG_TRELLIS_QUANT)){ av_log(avctx, AV_LOG_ERROR, "CBP RD needs trellis quantn"); return -1; } if((s->flags & CODEC_FLAG_QP_RD) && s->avctx->mb_decision != FF_MB_DECISION_RD){ av_log(avctx, AV_LOG_ERROR, "QP RD needs mbd=2n"); return -1; } if(s->avctx->scenechange_threshold < 1000000000 && (s->flags & CODEC_FLAG_CLOSED_GOP)){ av_log(avctx, AV_LOG_ERROR, "closed gop with scene change detection arent supported yetn"); return -1; } if(s->avctx->thread_count > 1 && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_MPEG1VIDEO && s->codec_id != CODEC_ID_MPEG2VIDEO && (s->codec_id != CODEC_ID_H263P || !(s->flags & CODEC_FLAG_H263P_SLICE_STRUCT))){ av_log(avctx, AV_LOG_ERROR, "multi threaded encoding not supported by codecn"); return -1; } if(s->avctx->thread_count > 1) s->rtp_mode= 1; if(!avctx->time_base.den || !avctx->time_base.num){ av_log(avctx, AV_LOG_ERROR, "framerate not setn"); return -1; } i= (INT_MAX/2+128)>>8; if(avctx->me_threshold >= i){ av_log(avctx, AV_LOG_ERROR, "me_threshold too large, max is %dn", i - 1); return -1; } if(avctx->mb_threshold >= i){ av_log(avctx, AV_LOG_ERROR, "mb_threshold too large, max is %dn", i - 1); return -1; } if(avctx->b_frame_strategy && (avctx->flags&CODEC_FLAG_PASS2)){ av_log(avctx, AV_LOG_ERROR, "b_frame_strategy must be 0 on the second pass"); return -1; } i= ff_gcd(avctx->time_base.den, avctx->time_base.num); if(i > 1){ av_log(avctx, AV_LOG_INFO, "removing common factors from frameraten"); avctx->time_base.den /= i; avctx->time_base.num /= i; // return -1; } if(s->codec_id==CODEC_ID_MJPEG){ s->intra_quant_bias= 1<<(QUANT_BIAS_SHIFT-1); //(a + x/2)/x s->inter_quant_bias= 0; }else if(s->mpeg_quant || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO){ s->intra_quant_bias= 3<<(QUANT_BIAS_SHIFT-3); //(a + x*3/8)/x s->inter_quant_bias= 0; }else{ s->intra_quant_bias=0; s->inter_quant_bias=-(1<<(QUANT_BIAS_SHIFT-2)); //(a - x/4)/x } if(avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) s->intra_quant_bias= avctx->intra_quant_bias; if(avctx->inter_quant_bias != FF_DEFAULT_QUANT_BIAS) s->inter_quant_bias= avctx->inter_quant_bias; avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, &chroma_v_shift); if(avctx->codec_id == CODEC_ID_MPEG4 && s->avctx->time_base.den > (1<<16)-1){ av_log(avctx, AV_LOG_ERROR, "timebase not supported by mpeg 4 standardn"); return -1; } s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1; switch(avctx->codec->id) { case CODEC_ID_MPEG1VIDEO: s->out_format = FMT_MPEG1; s->low_delay= 0; //s->max_b_frames ? 0 : 1; avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); break; case CODEC_ID_MPEG2VIDEO: s->out_format = FMT_MPEG1; s->low_delay= 0; //s->max_b_frames ? 0 : 1; avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); s->rtp_mode= 1; break; case CODEC_ID_LJPEG: case CODEC_ID_MJPEG: s->out_format = FMT_MJPEG; s->intra_only = 1; /* force intra only for jpeg */ s->mjpeg_write_tables = 1; /* write all tables */ s->mjpeg_data_only_frames = 0; /* write all the needed headers */ s->mjpeg_vsample[0] = 1<<chroma_v_shift; s->mjpeg_vsample[1] = 1; s->mjpeg_vsample[2] = 1; s->mjpeg_hsample[0] = 1<<chroma_h_shift; s->mjpeg_hsample[1] = 1; s->mjpeg_hsample[2] = 1; if (mjpeg_init(s) < 0) return -1; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_H261: s->out_format = FMT_H261; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_H263: if (h263_get_picture_format(s->width, s->height) == 7) { av_log(avctx, AV_LOG_INFO, "Input picture size isn't suitable for h263 codec! try h263+n"); return -1; } s->out_format = FMT_H263; s->obmc= (avctx->flags & CODEC_FLAG_OBMC) ? 1:0; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_H263P: s->out_format = FMT_H263; s->h263_plus = 1; /* Fx */ s->umvplus = (avctx->flags & CODEC_FLAG_H263P_UMV) ? 1:0; s->h263_aic= (avctx->flags & CODEC_FLAG_H263P_AIC) ? 1:0; s->modified_quant= s->h263_aic; s->alt_inter_vlc= (avctx->flags & CODEC_FLAG_H263P_AIV) ? 1:0; s->obmc= (avctx->flags & CODEC_FLAG_OBMC) ? 1:0; s->loop_filter= (avctx->flags & CODEC_FLAG_LOOP_FILTER) ? 1:0; s->unrestricted_mv= s->obmc || s->loop_filter || s->umvplus; s->h263_slice_structured= (s->flags & CODEC_FLAG_H263P_SLICE_STRUCT) ? 1:0; /* /Fx */ /* These are just to be sure */ avctx->delay=0; s->low_delay=1; break; case CODEC_ID_FLV1: s->out_format = FMT_H263; s->h263_flv = 2; /* format = 1; 11-bit codes */ s->unrestricted_mv = 1; s->rtp_mode=0; /* don't allow GOB */ avctx->delay=0; s->low_delay=1; break; case CODEC_ID_RV10: s->out_format = FMT_H263; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_RV20: s->out_format = FMT_H263; avctx->delay=0; s->low_delay=1; s->modified_quant=1; s->h263_aic=1; s->h263_plus=1; s->loop_filter=1; s->unrestricted_mv= s->obmc || s->loop_filter || s->umvplus; break; case CODEC_ID_MPEG4: s->out_format = FMT_H263; s->h263_pred = 1; s->unrestricted_mv = 1; s->low_delay= s->max_b_frames ? 0 : 1; avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); break; case CODEC_ID_MSMPEG4V1: s->out_format = FMT_H263; s->h263_msmpeg4 = 1; s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 1; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_MSMPEG4V2: s->out_format = FMT_H263; s->h263_msmpeg4 = 1; s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 2; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_MSMPEG4V3: s->out_format = FMT_H263; s->h263_msmpeg4 = 1; s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 3; s->flipflop_rounding=1; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_WMV1: s->out_format = FMT_H263; s->h263_msmpeg4 = 1; s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 4; s->flipflop_rounding=1; avctx->delay=0; s->low_delay=1; break; case CODEC_ID_WMV2: s->out_format = FMT_H263; s->h263_msmpeg4 = 1; s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 5; s->flipflop_rounding=1; avctx->delay=0; s->low_delay=1; break; default: return -1; } avctx->has_b_frames= !s->low_delay; s->encoding = 1; /* init */ if (MPV_common_init(s) < 0) return -1; if(s->modified_quant) s->chroma_qscale_table= ff_h263_chroma_qscale_table; s->progressive_frame= s->progressive_sequence= !(avctx->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)); s->quant_precision=5; ff_set_cmp(&s->dsp, s->dsp.ildct_cmp, s->avctx->ildct_cmp); ff_set_cmp(&s->dsp, s->dsp.frame_skip_cmp, s->avctx->frame_skip_cmp); #ifdef CONFIG_H261_ENCODER if (s->out_format == FMT_H261) ff_h261_encode_init(s); #endif if (s->out_format == FMT_H263) h263_encode_init(s); if(s->msmpeg4_version) ff_msmpeg4_encode_init(s); if (s->out_format == FMT_MPEG1) ff_mpeg1_encode_init(s); /* init q matrix */ for(i=0;i<64;i++) { int j= s->dsp.idct_permutation[i]; if(s->codec_id==CODEC_ID_MPEG4 && s->mpeg_quant){ s->intra_matrix[j] = ff_mpeg4_default_intra_matrix[i]; s->inter_matrix[j] = ff_mpeg4_default_non_intra_matrix[i]; }else if(s->out_format == FMT_H263 || s->out_format == FMT_H261){ s->intra_matrix[j] = s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; }else { /* mpeg1/2 */ s->intra_matrix[j] = ff_mpeg1_default_intra_matrix[i]; s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; } if(s->avctx->intra_matrix) s->intra_matrix[j] = s->avctx->intra_matrix[i]; if(s->avctx->inter_matrix) s->inter_matrix[j] = s->avctx->inter_matrix[i]; } /* precompute matrix */ /* for mjpeg, we do include qscale in the matrix */ if (s->out_format != FMT_MJPEG) { convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->intra_quant_bias, avctx->qmin, 31, 1); convert_matrix(&s->dsp, s->q_inter_matrix, s->q_inter_matrix16, s->inter_matrix, s->inter_quant_bias, avctx->qmin, 31, 0); } if(ff_rate_control_init(s) < 0) return -1; return 0; } int MPV_encode_end(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; #ifdef STATS print_stats(); #endif ff_rate_control_uninit(s); MPV_common_end(s); if (s->out_format == FMT_MJPEG) mjpeg_close(s); av_freep(&avctx->extradata); return 0; } #endif //CONFIG_ENCODERS void init_rl(RLTable *rl, int use_static) { int8_t max_level[MAX_RUN+1], max_run[MAX_LEVEL+1]; uint8_t index_run[MAX_RUN+1]; int last, run, level, start, end, i; /* If table is static, we can quit if rl->max_level[0] is not NULL */ if(use_static && rl->max_level[0]) return; /* compute max_level[], max_run[] and index_run[] */ for(last=0;last<2;last++) { if (last == 0) { start = 0; end = rl->last; } else { start = rl->last; end = rl->n; } memset(max_level, 0, MAX_RUN + 1); memset(max_run, 0, MAX_LEVEL + 1); memset(index_run, rl->n, MAX_RUN + 1); for(i=start;i<end;i++) { run = rl->table_run[i]; level = rl->table_level[i]; if (index_run[run] == rl->n) index_run[run] = i; if (level > max_level[run]) max_level[run] = level; if (run > max_run[level]) max_run[level] = run; } if(use_static) rl->max_level[last] = av_mallocz_static(MAX_RUN + 1); else rl->max_level[last] = av_malloc(MAX_RUN + 1); memcpy(rl->max_level[last], max_level, MAX_RUN + 1); if(use_static) rl->max_run[last] = av_mallocz_static(MAX_LEVEL + 1); else rl->max_run[last] = av_malloc(MAX_LEVEL + 1); memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); if(use_static) rl->index_run[last] = av_mallocz_static(MAX_RUN + 1); else rl->index_run[last] = av_malloc(MAX_RUN + 1); memcpy(rl->index_run[last], index_run, MAX_RUN + 1); } } /* draw the edges of width 'w' of an image of size width, height */ //FIXME check that this is ok for mpeg4 interlaced static void draw_edges_c(uint8_t *buf, int wrap, int width, int height, int w) { uint8_t *ptr, *last_line; int i; last_line = buf + (height - 1) * wrap; for(i=0;i<w;i++) { /* top and bottom */ memcpy(buf - (i + 1) * wrap, buf, width); memcpy(last_line + (i + 1) * wrap, last_line, width); } /* left and right */ ptr = buf; for(i=0;i<height;i++) { memset(ptr - w, ptr[0], w); memset(ptr + width, ptr[width-1], w); ptr += wrap; } /* corners */ for(i=0;i<w;i++) { memset(buf - (i + 1) * wrap - w, buf[0], w); /* top left */ memset(buf - (i + 1) * wrap + width, buf[width-1], w); /* top right */ memset(last_line + (i + 1) * wrap - w, last_line[0], w); /* top left */ memset(last_line + (i + 1) * wrap + width, last_line[width-1], w); /* top right */ } } int ff_find_unused_picture(MpegEncContext *s, int shared){ int i; if(shared){ for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0]==NULL && s->picture[i].type==0) return i; } }else{ for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0]==NULL && s->picture[i].type!=0) return i; //FIXME } for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0]==NULL) return i; } } assert(0); return -1; } static void update_noise_reduction(MpegEncContext *s){ int intra, i; for(intra=0; intra<2; intra++){ if(s->dct_count[intra] > (1<<16)){ for(i=0; i<64; i++){ s->dct_error_sum[intra][i] >>=1; } s->dct_count[intra] >>= 1; } for(i=0; i<64; i++){ s->dct_offset[intra][i]= (s->avctx->noise_reduction * s->dct_count[intra] + s->dct_error_sum[intra][i]/2) / (s->dct_error_sum[intra][i]+1); } } } /** * generic function for encode/decode called after coding/decoding the header and before a frame is coded/decoded */ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) { int i; AVFrame *pic; s->mb_skipped = 0; assert(s->last_picture_ptr==NULL || s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3); /* mark&release old frames */ if (s->pict_type != B_TYPE && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->data[0]) { avctx->release_buffer(avctx, (AVFrame*)s->last_picture_ptr); /* release forgotten pictures */ /* if(mpeg124/h263) */ if(!s->encoding){ for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].reference){ av_log(avctx, AV_LOG_ERROR, "releasing zombie picturen"); avctx->release_buffer(avctx, (AVFrame*)&s->picture[i]); } } } } alloc: if(!s->encoding){ /* release non reference frames */ for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){ s->avctx->release_buffer(s->avctx, (AVFrame*)&s->picture[i]); } } if(s->current_picture_ptr && s->current_picture_ptr->data[0]==NULL) pic= (AVFrame*)s->current_picture_ptr; //we allready have a unused image (maybe it was set before reading the header) else{ i= ff_find_unused_picture(s, 0); pic= (AVFrame*)&s->picture[i]; } pic->reference= (s->pict_type != B_TYPE || s->codec_id == CODEC_ID_H264) && !s->dropable ? 3 : 0; pic->coded_picture_number= s->coded_picture_number++; if( alloc_picture(s, (Picture*)pic, 0) < 0) return -1; s->current_picture_ptr= (Picture*)pic; s->current_picture_ptr->top_field_first= s->top_field_first; //FIXME use only the vars from current_pic s->current_picture_ptr->interlaced_frame= !s->progressive_frame && !s->progressive_sequence; } s->current_picture_ptr->pict_type= s->pict_type; // if(s->flags && CODEC_FLAG_QSCALE) // s->current_picture_ptr->quality= s->new_picture_ptr->quality; s->current_picture_ptr->key_frame= s->pict_type == I_TYPE; copy_picture(&s->current_picture, s->current_picture_ptr); if(s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3){ if (s->pict_type != B_TYPE) { s->last_picture_ptr= s->next_picture_ptr; if(!s->dropable) s->next_picture_ptr= s->current_picture_ptr; } /* av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%dn", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, s->last_picture_ptr ? s->last_picture_ptr->data[0] : NULL, s->next_picture_ptr ? s->next_picture_ptr->data[0] : NULL, s->current_picture_ptr ? s->current_picture_ptr->data[0] : NULL, s->pict_type, s->dropable);*/ if(s->last_picture_ptr) copy_picture(&s->last_picture, s->last_picture_ptr); if(s->next_picture_ptr) copy_picture(&s->next_picture, s->next_picture_ptr); if(s->pict_type != I_TYPE && (s->last_picture_ptr==NULL || s->last_picture_ptr->data[0]==NULL)){ av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframen"); assert(s->pict_type != B_TYPE); //these should have been dropped if we don't have a reference goto alloc; } assert(s->pict_type == I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->data[0])); if(s->picture_structure!=PICT_FRAME){ int i; for(i=0; i<4; i++){ if(s->picture_structure == PICT_BOTTOM_FIELD){ s->current_picture.data[i] += s->current_picture.linesize[i]; } s->current_picture.linesize[i] *= 2; s->last_picture.linesize[i] *=2; s->next_picture.linesize[i] *=2; } } } s->hurry_up= s->avctx->hurry_up; s->error_resilience= avctx->error_resilience; /* set dequantizer, we can't do it during init as it might change for mpeg4 and we can't do it in the header decode as init isnt called for mpeg4 there yet */ if(s->mpeg_quant || s->codec_id == CODEC_ID_MPEG2VIDEO){ s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; }else if(s->out_format == FMT_H263 || s->out_format == FMT_H261){ s->dct_unquantize_intra = s->dct_unquantize_h263_intra; s->dct_unquantize_inter = s->dct_unquantize_h263_inter; }else{ s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra; s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; } if(s->dct_error_sum){ assert(s->avctx->noise_reduction && s->encoding); update_noise_reduction(s); } #ifdef HAVE_XVMC if(s->avctx->xvmc_acceleration) return XVMC_field_start(s, avctx); #endif return 0; } /* generic function for encode/decode called after a frame has been coded/decoded */ void MPV_frame_end(MpegEncContext *s) { int i; /* draw edge for correct motion prediction if outside */ #ifdef HAVE_XVMC //just to make sure that all data is rendered. if(s->avctx->xvmc_acceleration){ XVMC_field_end(s); }else #endif if(s->unrestricted_mv && s->current_picture.reference && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) { draw_edges(s->current_picture.data[0], s->linesize , s->h_edge_pos , s->v_edge_pos , EDGE_WIDTH ); draw_edges(s->current_picture.data[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); draw_edges(s->current_picture.data[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); } emms_c(); s->last_pict_type = s->pict_type; if(s->pict_type!=B_TYPE){ s->last_non_b_pict_type= s->pict_type; } #if 0 /* copy back current_picture variables */ for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0] == s->current_picture.data[0]){ s->picture[i]= s->current_picture; break; } } assert(i<MAX_PICTURE_COUNT); #endif if(s->encoding){ /* release non-reference frames */ for(i=0; i<MAX_PICTURE_COUNT; i++){ if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){ s->avctx->release_buffer(s->avctx, (AVFrame*)&s->picture[i]); } } } // clear copies, to avoid confusion #if 0 memset(&s->last_picture, 0, sizeof(Picture)); memset(&s->next_picture, 0, sizeof(Picture)); memset(&s->current_picture, 0, sizeof(Picture)); #endif s->avctx->coded_frame= (AVFrame*)s->current_picture_ptr; } /** * draws an line from (ex, ey) -> (sx, sy). * @param w width of the image * @param h height of the image * @param stride stride/linesize of the image * @param color color of the arrow */ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int stride, int color){ int t, x, y, fr, f; sx= clip(sx, 0, w-1); sy= clip(sy, 0, h-1); ex= clip(ex, 0, w-1); ey= clip(ey, 0, h-1); buf[sy*stride + sx]+= color; if(ABS(ex - sx) > ABS(ey - sy)){ if(sx > ex){ t=sx; sx=ex; ex=t; t=sy; sy=ey; ey=t; } buf+= sx + sy*stride; ex-= sx; f= ((ey-sy)<<16)/ex; for(x= 0; x <= ex; x++){ y = (x*f)>>16; fr= (x*f)&0xFFFF; buf[ y *stride + x]+= (color*(0x10000-fr))>>16; buf[(y+1)*stride + x]+= (color* fr )>>16; } }else{ if(sy > ey){ t=sx; sx=ex; ex=t; t=sy; sy=ey; ey=t; } buf+= sx + sy*stride; ey-= sy; if(ey) f= ((ex-sx)<<16)/ey; else f= 0; for(y= 0; y <= ey; y++){ x = (y*f)>>16; fr= (y*f)&0xFFFF; buf[y*stride + x ]+= (color*(0x10000-fr))>>16;; buf[y*stride + x+1]+= (color* fr )>>16;; } } } /** * draws an arrow from (ex, ey) -> (sx, sy). * @param w width of the image * @param h height of the image * @param stride stride/linesize of the image * @param color color of the arrow */ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int stride, int color){ int dx,dy; sx= clip(sx, -100, w+100); sy= clip(sy, -100, h+100); ex= clip(ex, -100, w+100); ey= clip(ey, -100, h+100); dx= ex - sx; dy= ey - sy; if(dx*dx + dy*dy > 3*3){ int rx= dx + dy; int ry= -dx + dy; int length= ff_sqrt((rx*rx + ry*ry)<<8); //FIXME subpixel accuracy rx= ROUNDED_DIV(rx*3<<4, length); ry= ROUNDED_DIV(ry*3<<4, length); draw_line(buf, sx, sy, sx + rx, sy + ry, w, h, stride, color); draw_line(buf, sx, sy, sx - ry, sy + rx, w, h, stride, color); } draw_line(buf, sx, sy, ex, ey, w, h, stride, color); } #if 0 //Picard
- /** * prints debuging info for the given picture. */ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){ if(!pict || !pict->mb_type) return; if(s->avctx->debug&(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)){ int x,y; av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: "); switch (pict->pict_type) { case FF_I_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"In"); break; case FF_P_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"Pn"); break; case FF_B_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"Bn"); break; case FF_S_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"Sn"); break; case FF_SI_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SIn"); break; case FF_SP_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SPn"); break; } for(y=0; y<s->mb_height; y++){ for(x=0; x<s->mb_width; x++){ if(s->avctx->debug&FF_DEBUG_SKIP){ int count= s->mbskip_table[x + y*s->mb_stride]; if(count>9) count=9; av_log(s->avctx, AV_LOG_DEBUG, "%1d", count); } if(s->avctx->debug&FF_DEBUG_QP){ av_log(s->avctx, AV_LOG_DEBUG, "%2d", pict->qscale_table[x + y*s->mb_stride]); } if(s->avctx->debug&FF_DEBUG_MB_TYPE){ int mb_type= pict->mb_type[x + y*s->mb_stride]; //Type & MV direction if(IS_PCM(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "P"); else if(IS_INTRA(mb_type) && IS_ACPRED(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "A"); else if(IS_INTRA4x4(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "i"); else if(IS_INTRA16x16(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "I"); else if(IS_DIRECT(mb_type) && IS_SKIP(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "d"); else if(IS_DIRECT(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "D"); else if(IS_GMC(mb_type) && IS_SKIP(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "g"); else if(IS_GMC(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "G"); else if(IS_SKIP(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "S"); else if(!USES_LIST(mb_type, 1)) av_log(s->avctx, AV_LOG_DEBUG, ">"); else if(!USES_LIST(mb_type, 0)) av_log(s->avctx, AV_LOG_DEBUG, "<"); else{ assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); av_log(s->avctx, AV_LOG_DEBUG, "X"); } //segmentation if(IS_8X8(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "+"); else if(IS_16X8(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "-"); else if(IS_8X16(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, "|"); else if(IS_INTRA(mb_type) || IS_16X16(mb_type)) av_log(s->avctx, AV_LOG_DEBUG, " "); else av_log(s->avctx, AV_LOG_DEBUG, "?"); if(IS_INTERLACED(mb_type) && s->codec_id == CODEC_ID_H264) av_log(s->avctx, AV_LOG_DEBUG, "="); else av_log(s->avctx, AV_LOG_DEBUG, " "); } // av_log(s->avctx, AV_LOG_DEBUG, " "); } av_log(s->avctx, AV_LOG_DEBUG, "n"); } } if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){ const int shift= 1 + s->quarter_sample; int mb_y; uint8_t *ptr; int i; int h_chroma_shift, v_chroma_shift; const int width = s->avctx->width; const int height= s->avctx->height; const int mv_sample_log2= 4 - pict->motion_subsample_log2; const int mv_stride= (s->mb_width << mv_sample_log2) + 1; s->low_delay=0; //needed to see the vectors without trashing the buffers avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); for(i=0; i<3; i++){ memcpy(s->visualization_buffer[i], pict->data[i], (i==0) ? pict->linesize[i]*height:pict->linesize[i]*height >> v_chroma_shift); pict->data[i]= s->visualization_buffer[i]; } pict->type= FF_BUFFER_TYPE_COPY; ptr= pict->data[0]; for(mb_y=0; mb_y<s->mb_height; mb_y++){ int mb_x; for(mb_x=0; mb_x<s->mb_width; mb_x++){ const int mb_index= mb_x + mb_y*s->mb_stride; if((s->avctx->debug_mv) && pict->motion_val){ int type; for(type=0; type<3; type++){ int direction = 0; switch (type) { case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=FF_P_TYPE)) continue; direction = 0; break; case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=FF_B_TYPE)) continue; direction = 0; break; case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=FF_B_TYPE)) continue; direction = 1; break; } if(!USES_LIST(pict->mb_type[mb_index], direction)) continue; if(IS_8X8(pict->mb_type[mb_index])){ int i; for(i=0; i<4; i++){ int sx= mb_x*16 + 4 + 8*(i&1); int sy= mb_y*16 + 4 + 8*(i>>1); int xy= (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride) << (mv_sample_log2-1); int mx= (pict->motion_val[direction][xy][0]>>shift) + sx; int my= (pict->motion_val[direction][xy][1]>>shift) + sy; draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100); } }else if(IS_16X8(pict->mb_type[mb_index])){ int i; for(i=0; i<2; i++){ int sx=mb_x*16 + 8; int sy=mb_y*16 + 4 + 8*i; int xy= (mb_x*2 + (mb_y*2 + i)*mv_stride) << (mv_sample_log2-1); int mx=(pict->motion_val[direction][xy][0]>>shift); int my=(pict->motion_val[direction][xy][1]>>shift); if(IS_INTERLACED(pict->mb_type[mb_index])) my*=2; draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100); } }else if(IS_8X16(pict->mb_type[mb_index])){ int i; for(i=0; i<2; i++){ int sx=mb_x*16 + 4 + 8*i; int sy=mb_y*16 + 8; int xy= (mb_x*2 + i + mb_y*2*mv_stride) << (mv_sample_log2-1); int mx=(pict->motion_val[direction][xy][0]>>shift); int my=(pict->motion_val[direction][xy][1]>>shift); if(IS_INTERLACED(pict->mb_type[mb_index])) my*=2; draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100); } }else{ int sx= mb_x*16 + 8; int sy= mb_y*16 + 8; int xy= (mb_x + mb_y*mv_stride) << mv_sample_log2; int mx= (pict->motion_val[direction][xy][0]>>shift) + sx; int my= (pict->motion_val[direction][xy][1]>>shift) + sy; draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100); } } } if((s->avctx->debug&FF_DEBUG_VIS_QP) && pict->motion_val){ uint64_t c= (pict->qscale_table[mb_index]*128/31) * 0x0101010101010101ULL; int y; for(y=0; y<8; y++){ *(uint64_t*)(pict->data[1] + 8*mb_x + (8*mb_y + y)*pict->linesize[1])= c; *(uint64_t*)(pict->data[2] + 8*mb_x + (8*mb_y + y)*pict->linesize[2])= c; } } if((s->avctx->debug&FF_DEBUG_VIS_MB_TYPE) && pict->motion_val){ int mb_type= pict->mb_type[mb_index]; uint64_t u,v; int y; #define COLOR(theta, r) u= (int)(128 + r*cos(theta*3.141592/180)); v= (int)(128 + r*sin(theta*3.141592/180)); u=v=128; if(IS_PCM(mb_type)){ COLOR(120,48) }else if((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || IS_INTRA16x16(mb_type)){ COLOR(30,48) }else if(IS_INTRA4x4(mb_type)){ COLOR(90,48) }else if(IS_DIRECT(mb_type) && IS_SKIP(mb_type)){ // COLOR(120,48) }else if(IS_DIRECT(mb_type)){ COLOR(150,48) }else if(IS_GMC(mb_type) && IS_SKIP(mb_type)){ COLOR(170,48) }else if(IS_GMC(mb_type)){ COLOR(190,48) }else if(IS_SKIP(mb_type)){ // COLOR(180,48) }else if(!USES_LIST(mb_type, 1)){ COLOR(240,48) }else if(!USES_LIST(mb_type, 0)){ COLOR(0,48) }else{ assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); COLOR(300,48) } u*= 0x0101010101010101ULL; v*= 0x0101010101010101ULL; for(y=0; y<8; y++){ *(uint64_t*)(pict->data[1] + 8*mb_x + (8*mb_y + y)*pict->linesize[1])= u; *(uint64_t*)(pict->data[2] + 8*mb_x + (8*mb_y + y)*pict->linesize[2])= v; } //segmentation if(IS_8X8(mb_type) || IS_16X8(mb_type)){ *(uint64_t*)(pict->data[0] + 16*mb_x + 0 + (16*mb_y + 8)*pict->linesize[0])^= 0x8080808080808080ULL; *(uint64_t*)(pict->data[0] + 16*mb_x + 8 + (16*mb_y + 8)*pict->linesize[0])^= 0x8080808080808080ULL; } if(IS_8X8(mb_type) || IS_8X16(mb_type)){ for(y=0; y<16; y++) pict->data[0][16*mb_x + 8 + (16*mb_y + y)*pict->linesize[0]]^= 0x80; } if(IS_8X8(mb_type) && mv_sample_log2 >= 2){ int dm= 1 << (mv_sample_log2-2); for(i=0; i<4; i++){ int sx= mb_x*16 + 8*(i&1); int sy= mb_y*16 + 8*(i>>1); int xy= (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride) << (mv_sample_log2-1); //FIXME bidir int32_t *mv = (int32_t*)&pict->motion_val[0][xy]; if(mv[0] != mv[dm] || mv[dm*mv_stride] != mv[dm*(mv_stride+1)]) for(y=0; y<8; y++) pict->data[0][sx + 4 + (sy + y)*pict->linesize[0]]^= 0x80; if(mv[0] != mv[dm*mv_stride] || mv[dm] != mv[dm*(mv_stride+1)]) *(uint64_t*)(pict->data[0] + sx + (sy + 4)*pict->linesize[0])^= 0x8080808080808080ULL; } } if(IS_INTERLACED(mb_type) && s->codec_id == CODEC_ID_H264){ // hmm } } s->mbskip_table[mb_index]=0; } } } } #else
- void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
- {