diff options
-rw-r--r-- | contrib/Jamfile | 1 | ||||
-rw-r--r-- | contrib/patch-ffmpeg-mpegleak.patch | 71 | ||||
-rw-r--r-- | libhb/decavcodec.c | 30 | ||||
-rw-r--r-- | libhb/hb.c | 2 |
4 files changed, 94 insertions, 10 deletions
diff --git a/contrib/Jamfile b/contrib/Jamfile index 4a871903a..98b310bdc 100644 --- a/contrib/Jamfile +++ b/contrib/Jamfile @@ -79,6 +79,7 @@ rule LibAvCodec { FFMPEG_PATCH = "$(PATCH) -p0 < ../patch-ffmpeg.patch" ; FFMPEG_PATCH += " && $(PATCH) -p0 < ../patch-ffmpeg-latm.patch " ; + FFMPEG_PATCH += " && $(PATCH) -p0 < ../patch-ffmpeg-mpegleak.patch " ; if $(OS) = CYGWIN { FFMPEG_PATCH += " && $(PATCH) -p1 < ../patch-ffmpeg-cygwin.patch " ; diff --git a/contrib/patch-ffmpeg-mpegleak.patch b/contrib/patch-ffmpeg-mpegleak.patch new file mode 100644 index 000000000..88538922f --- /dev/null +++ b/contrib/patch-ffmpeg-mpegleak.patch @@ -0,0 +1,71 @@ +Index: libavcodec/h264.c +=================================================================== +--- libavcodec/h264.c (revision 14820) ++++ libavcodec/h264.c (working copy) +@@ -3355,7 +3355,7 @@ + * stream. Need to discard one frame. Prevents overrun of the + * short_ref and long_ref buffers. + */ +- av_log(h->s.avctx, AV_LOG_ERROR, ++ av_log(h->s.avctx, AV_LOG_DEBUG, + "number of reference frames exceeds max (probably " + "corrupt input), discarding one\n"); + +@@ -7557,7 +7557,7 @@ + + if(!(s->flags2 & CODEC_FLAG2_CHUNKS) && !s->current_picture_ptr){ + if (avctx->skip_frame >= AVDISCARD_NONREF || s->hurry_up) return 0; +- av_log(avctx, AV_LOG_ERROR, "no frame!\n"); ++ av_log(avctx, AV_LOG_DEBUG, "no frame!\n"); + return -1; + } + +Index: libavcodec/mpegvideo.c +=================================================================== +--- libavcodec/mpegvideo.c (revision 14820) ++++ libavcodec/mpegvideo.c (working copy) +@@ -772,6 +772,15 @@ + }else{ + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0]==NULL && s->picture[i].type!=0) return i; //FIXME ++ /* XXX there seems to be a leak caused by h264 in mpeg transport ++ * streams: Over-the-air streams have a lot of errors. A picture ++ * may be marked as referenced but the actual references get lost ++ * so it never gets released. We take care of that here by purging ++ * pictures that are impossibly old. ++ */ ++ if (s->coded_picture_number - s->picture[i].coded_picture_number > ++ 32*MAX_PICTURE_COUNT) ++ s->avctx->release_buffer(s->avctx, (AVFrame*)&s->picture[i]); + } + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0]==NULL) return i; +@@ -779,19 +788,15 @@ + } + + av_log(s->avctx, AV_LOG_FATAL, "Internal error, picture buffer overflow\n"); +- /* We could return -1, but the codec would crash trying to draw into a +- * non-existing frame anyway. This is safer than waiting for a random crash. +- * Also the return of this is never useful, an encoder must only allocate +- * as much as allowed in the specification. This has no relationship to how +- * much libavcodec could allocate (and MAX_PICTURE_COUNT is always large +- * enough for such valid streams). +- * Plus, a decoder has to check stream validity and remove frames if too +- * many reference frames are around. Waiting for "OOM" is not correct at +- * all. Similarly, missing reference frames have to be replaced by +- * interpolated/MC frames, anything else is a bug in the codec ... +- */ +- abort(); +- return -1; ++ /* assume that we don't have a picture because of the leak described above. ++ * just release the oldest we have & reuse its slot. */ ++ int oldest=0; ++ for(i=0; i<MAX_PICTURE_COUNT; i++){ ++ if (s->picture[i].coded_picture_number < s->picture[oldest].coded_picture_number) ++ oldest = i; ++ } ++ s->avctx->release_buffer(s->avctx, (AVFrame*)&s->picture[oldest]); ++ return oldest; + } + + static void update_noise_reduction(MpegEncContext *s){ diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index a945680e0..62eca6566 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -92,8 +92,9 @@ struct hb_work_private_s int64_t chap_time; // time of next chap mark (if new_chap != 0) int new_chap; int ignore_pts; // workaround M$ bugs - int nframes; - int ndrops; + uint32_t nframes; + uint32_t ndrops; + uint32_t decode_errors; double duration; // frame duration (for video) }; @@ -340,8 +341,16 @@ static int get_frame_buf( AVCodecContext *context, AVFrame *frame ) static void log_chapter( hb_work_private_t *pv, int chap_num, int64_t pts ) { hb_chapter_t *c = hb_list_item( pv->job->title->list_chapter, chap_num - 1 ); - hb_log( "%s: \"%s\" (%d) at frame %u time %lld", pv->context->codec->name, - c->title, chap_num, pv->nframes, pts ); + if ( c && c->title ) + { + hb_log( "%s: \"%s\" (%d) at frame %u time %lld", + pv->context->codec->name, c->title, chap_num, pv->nframes, pts ); + } + else + { + hb_log( "%s: Chapter %d at frame %u time %lld", + pv->context->codec->name, chap_num, pv->nframes, pts ); + } } static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size ) @@ -349,7 +358,10 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size ) int got_picture; AVFrame frame; - avcodec_decode_video( pv->context, &frame, &got_picture, data, size ); + if ( avcodec_decode_video( pv->context, &frame, &got_picture, data, size ) < 0 ) + { + ++pv->decode_errors; + } if( got_picture ) { // ffmpeg makes it hard to attach a pts to a frame. if the MPEG ES @@ -498,7 +510,8 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in, decodeVideo( pv, in->data, in->size, pts, dts ); hb_list_add( pv->list, in ); *buf_out = link_buf_list( pv ); - hb_log( "%s done: %d frames", pv->context->codec->name, pv->nframes ); + hb_log( "%s done: %u frames, %u decoder errors", + pv->context->codec->name, pv->nframes, pv->decode_errors ); return HB_WORK_DONE; } @@ -710,8 +723,9 @@ static int decavcodecviWork( hb_work_object_t * w, hb_buffer_t ** buf_in, } hb_list_add( pv->list, in ); *buf_out = link_buf_list( pv ); - hb_log( "%s done: %d frames %d drops", pv->context->codec->name, - pv->nframes, pv->ndrops ); + hb_log( "%s done: %u frames, %u decoder errors, %u drops", + pv->context->codec->name, pv->nframes, pv->decode_errors, + pv->ndrops ); return HB_WORK_DONE; } diff --git a/libhb/hb.c b/libhb/hb.c index 0e0bddb3c..f73a2437e 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -73,7 +73,6 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) if( verbose > HB_DEBUG_NONE ) { putenv( "HB_DEBUG=1" ); - av_log_set_level(AV_LOG_DEBUG); } /* Check for an update on the website if asked to */ @@ -153,7 +152,6 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) if( verbose > HB_DEBUG_NONE ) { putenv( "HB_DEBUG=1" ); - av_log_set_level(AV_LOG_DEBUG); } /* Check for an update on the website if asked to */ |