fix: PTS diverge DTS when DTS close to 2pow33 and PTS more than 0 (#1050)
Fixes #1049 Co-authored-by: Joey Parrish <joeyparrish@users.noreply.github.com>
This commit is contained in:
parent
3d60105738
commit
ab8ab12d09
|
@ -28,7 +28,9 @@ class Mp2tMediaParserTest : public testing::Test {
|
||||||
: audio_frame_count_(0),
|
: audio_frame_count_(0),
|
||||||
video_frame_count_(0),
|
video_frame_count_(0),
|
||||||
video_min_dts_(kNoTimestamp),
|
video_min_dts_(kNoTimestamp),
|
||||||
video_max_dts_(kNoTimestamp) {
|
video_max_dts_(kNoTimestamp),
|
||||||
|
video_min_pts_(kNoTimestamp),
|
||||||
|
video_max_pts_(kNoTimestamp) {
|
||||||
parser_.reset(new Mp2tMediaParser());
|
parser_.reset(new Mp2tMediaParser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +43,8 @@ class Mp2tMediaParserTest : public testing::Test {
|
||||||
int video_frame_count_;
|
int video_frame_count_;
|
||||||
int64_t video_min_dts_;
|
int64_t video_min_dts_;
|
||||||
int64_t video_max_dts_;
|
int64_t video_max_dts_;
|
||||||
|
int64_t video_min_pts_;
|
||||||
|
int64_t video_max_pts_;
|
||||||
|
|
||||||
bool AppendData(const uint8_t* data, size_t length) {
|
bool AppendData(const uint8_t* data, size_t length) {
|
||||||
return parser_->Parse(data, static_cast<int>(length));
|
return parser_->Parse(data, static_cast<int>(length));
|
||||||
|
@ -79,6 +83,8 @@ class Mp2tMediaParserTest : public testing::Test {
|
||||||
++video_frame_count_;
|
++video_frame_count_;
|
||||||
if (video_min_dts_ == kNoTimestamp)
|
if (video_min_dts_ == kNoTimestamp)
|
||||||
video_min_dts_ = sample->dts();
|
video_min_dts_ = sample->dts();
|
||||||
|
if (video_min_pts_ == kNoTimestamp || video_min_pts_ > sample->pts())
|
||||||
|
video_min_pts_ = sample->pts();
|
||||||
// Verify timestamps are increasing.
|
// Verify timestamps are increasing.
|
||||||
if (video_max_dts_ == kNoTimestamp)
|
if (video_max_dts_ == kNoTimestamp)
|
||||||
video_max_dts_ = sample->dts();
|
video_max_dts_ = sample->dts();
|
||||||
|
@ -86,6 +92,9 @@ class Mp2tMediaParserTest : public testing::Test {
|
||||||
LOG(ERROR) << "Video DTS not strictly increasing.";
|
LOG(ERROR) << "Video DTS not strictly increasing.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (video_max_pts_ < sample->pts()) {
|
||||||
|
video_max_pts_ = sample->pts();
|
||||||
|
}
|
||||||
video_max_dts_ = sample->dts();
|
video_max_dts_ = sample->dts();
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Missing StreamInfo for track ID " << track_id;
|
LOG(ERROR) << "Missing StreamInfo for track ID " << track_id;
|
||||||
|
@ -153,9 +162,9 @@ TEST_F(Mp2tMediaParserTest, UnalignedAppend512_H265) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(Mp2tMediaParserTest, TimestampWrapAround) {
|
TEST_F(Mp2tMediaParserTest, TimestampWrapAround) {
|
||||||
// "bear-640x360.ts" has been transcoded from bear-640x360.mp4 by applying a
|
// "bear-640x360_ptszero_dtswraparound.ts" has been transcoded from
|
||||||
// time offset of 95442s (close to 2^33 / 90000) which results in timestamps
|
// bear-640x360.mp4 by applying a time offset of 95442s (close to 2^33 /
|
||||||
// wrap around in the Mpeg2 TS stream.
|
// 90000) which results in timestamp wrap around in the Mpeg2 TS stream.
|
||||||
ParseMpeg2TsFile("bear-640x360_ptswraparound.ts", 512);
|
ParseMpeg2TsFile("bear-640x360_ptswraparound.ts", 512);
|
||||||
EXPECT_TRUE(parser_->Flush());
|
EXPECT_TRUE(parser_->Flush());
|
||||||
EXPECT_EQ(82, video_frame_count_);
|
EXPECT_EQ(82, video_frame_count_);
|
||||||
|
@ -163,6 +172,22 @@ TEST_F(Mp2tMediaParserTest, TimestampWrapAround) {
|
||||||
EXPECT_GT(video_max_dts_, static_cast<int64_t>(1) << 33);
|
EXPECT_GT(video_max_dts_, static_cast<int64_t>(1) << 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Mp2tMediaParserTest, PtsZeroDtsWrapAround) {
|
||||||
|
// "bear-640x360.ts" has been transcoded from bear-640x360.mp4 by applying a
|
||||||
|
// dts (close to 2^33 / 90000) and pts 1433 which results in dts
|
||||||
|
// wrap around in the Mpeg2 TS stream but pts does not.
|
||||||
|
ParseMpeg2TsFile("bear-640x360_ptszero_dtswraparound.ts", 512);
|
||||||
|
EXPECT_TRUE(parser_->Flush());
|
||||||
|
EXPECT_EQ(64, video_frame_count_);
|
||||||
|
// DTS was subjected to unroll
|
||||||
|
EXPECT_LT(video_min_dts_, static_cast<int64_t>(1) << 33);
|
||||||
|
EXPECT_GT(video_max_dts_, static_cast<int64_t>(1) << 33);
|
||||||
|
// PTS was not subjected to unroll but was artificially unrolled to be close
|
||||||
|
// to DTS
|
||||||
|
EXPECT_GT(video_min_pts_, static_cast<int64_t>(1) << 33);
|
||||||
|
EXPECT_GT(video_max_pts_, static_cast<int64_t>(1) << 33);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mp2t
|
} // namespace mp2t
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "packager/media/formats/mp2t/ts_section_pes.h"
|
#include "packager/media/formats/mp2t/ts_section_pes.h"
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
|
||||||
#include "packager/media/base/bit_reader.h"
|
#include "packager/media/base/bit_reader.h"
|
||||||
#include "packager/media/base/timestamp.h"
|
#include "packager/media/base/timestamp.h"
|
||||||
#include "packager/media/formats/mp2t/es_parser.h"
|
#include "packager/media/formats/mp2t/es_parser.h"
|
||||||
|
@ -273,14 +272,6 @@ bool TsSectionPes::ParseInternal(const uint8_t* raw_pes, int raw_pes_size) {
|
||||||
// Convert and unroll the timestamps.
|
// Convert and unroll the timestamps.
|
||||||
int64_t media_pts(kNoTimestamp);
|
int64_t media_pts(kNoTimestamp);
|
||||||
int64_t media_dts(kNoTimestamp);
|
int64_t media_dts(kNoTimestamp);
|
||||||
if (is_pts_valid) {
|
|
||||||
int64_t pts = ConvertTimestampSectionToTimestamp(pts_section);
|
|
||||||
if (previous_pts_valid_)
|
|
||||||
pts = UnrollTimestamp(previous_pts_, pts);
|
|
||||||
previous_pts_ = pts;
|
|
||||||
previous_pts_valid_ = true;
|
|
||||||
media_pts = pts;
|
|
||||||
}
|
|
||||||
if (is_dts_valid) {
|
if (is_dts_valid) {
|
||||||
int64_t dts = ConvertTimestampSectionToTimestamp(dts_section);
|
int64_t dts = ConvertTimestampSectionToTimestamp(dts_section);
|
||||||
if (previous_dts_valid_)
|
if (previous_dts_valid_)
|
||||||
|
@ -289,6 +280,19 @@ bool TsSectionPes::ParseInternal(const uint8_t* raw_pes, int raw_pes_size) {
|
||||||
previous_dts_valid_ = true;
|
previous_dts_valid_ = true;
|
||||||
media_dts = dts;
|
media_dts = dts;
|
||||||
}
|
}
|
||||||
|
if (is_pts_valid) {
|
||||||
|
int64_t pts = ConvertTimestampSectionToTimestamp(pts_section);
|
||||||
|
if (previous_pts_valid_) {
|
||||||
|
pts = UnrollTimestamp(previous_pts_, pts);
|
||||||
|
} else {
|
||||||
|
if (media_dts != kNoTimestamp) {
|
||||||
|
pts = UnrollTimestamp(media_dts, pts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous_pts_ = pts;
|
||||||
|
previous_pts_valid_ = true;
|
||||||
|
media_pts = pts;
|
||||||
|
}
|
||||||
|
|
||||||
// Discard the rest of the PES packet header.
|
// Discard the rest of the PES packet header.
|
||||||
DCHECK_EQ(bit_reader.bits_available() % 8, 0u);
|
DCHECK_EQ(bit_reader.bits_available() % 8, 0u);
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue