summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Nißl <rnissl@gmx.de>2009-01-11 01:37:05 +0100
committerReinhard Nißl <rnissl@gmx.de>2009-01-11 01:37:05 +0100
commit37a9cc3f7acf8db19b736123471cedfe10a148dc (patch)
tree17e39b2d3f02e02591aa149a80e757437b6eba98
parent90acd04b32de69512076b386cbb385041697e63e (diff)
downloadxine-lib-37a9cc3f7acf8db19b736123471cedfe10a148dc.tar.gz
xine-lib-37a9cc3f7acf8db19b736123471cedfe10a148dc.tar.bz2
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
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c30
1 files changed, 22 insertions, 8 deletions
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;