From 37a24a7db9901730f6709e802df0fef42884ddf9 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 8 Jan 2009 21:44:24 +0000 Subject: Fix build with libavcodec < 51.68.0. This covers the internal snapshot and the version in Debian lenny. --- src/combined/ffmpeg/ff_video_decoder.c | 54 +++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'src/combined/ffmpeg/ff_video_decoder.c') diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index a1ab3696c..01635e1ab 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -58,6 +58,12 @@ #define ENABLE_DIRECT_RENDERING +/* reordered_opaque appeared in libavcodec 51.68.0 */ +#define AVCODEC_HAS_REORDERED_OPAQUE +#if LIBAVCODEC_VERSION_INT < 0x334400 +# undef AVCODEC_HAS_REORDERED_OPAQUE +#endif + typedef struct ff_video_decoder_s ff_video_decoder_t; typedef struct ff_video_class_s { @@ -78,9 +84,11 @@ struct ff_video_decoder_s { xine_stream_t *stream; int64_t pts; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE uint64_t pts_tag_mask; uint64_t pts_tag; int pts_tag_counter; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ int video_step; uint8_t decoder_ok:1; @@ -609,10 +617,6 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { su = this->av_frame->data[1]; sv = this->av_frame->data[2]; - /* Some segfaults & heap corruption have been observed with img->height, - * so we use this->bih.biHeight instead (which is the displayed height) - */ - if (this->context->pix_fmt == PIX_FMT_YUV410P) { yuv9_to_yv12( @@ -633,7 +637,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - this->bih.biHeight); + img->height); } else if (this->context->pix_fmt == PIX_FMT_YUV411P) { @@ -655,7 +659,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - this->bih.biHeight); + img->height); } else if (this->context->pix_fmt == PIX_FMT_RGBA32) { @@ -663,7 +667,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint32_t *argb_pixels; uint32_t argb; - for(y = 0; y < this->bih.biHeight; y++) { + for(y = 0; y < img->height; y++) { argb_pixels = (uint32_t *)sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -691,7 +695,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint8_t *src; uint16_t pixel16; - for(y = 0; y < this->bih.biHeight; y++) { + for(y = 0; y < img->height; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -720,7 +724,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint8_t *src; uint16_t pixel16; - for(y = 0; y < this->bih.biHeight; y++) { + for(y = 0; y < img->height; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -748,7 +752,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < this->bih.biHeight; y++) { + for(y = 0; y < img->height; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -772,7 +776,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < this->bih.biHeight; y++) { + for(y = 0; y < img->height; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -815,7 +819,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { v_palette[x] = COMPUTE_V(r, g, b); } - for(y = 0; y < this->bih.biHeight; y++) { + for(y = 0; y < img->height; y++) { src = sy; for(x = 0; x < img->width; x++) { pixel = *src++; @@ -832,7 +836,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } else { - for (y = 0; y < this->bih.biHeight; y++) { + for (y=0; yheight; y++) { xine_fast_memcpy (dy, sy, img->width); dy += img->pitches[0]; @@ -840,7 +844,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { sy += this->av_frame->linesize[0]; } - for (y = 0; y < this->bih.biHeight / 2; y++) { + for (y=0; y<(img->height/2); y++) { if (this->context->pix_fmt != PIX_FMT_YUV444P) { @@ -1181,6 +1185,7 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu } } +#ifdef AVCODEC_HAS_REORDERED_OPAQUE static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts) { return pts | this->pts_tag; @@ -1217,6 +1222,7 @@ static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts) } } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { uint8_t *chunk_buf = this->buf; AVRational avr00 = {0, 1}; @@ -1241,12 +1247,14 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->size = 0; } +#ifdef AVCODEC_HAS_REORDERED_OPAQUE if (this->size == 0) { /* take over pts when we are about to buffer a frame */ this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); this->context->reordered_opaque = ff_tag_pts(this, this->pts); this->pts = 0; } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ /* data accumulation */ if (buf->size > 0) { @@ -1301,8 +1309,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { &got_picture, &chunk_buf[offset], this->size); +#ifdef AVCODEC_HAS_REORDERED_OPAQUE /* reset consumed pts value */ this->context->reordered_opaque = ff_tag_pts(this, 0); +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ lprintf("consumed size: %d, got_picture: %d\n", len, got_picture); if ((len <= 0) || (len > this->size)) { @@ -1320,10 +1330,12 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { memmove (this->buf, &chunk_buf[offset], this->size); chunk_buf = this->buf; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE /* take over pts for next access unit */ this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); this->context->reordered_opaque = ff_tag_pts(this, this->pts); this->pts = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } } } @@ -1418,9 +1430,14 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_convert_frame(this, img); } +#ifndef AVCODEC_HAS_REORDERED_OPAQUE + img->pts = this->pts; + this->pts = 0; +#else /* AVCODEC_HAS_REORDERED_OPAQUE */ img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); ff_check_pts_tagging(this, this->av_frame->reordered_opaque); /* only check for valid frames */ this->av_frame->reordered_opaque = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ /* workaround for weird 120fps streams */ if( video_step_to_use == 750 ) { @@ -1460,8 +1477,13 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->output_format, VO_BOTH_FIELDS|this->frame_flags); /* set PTS to allow early syncing */ +#ifndef AVCODEC_HAS_REORDERED_OPAQUE + img->pts = this->pts; + this->pts = 0; +#else /* AVCODEC_HAS_REORDERED_OPAQUE */ img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); this->av_frame->reordered_opaque = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ img->duration = video_step_to_use; @@ -1547,9 +1569,11 @@ static void ff_reset (video_decoder_t *this_gen) { if (this->is_mpeg12) mpeg_parser_reset(this->mpeg_parser); +#ifdef AVCODEC_HAS_REORDERED_OPAQUE this->pts_tag_mask = 0; this->pts_tag = 0; this->pts_tag_counter = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } static void ff_discontinuity (video_decoder_t *this_gen) { @@ -1558,6 +1582,7 @@ static void ff_discontinuity (video_decoder_t *this_gen) { lprintf ("ff_discontinuity\n"); this->pts = 0; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE /* * there is currently no way to reset all the pts which are stored in the decoder. * therefore, we add a unique tag (generated from pts_tag_counter) to pts (see @@ -1588,6 +1613,7 @@ static void ff_discontinuity (video_decoder_t *this_gen) { counter_mask <<= 1; } } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } static void ff_dispose (video_decoder_t *this_gen) { -- cgit v1.2.3 From 37a9cc3f7acf8db19b736123471cedfe10a148dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 11 Jan 2009 01:37:05 +0100 Subject: Fix PTS tagging: large (negative) PTS values are a result of turning it off to early The current code turns of PTS tagging as soon as a match is found. But depending on picture reordering, there may be later frames which still have the tag. The result is that most likely the highest bit is set which makes the PTS values large negative numbers which cause a clock error and make streams unplayable. To fix this issue, a stable counter is introduced. The two passes of PTS tagging are now switched after the tag has been seen stable for 100 frames. This should protect us from picture reordering issues. --HG-- extra : transplant_source : I%2A%BBi%A5nb/%5E%12%9Ay%7B%BAj%7D%0B%16%0By --- src/combined/ffmpeg/ff_video_decoder.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'src/combined/ffmpeg/ff_video_decoder.c') diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index f4f7175fa..c781146a2 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -81,6 +81,7 @@ struct ff_video_decoder_s { uint64_t pts_tag_mask; uint64_t pts_tag; int pts_tag_counter; + int pts_tag_stable_counter; int video_step; uint8_t decoder_ok:1; @@ -1197,19 +1198,29 @@ static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts) { if (this->pts_tag_mask == 0) return; /* pts tagging inactive */ - - if ((pts & this->pts_tag_mask) != this->pts_tag) + if ((pts & this->pts_tag_mask) != this->pts_tag) { + this->pts_tag_stable_counter = 0; return; /* pts still outdated */ + } + + /* the tag should be stable for 100 frames */ + this->pts_tag_stable_counter++; if (this->pts_tag != 0) { - /* first pass: reset pts_tag */ - this->pts_tag = 0; + if (this->pts_tag_stable_counter >= 100) { + /* first pass: reset pts_tag */ + this->pts_tag = 0; + this->pts_tag_stable_counter = 0; + } } else if (pts == 0) return; /* cannot detect second pass */ else { - /* second pass: reset pts_tag_mask and pts_tag_counter */ - this->pts_tag_mask = 0; - this->pts_tag_counter = 0; + if (this->pts_tag_stable_counter >= 100) { + /* second pass: reset pts_tag_mask and pts_tag_counter */ + this->pts_tag_mask = 0; + this->pts_tag_counter = 0; + this->pts_tag_stable_counter = 0; + } } } @@ -1546,6 +1557,7 @@ static void ff_reset (video_decoder_t *this_gen) { this->pts_tag_mask = 0; this->pts_tag = 0; this->pts_tag_counter = 0; + this->pts_tag_stable_counter = 0; } static void ff_discontinuity (video_decoder_t *this_gen) { @@ -1567,9 +1579,11 @@ static void ff_discontinuity (video_decoder_t *this_gen) { this->pts_tag_counter++; this->pts_tag_mask = 0; this->pts_tag = 0; + this->pts_tag_stable_counter = 0; { /* pts values typically don't use the uppermost bits. therefore we put the tag there */ int counter_mask = 1; + int counter = 2 * this->pts_tag_counter + 1; /* always set the uppermost bit in tag_mask */ uint64_t tag_mask = 0x8000000000000000ull; while (this->pts_tag_counter >= counter_mask) { @@ -1577,7 +1591,7 @@ static void ff_discontinuity (video_decoder_t *this_gen) { * mirror the counter into the uppermost bits. this allows us to enlarge mask as * necessary and while previous taggings can still be detected to be outdated. */ - if (this->pts_tag_counter & counter_mask) + if (counter & counter_mask) this->pts_tag |= tag_mask; this->pts_tag_mask |= tag_mask; tag_mask >>= 1; -- cgit v1.2.3 From 5e14134988d4120d747ead46466c2bb0d68f7289 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Sun, 11 Jan 2009 01:37:38 +0000 Subject: Reapply cset ffb2e82d7bb7 (accidental removal by this cset's parent). --- src/combined/ffmpeg/ff_video_decoder.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/combined/ffmpeg/ff_video_decoder.c') diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index 01635e1ab..801155ab2 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -617,6 +617,10 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { su = this->av_frame->data[1]; sv = this->av_frame->data[2]; + /* Some segfaults & heap corruption have been observed with img->height, + * so we use this->bih.biHeight instead (which is the displayed height) + */ + if (this->context->pix_fmt == PIX_FMT_YUV410P) { yuv9_to_yv12( @@ -637,7 +641,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - img->height); + this->bih.biHeight); } else if (this->context->pix_fmt == PIX_FMT_YUV411P) { @@ -659,7 +663,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - img->height); + this->bih.biHeight); } else if (this->context->pix_fmt == PIX_FMT_RGBA32) { @@ -667,7 +671,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint32_t *argb_pixels; uint32_t argb; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { argb_pixels = (uint32_t *)sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -695,7 +699,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint8_t *src; uint16_t pixel16; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -724,7 +728,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { uint8_t *src; uint16_t pixel16; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -752,7 +756,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -776,7 +780,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; @@ -819,7 +823,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { v_palette[x] = COMPUTE_V(r, g, b); } - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { pixel = *src++; @@ -836,7 +840,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } else { - for (y=0; yheight; y++) { + for (y = 0; y < this->bih.biHeight; y++) { xine_fast_memcpy (dy, sy, img->width); dy += img->pitches[0]; @@ -844,7 +848,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { sy += this->av_frame->linesize[0]; } - for (y=0; y<(img->height/2); y++) { + for (y = 0; y < this->bih.biHeight / 2; y++) { if (this->context->pix_fmt != PIX_FMT_YUV444P) { -- cgit v1.2.3