diff --git a/packager/media/formats/mp2t/mp2t_media_parser_unittest.cc b/packager/media/formats/mp2t/mp2t_media_parser_unittest.cc index 639039d5c8..011be293c6 100644 --- a/packager/media/formats/mp2t/mp2t_media_parser_unittest.cc +++ b/packager/media/formats/mp2t/mp2t_media_parser_unittest.cc @@ -28,7 +28,9 @@ class Mp2tMediaParserTest : public testing::Test { : audio_frame_count_(0), video_frame_count_(0), video_min_dts_(kNoTimestamp), - video_max_dts_(kNoTimestamp) { + video_max_dts_(kNoTimestamp), + video_min_pts_(kNoTimestamp), + video_max_pts_(kNoTimestamp) { parser_.reset(new Mp2tMediaParser()); } @@ -41,6 +43,8 @@ class Mp2tMediaParserTest : public testing::Test { int video_frame_count_; int64_t video_min_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) { return parser_->Parse(data, static_cast(length)); @@ -79,6 +83,8 @@ class Mp2tMediaParserTest : public testing::Test { ++video_frame_count_; if (video_min_dts_ == kNoTimestamp) video_min_dts_ = sample->dts(); + if (video_min_pts_ == kNoTimestamp || video_min_pts_ > sample->pts()) + video_min_pts_ = sample->pts(); // Verify timestamps are increasing. if (video_max_dts_ == kNoTimestamp) video_max_dts_ = sample->dts(); @@ -86,6 +92,9 @@ class Mp2tMediaParserTest : public testing::Test { LOG(ERROR) << "Video DTS not strictly increasing."; return false; } + if (video_max_pts_ < sample->pts()) { + video_max_pts_ = sample->pts(); + } video_max_dts_ = sample->dts(); } else { LOG(ERROR) << "Missing StreamInfo for track ID " << track_id; @@ -153,9 +162,9 @@ TEST_F(Mp2tMediaParserTest, UnalignedAppend512_H265) { } TEST_F(Mp2tMediaParserTest, TimestampWrapAround) { - // "bear-640x360.ts" has been transcoded from bear-640x360.mp4 by applying a - // time offset of 95442s (close to 2^33 / 90000) which results in timestamps - // wrap around in the Mpeg2 TS stream. + // "bear-640x360_ptszero_dtswraparound.ts" has been transcoded from + // bear-640x360.mp4 by applying a time offset of 95442s (close to 2^33 / + // 90000) which results in timestamp wrap around in the Mpeg2 TS stream. ParseMpeg2TsFile("bear-640x360_ptswraparound.ts", 512); EXPECT_TRUE(parser_->Flush()); EXPECT_EQ(82, video_frame_count_); @@ -163,6 +172,22 @@ TEST_F(Mp2tMediaParserTest, TimestampWrapAround) { EXPECT_GT(video_max_dts_, static_cast(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(1) << 33); + EXPECT_GT(video_max_dts_, static_cast(1) << 33); + // PTS was not subjected to unroll but was artificially unrolled to be close + // to DTS + EXPECT_GT(video_min_pts_, static_cast(1) << 33); + EXPECT_GT(video_max_pts_, static_cast(1) << 33); +} + } // namespace mp2t } // namespace media } // namespace shaka diff --git a/packager/media/formats/mp2t/ts_section_pes.cc b/packager/media/formats/mp2t/ts_section_pes.cc index 31f799cb11..9b6e5c8b3c 100644 --- a/packager/media/formats/mp2t/ts_section_pes.cc +++ b/packager/media/formats/mp2t/ts_section_pes.cc @@ -5,7 +5,6 @@ #include "packager/media/formats/mp2t/ts_section_pes.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/timestamp.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. int64_t media_pts(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) { int64_t dts = ConvertTimestampSectionToTimestamp(dts_section); if (previous_dts_valid_) @@ -289,6 +280,19 @@ bool TsSectionPes::ParseInternal(const uint8_t* raw_pes, int raw_pes_size) { previous_dts_valid_ = true; 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. DCHECK_EQ(bit_reader.bits_available() % 8, 0u); diff --git a/packager/media/test/data/bear-640x360_ptszero_dtswraparound.ts b/packager/media/test/data/bear-640x360_ptszero_dtswraparound.ts new file mode 100644 index 0000000000..8d633b5700 Binary files /dev/null and b/packager/media/test/data/bear-640x360_ptszero_dtswraparound.ts differ