summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/Jamfile1
-rw-r--r--contrib/patch-ffmpeg-mpegleak.patch71
-rw-r--r--libhb/decavcodec.c30
-rw-r--r--libhb/hb.c2
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 */