From 4e00e76b3cf20eff69d8c86a5376bf0a12d3f6d4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 9 Dec 2002 00:29:17 +0000 Subject: [PATCH] cleanup / messup? fixes 20% speedloss bug removes redundant variables from MpegEncContext release buffers in avcodec_flush_buffers() (untested) Originally committed as revision 1325 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/avcodec.h | 19 ++- libavcodec/h263dec.c | 16 +-- libavcodec/mpeg12.c | 4 +- libavcodec/mpegvideo.c | 301 ++++++++++++++++++++++++++--------------- libavcodec/mpegvideo.h | 2 - libavcodec/svq1.c | 2 +- libavcodec/utils.c | 41 +++++- 7 files changed, 251 insertions(+), 134 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0dd560e36c..d02c3e7211 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5,8 +5,8 @@ #define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION "0.4.6" -#define LIBAVCODEC_BUILD 4643 -#define LIBAVCODEC_BUILD_STR "4643" +#define LIBAVCODEC_BUILD 4644 +#define LIBAVCODEC_BUILD_STR "4644" enum CodecID { CODEC_ID_NONE, @@ -119,7 +119,7 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, ME_X1, ME_EPZS, ME_FULL }; -#define FF_MAX_B_FRAMES 4 +#define FF_MAX_B_FRAMES 8 /* encoding support these flags can be passed in AVCodecContext.flags before initing @@ -260,6 +260,19 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, * decoding: unused\ */\ uint64_t error[4];\ +\ + /**\ + * type of the buffer (to keep track of who has to dealloc data[*])\ + * encoding: set by the one who allocs it\ + * decoding: set by the one who allocs it\ + * Note: user allocated (direct rendering) & internal buffers can not coexist currently\ + */\ + int type;\ + +#define FF_BUFFER_TYPE_INTERNAL 1 +#define FF_BUFFER_TYPE_USER 2 // Direct rendering buffers +#define FF_BUFFER_TYPE_SHARED 4 // input frame for encoding(wont be dealloced) + #define FF_I_TYPE 1 // Intra #define FF_P_TYPE 2 // Predicted diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 2ac68060f9..cf90a95714 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -55,6 +55,7 @@ static int h263_decode_init(AVCodecContext *avctx) s->quant_precision=5; s->progressive_sequence=1; s->decode_mb= ff_h263_decode_mb; + s->low_delay= 1; /* select sub codec */ switch(avctx->codec->id) { @@ -64,7 +65,7 @@ static int h263_decode_init(AVCodecContext *avctx) case CODEC_ID_MPEG4: s->time_increment_bits = 4; /* default value for broken headers */ s->h263_pred = 1; - s->has_b_frames = 1; //default, might be overriden in the vol header during header parsing + s->low_delay = 0; //default, might be overriden in the vol header during header parsing break; case CODEC_ID_MSMPEG4V1: s->h263_msmpeg4 = 1; @@ -430,14 +431,12 @@ retry: if(s->flags& CODEC_FLAG_LOW_DELAY) s->low_delay=1; - - s->has_b_frames= !s->low_delay; } else if (s->h263_intel) { ret = intel_h263_decode_picture_header(s); } else { ret = h263_decode_picture_header(s); } - avctx->has_b_frames= s->has_b_frames; + avctx->has_b_frames= !s->low_delay; if(s->workaround_bugs&FF_BUG_AUTODETECT){ if(s->avctx->fourcc == ff_get_fourcc("XVIX")) @@ -531,7 +530,7 @@ retry: s->current_picture.key_frame= s->pict_type == I_TYPE; /* skip b frames if we dont have reference frames */ - if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size); + if(s->last_picture.data[0]==NULL && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size); /* skip b frames if we are in a hurry */ if(avctx->hurry_up && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size); /* skip everything if we are in a hurry>=5 */ @@ -676,7 +675,7 @@ retry: } #endif - if(s->pict_type==B_TYPE || (!s->has_b_frames)){ + if(s->pict_type==B_TYPE || s->low_delay){ *pict= *(AVVideoFrame*)&s->current_picture; } else { *pict= *(AVVideoFrame*)&s->last_picture; @@ -686,9 +685,8 @@ retry: /* we substract 1 because it is added on utils.c */ avctx->frame_number = s->picture_number - 1; - /* dont output the last pic after seeking - note we allready added +1 for the current pix in MPV_frame_end(s) */ - if(s->num_available_buffers>=2 || (!s->has_b_frames)) + /* dont output the last pic after seeking */ + if(s->last_picture.data[0] || s->low_delay) *data_size = sizeof(AVVideoFrame); #ifdef PRINT_FRAME_TIME printf("%Ld\n", rdtsc()-time); diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 5058d1d5f5..22c701340c 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1702,7 +1702,7 @@ eos: //end of slice MPV_frame_end(s); - if (s->pict_type == B_TYPE) { + if (s->pict_type == B_TYPE || s->low_delay) { *pict= *(AVVideoFrame*)&s->current_picture; } else { s->picture_number++; @@ -1756,7 +1756,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, } s->width = width; s->height = height; - avctx->has_b_frames= s->has_b_frames = 1; + avctx->has_b_frames= 1; s->avctx = avctx; avctx->width = width; avctx->height = height; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 63338012ff..f947634c2c 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -268,40 +268,87 @@ int DCT_common_init(MpegEncContext *s) } /** - * allocates various arrays for a Picture structure, except the pixels themself. - * The pixels are allocated/set in te get_buffer() + * allocates a Picture + * The pixels are allocated/set by calling get_buffer() if shared=0 */ -static int alloc_picture(MpegEncContext *s, Picture *pic){ - if (s->encoding) { - CHECKED_ALLOCZ(pic->mb_var , s->mb_num * sizeof(INT16)) - CHECKED_ALLOCZ(pic->mc_mb_var, s->mb_num * sizeof(INT16)) - CHECKED_ALLOCZ(pic->mb_mean , s->mb_num * sizeof(INT8)) +static int alloc_picture(MpegEncContext *s, Picture *pic, int shared){ + + 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, (AVVideoFrame*)pic); + + if(r<0 || !pic->age || !pic->type || !pic->data[0]){ + fprintf(stderr, "get_buffer() failed (%d %d %d %X)\n", r, pic->age, pic->type, (int)pic->data[0]); + return -1; + } + + if(s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1])){ + fprintf(stderr, "get_buffer() failed (stride changed)\n"); + return -1; + } + + if(pic->linesize[1] != pic->linesize[2]){ + fprintf(stderr, "get_buffer() failed (uv stride missmatch)\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 , s->mb_num * sizeof(INT16)) + CHECKED_ALLOCZ(pic->mc_mb_var, s->mb_num * sizeof(INT16)) + CHECKED_ALLOCZ(pic->mb_mean , s->mb_num * sizeof(INT8)) + } - CHECKED_ALLOCZ(pic->mbskip_table , s->mb_num * sizeof(UINT8)+1) //the +1 is for the slice end check - CHECKED_ALLOCZ(pic->qscale_table , s->mb_num * sizeof(UINT8)) - pic->qstride= s->mb_width; + CHECKED_ALLOCZ(pic->mbskip_table , s->mb_num * sizeof(UINT8)+1) //the +1 is for the slice end check + CHECKED_ALLOCZ(pic->qscale_table , s->mb_num * sizeof(UINT8)) + pic->qstride= s->mb_width; + } 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, (AVVideoFrame*)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); - if(s->avctx->get_buffer == avcodec_default_get_buffer){ + if(pic->type == FF_BUFFER_TYPE_INTERNAL){ for(i=0; i<4; i++){ av_freep(&pic->base[i]); pic->data[i]= NULL; } av_freep(&pic->opaque); + pic->type= 0; + }else if(pic->type == FF_BUFFER_TYPE_SHARED){ + for(i=0; i<4; i++){ + pic->base[i]= + pic->data[i]= NULL; + } + pic->type= 0; } } @@ -445,12 +492,6 @@ void MPV_common_end(MpegEncContext *s) { int i; - for(i=0; ipicture[i].data[0]){ - s->avctx->release_buffer(s->avctx, (AVVideoFrame*)&s->picture[i]); - } - } - av_freep(&s->mb_type); av_freep(&s->p_mv_table); av_freep(&s->b_forw_mv_table); @@ -572,6 +613,7 @@ int MPV_encode_init(AVCodecContext *avctx) if (mjpeg_init(s) < 0) return -1; avctx->delay=0; + s->low_delay=1; break; case CODEC_ID_H263: if (h263_get_picture_format(s->width, s->height) == 7) { @@ -580,6 +622,7 @@ int MPV_encode_init(AVCodecContext *avctx) } s->out_format = FMT_H263; avctx->delay=0; + s->low_delay=1; break; case CODEC_ID_H263P: s->out_format = FMT_H263; @@ -591,18 +634,19 @@ int MPV_encode_init(AVCodecContext *avctx) s->umvplus = 0; s->umvplus_dec = 0; avctx->delay=0; + s->low_delay=1; break; case CODEC_ID_RV10: s->out_format = FMT_H263; s->h263_rv10 = 1; avctx->delay=0; + s->low_delay=1; break; case CODEC_ID_MPEG4: s->out_format = FMT_H263; s->h263_pred = 1; s->unrestricted_mv = 1; - s->has_b_frames= s->max_b_frames ? 1 : 0; - s->low_delay= !s->has_b_frames; + 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: @@ -612,6 +656,7 @@ int MPV_encode_init(AVCodecContext *avctx) 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; @@ -620,6 +665,7 @@ int MPV_encode_init(AVCodecContext *avctx) 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; @@ -628,6 +674,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->unrestricted_mv = 1; s->msmpeg4_version= 3; avctx->delay=0; + s->low_delay=1; break; case CODEC_ID_WMV1: s->out_format = FMT_H263; @@ -636,6 +683,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->unrestricted_mv = 1; s->msmpeg4_version= 4; avctx->delay=0; + s->low_delay=1; break; case CODEC_ID_WMV2: s->out_format = FMT_H263; @@ -644,6 +692,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->unrestricted_mv = 1; s->msmpeg4_version= 5; avctx->delay=0; + s->low_delay=1; break; default: return -1; @@ -770,10 +819,30 @@ static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w) } } +static int find_unused_picture(MpegEncContext *s, int shared){ + int i; + + if(shared){ + for(i=0; ipicture[i].data[0]==NULL && s->picture[i].type==0) break; + } + }else{ + for(i=0; ipicture[i].data[0]==NULL && s->picture[i].type!=0) break; + } + for(i=0; ipicture[i].data[0]==NULL) break; + } + } + + assert(imb_skiped = 0; @@ -781,6 +850,7 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) /* mark&release old frames */ if (s->pict_type != B_TYPE && s->last_picture.data[0]) { for(i=0; ipicture[i].data[0], s->picture[i].type, i, s->next_picture.data[0], s->last_picture.data[0]); if(s->picture[i].data[0] == s->last_picture.data[0]){ // s->picture[i].reference=0; avctx->release_buffer(avctx, (AVVideoFrame*)&s->picture[i]); @@ -802,28 +872,13 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) } alloc: if(!s->encoding){ - /* find unused Picture */ - for(i=0; ipicture[i].data[0]==NULL) break; - } - assert(ipicture[i]; pic->reference= s->pict_type != B_TYPE; pic->coded_picture_number= s->current_picture.coded_picture_number+1; - r= avctx->get_buffer(avctx, pic); - - if(r<0 || (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1]))){ - fprintf(stderr, "get_buffer() failed (stride changed), bye bye\n"); - return -1; - } - - s->linesize = pic->linesize[0]; - s->uvlinesize= pic->linesize[1]; - - if(pic->qscale_table==NULL) - alloc_picture(s, (Picture*)pic); + alloc_picture(s, (Picture*)pic, 0); s->current_picture= s->picture[i]; } @@ -873,8 +928,6 @@ void MPV_frame_end(MpegEncContext *s) s->last_pict_type = s->pict_type; if(s->pict_type!=B_TYPE){ s->last_non_b_pict_type= s->pict_type; - s->num_available_buffers++; - if(s->num_available_buffers>2) s->num_available_buffers= 2; } s->current_picture.quality= s->qscale; //FIXME get average of qscale_table @@ -892,7 +945,7 @@ void MPV_frame_end(MpegEncContext *s) /* release non refernce frames */ for(i=0; ipicture[i].data[0] && !s->picture[i].reference) + if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/) s->avctx->release_buffer(s->avctx, (AVVideoFrame*)&s->picture[i]); } } @@ -930,81 +983,81 @@ static int get_intra_count(MpegEncContext *s, uint8_t *src, uint8_t *ref, int st return acc; } + static int load_input_picture(MpegEncContext *s, AVVideoFrame *pic_arg){ AVVideoFrame *pic; - int i,r; + int i; const int encoding_delay= s->max_b_frames; + int direct=1; - /* find unused Picture */ - for(i=0; ipicture[i].data[0]==NULL) break; - } - assert(ipicture[i]; - pic->reference= 1; + if(encoding_delay && !(s->flags&CODEC_FLAG_INPUT_PRESERVED)) direct=0; + if(pic_arg->linesize[0] != s->linesize) direct=0; + if(pic_arg->linesize[1] != s->uvlinesize) direct=0; + if(pic_arg->linesize[2] != s->uvlinesize) direct=0; + +// printf("%d %d %d %d\n",pic_arg->linesize[0], pic_arg->linesize[1], s->linesize, s->uvlinesize); -// assert(avctx->get_buffer == default_get_buffer || avctx->get_buffer==NULL); - r= s->avctx->get_buffer(s->avctx, pic); + if(direct){ + i= find_unused_picture(s, 1); - if(r<0 || (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1]))){ - fprintf(stderr, "get_buffer() failed (stride changed), bye bye\n"); - return -1; - } - - assert(s->linesize==0 || s->linesize ==pic->linesize[0]); - assert(s->uvlinesize==0 || s->uvlinesize==pic->linesize[1]); - assert(pic->linesize[1] == pic->linesize[2]); - s->linesize = pic->linesize[0]; - s->uvlinesize= pic->linesize[1]; + pic= (AVVideoFrame*)&s->picture[i]; + pic->reference= 1; - if(pic->qscale_table==NULL) - alloc_picture(s, (Picture*)pic); + for(i=0; i<4; i++){ + pic->data[i]= pic_arg->data[i]; + pic->linesize[i]= pic_arg->linesize[i]; + } + alloc_picture(s, (Picture*)pic, 1); + }else{ + i= find_unused_picture(s, 0); -// assert(s->input_picture[0]==NULL || s->input_picture[0]->data[0]==NULL); - - if(s->input_picture[encoding_delay]) - pic->display_picture_number= s->input_picture[encoding_delay]->display_picture_number + 1; -//printf("dpn2:%d\n", pic->display_picture_number); + pic= (AVVideoFrame*)&s->picture[i]; + pic->reference= 1; - /* shift buffer entries */ - for(i=1; iencoding_delay+1*/; i++) - s->input_picture[i-1]= s->input_picture[i]; - - s->input_picture[encoding_delay]= (Picture*)pic; - pic->pict_type= pic_arg->pict_type; - pic->quality= pic_arg->quality; - - if( pic->data[0] == pic_arg->data[0] - && pic->data[1] == pic_arg->data[1] - && pic->data[2] == pic_arg->data[2]){ + alloc_picture(s, (Picture*)pic, 0); + + if( pic->data[0] == pic_arg->data[0] + && pic->data[1] == pic_arg->data[1] + && pic->data[2] == pic_arg->data[2]){ // empty - }else{ - int h_chroma_shift, v_chroma_shift; + }else{ + int h_chroma_shift, v_chroma_shift; - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); - for(i=0; i<3; i++){ - int src_stride= pic_arg->linesize[i]; - int dst_stride= i ? s->uvlinesize : s->linesize; - int h_shift= i ? h_chroma_shift : 0; - int v_shift= i ? v_chroma_shift : 0; - int w= s->width >>h_shift; - int h= s->height>>v_shift; - uint8_t *src= pic_arg->data[i]; - uint8_t *dst= pic->data[i] + 16; + for(i=0; i<3; i++){ + int src_stride= pic_arg->linesize[i]; + int dst_stride= i ? s->uvlinesize : s->linesize; + int h_shift= i ? h_chroma_shift : 0; + int v_shift= i ? v_chroma_shift : 0; + int w= s->width >>h_shift; + int h= s->height>>v_shift; + uint8_t *src= pic_arg->data[i]; + uint8_t *dst= pic->data[i]; - if(src_stride==dst_stride) - memcpy(dst, src, src_stride*h); - else{ - while(h--){ - memcpy(dst, src, w); - dst += dst_stride; - src += src_stride; + if(src_stride==dst_stride) + memcpy(dst, src, src_stride*h); + else{ + while(h--){ + memcpy(dst, src, w); + dst += dst_stride; + src += src_stride; + } } } } } + pic->quality= pic_arg->quality; + pic->pict_type= pic_arg->pict_type; + + if(s->input_picture[encoding_delay]) + pic->display_picture_number= s->input_picture[encoding_delay]->display_picture_number + 1; + + /* shift buffer entries */ + for(i=1; iencoding_delay+1*/; i++) + s->input_picture[i-1]= s->input_picture[i]; + + s->input_picture[encoding_delay]= (Picture*)pic; return 0; } @@ -1016,7 +1069,7 @@ static void select_input_picture(MpegEncContext *s){ if(s->reordered_input_picture[0]) coded_pic_num= s->reordered_input_picture[0]->coded_picture_number + 1; -//printf("cpn:%d\n", coded_pic_num); + for(i=1; ireordered_input_picture[i-1]= s->reordered_input_picture[i]; s->reordered_input_picture[MAX_PICTURE_COUNT-1]= NULL; @@ -1039,7 +1092,7 @@ static void select_input_picture(MpegEncContext *s){ if(i + 1 >= s->rc_context.num_entries) break; } } - + if(s->input_picture[0]->pict_type){ /* user selected pict_type */ for(b_frames=0; b_framesmax_b_frames+1; b_frames++){ @@ -1056,8 +1109,8 @@ static void select_input_picture(MpegEncContext *s){ for(i=1; imax_b_frames+1; i++){ if(s->input_picture[i]->b_frame_score==0){ s->input_picture[i]->b_frame_score= - get_intra_count(s, s->input_picture[i ]->data[0] + 16, - s->input_picture[i-1]->data[0] + 16, s->linesize) + 1; + get_intra_count(s, s->input_picture[i ]->data[0], + s->input_picture[i-1]->data[0], s->linesize) + 1; } } for(i=0; imax_b_frames; i++){ @@ -1097,14 +1150,38 @@ static void select_input_picture(MpegEncContext *s){ } if(s->reordered_input_picture[0]){ - if(s->reordered_input_picture[0]->pict_type==B_TYPE){ - s->reordered_input_picture[0]->reference=0; + s->reordered_input_picture[0]->reference= s->reordered_input_picture[0]->pict_type!=B_TYPE; + + if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_SHARED){ + int i= find_unused_picture(s, 0); + Picture *pic= &s->picture[i]; + + s->new_picture= *s->reordered_input_picture[0]; + + /* mark us unused / free shared pic */ + for(i=0; i<4; i++) + s->reordered_input_picture[0]->data[i]= NULL; + s->reordered_input_picture[0]->type= 0; + + pic->pict_type = s->reordered_input_picture[0]->pict_type; + pic->quality = s->reordered_input_picture[0]->quality; + pic->coded_picture_number = s->reordered_input_picture[0]->coded_picture_number; + pic->reference = s->reordered_input_picture[0]->reference; + + alloc_picture(s, pic, 0); + + s->current_picture= *pic; + }else{ + assert( s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_USER + || s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL); + + s->new_picture= *s->reordered_input_picture[0]; + + for(i=0; i<4; i++){ + s->reordered_input_picture[0]->data[i]-=16; //FIXME dirty + } + s->current_picture= *s->reordered_input_picture[0]; } - s->current_picture= *s->reordered_input_picture[0]; - s->new_picture= s->current_picture; - s->new_picture.data[0]+=16; - s->new_picture.data[1]+=16; - s->new_picture.data[2]+=16; s->picture_number= s->new_picture.display_picture_number; //printf("dpn:%d\n", s->picture_number); @@ -2231,7 +2308,7 @@ static int pix_diff_vcmp16x8(UINT8 *s1, UINT8*s2, int stride){ //FIXME move to d void ff_draw_horiz_band(MpegEncContext *s){ if ( s->avctx->draw_horiz_band - && (s->num_available_buffers>=1 || (!s->has_b_frames)) ) { + && (s->last_picture.data[0] || s->low_delay) ) { UINT8 *src_ptr[3]; int y, h, offset; y = s->mb_y * 16; @@ -2244,7 +2321,7 @@ void ff_draw_horiz_band(MpegEncContext *s){ else offset = y * s->linesize; - if(s->pict_type==B_TYPE || (!s->has_b_frames)){ + if(s->pict_type==B_TYPE || s->low_delay){ src_ptr[0] = s->current_picture.data[0] + offset; src_ptr[1] = s->current_picture.data[1] + (offset >> 2); src_ptr[2] = s->current_picture.data[2] + (offset >> 2); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index fad4f8eaf1..fe5abff083 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -185,7 +185,6 @@ typedef struct MpegEncContext { Picture next_picture; /* previous picture (for bidir pred) */ Picture new_picture; /* source picture for encoding */ Picture current_picture; /* buffer to store the decompressed current picture */ - int num_available_buffers; /* is 0 at the start & after seeking, after the first I frame its 1 after next I/P 2 */ int last_dc[3]; /* last DC values for MPEG1 */ INT16 *dc_val[3]; /* used for mpeg4 DC prediction, all 3 arrays must be continuous */ int y_dc_scale, c_dc_scale; @@ -254,7 +253,6 @@ typedef struct MpegEncContext { UINT16 (*mv_penalty)[MAX_MV*2+1]; /* amount of bits needed to encode a MV, used for ME */ UINT8 *fcode_tab; /* smallest fcode needed for each MV */ - int has_b_frames; int no_rounding; /* apply no rounding to motion compensation (MPEG4, msmpeg4, ...) for b-frames rounding mode is allways 0 */ diff --git a/libavcodec/svq1.c b/libavcodec/svq1.c index 86ebd73825..929dece2ae 100644 --- a/libavcodec/svq1.c +++ b/libavcodec/svq1.c @@ -1179,7 +1179,7 @@ static int svq1_decode_init(AVCodecContext *avctx) s->height = (avctx->height+3)&~3; s->codec_id= avctx->codec->id; avctx->pix_fmt = PIX_FMT_YUV410P; - avctx->has_b_frames= s->has_b_frames=1; // not true, but DP frames and these behave like unidirectional b frames + avctx->has_b_frames= 1; // not true, but DP frames and these behave like unidirectional b frames s->flags= avctx->flags; if (MPV_common_init(s) < 0) return -1; return 0; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index bc7da83efe..768e8b6546 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -125,6 +125,9 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVVideoFrame *pic){ const int width = s->width; const int height= s->height; DefaultPicOpaque *opaque; + + assert(pic->data[0]==NULL); + assert(pic->type==0 || pic->type==FF_TYPE_INTERNAL); if(pic->opaque){ opaque= (DefaultPicOpaque *)pic->opaque; @@ -186,13 +189,14 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVVideoFrame *pic){ memset(pic->base[i], 128, pic->linesize[i]*h>>v_shift); if(s->flags&CODEC_FLAG_EMU_EDGE) - pic->data[i] = pic->base[i]; + pic->data[i] = pic->base[i] + 16; //FIXME 16 else - pic->data[i] = pic->base[i] + (pic->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift); + pic->data[i] = pic->base[i] + (pic->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift) + 16; //FIXME 16 opaque->data[i]= pic->data[i]; } pic->age= 256*256*256*64; + pic->type= FF_BUFFER_TYPE_INTERNAL; } return 0; @@ -201,6 +205,8 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVVideoFrame *pic){ void avcodec_default_release_buffer(AVCodecContext *s, AVVideoFrame *pic){ int i; + assert(pic->type==FF_BUFFER_TYPE_INTERNAL); + for(i=0; i<3; i++) pic->data[i]=NULL; //printf("R%X\n", pic->opaque); @@ -642,14 +648,39 @@ void avcodec_init(void) //dsputil_init(); } -/* this should be called after seeking and before trying to decode the next frame */ +/* this can be called after seeking and before trying to decode the next keyframe */ void avcodec_flush_buffers(AVCodecContext *avctx) { + int i; MpegEncContext *s = avctx->priv_data; - s->num_available_buffers=0; + + switch(avctx->codec_id){ + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_H263: + case CODEC_ID_RV10: + case CODEC_ID_MJPEG: + case CODEC_ID_MJPEGB: + case CODEC_ID_MPEG4: + case CODEC_ID_MSMPEG4V1: + case CODEC_ID_MSMPEG4V2: + case CODEC_ID_MSMPEG4V3: + case CODEC_ID_WMV1: + case CODEC_ID_WMV2: + case CODEC_ID_H263P: + case CODEC_ID_H263I: + case CODEC_ID_SVQ1: + for(i=0; ipicture[i].data[0] && ( s->picture[i].type == FF_BUFFER_TYPE_INTERNAL + || s->picture[i].type == FF_BUFFER_TYPE_USER)) + avctx->release_buffer(avctx, (AVVideoFrame*)&s->picture[i]); + } + break; + default: + //FIXME + break; + } } - static int raw_encode_init(AVCodecContext *s) { return 0;