From 102f3f706200b03ed811487d6686991f0ed5d439 Mon Sep 17 00:00:00 2001 From: Rintaro Kuroiwa Date: Mon, 18 Apr 2016 18:00:06 -0700 Subject: [PATCH] Scale sample duration in TsSegmenter - Sample duration wasn't scaled in TsSegmenter to calculate the current segment's length. So segmenting length did not always respect segment_duration. Change-Id: I1ef4747dbd12bde7852ffcbceb971f2775aa18b3 --- packager/media/formats/mp2t/ts_segmenter.cc | 7 +++++-- packager/media/formats/mp2t/ts_segmenter.h | 9 +++++++- .../formats/mp2t/ts_segmenter_unittest.cc | 21 +++++++------------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packager/media/formats/mp2t/ts_segmenter.cc b/packager/media/formats/mp2t/ts_segmenter.cc index a6e0ccb895..c26d37e26c 100644 --- a/packager/media/formats/mp2t/ts_segmenter.cc +++ b/packager/media/formats/mp2t/ts_segmenter.cc @@ -16,7 +16,7 @@ namespace media { namespace mp2t { namespace { -const int kTsTimescale = 90000; +const double kTsTimescale = 90000; } // namespace TsSegmenter::TsSegmenter(const MuxerOptions& options) @@ -35,6 +35,7 @@ Status TsSegmenter::Initialize(const StreamInfo& stream_info) { "Failed to initialize PesPacketGenerator."); } + timescale_scale_ = kTsTimescale / stream_info.time_scale(); return Status::OK; } @@ -62,7 +63,9 @@ Status TsSegmenter::AddSample(scoped_refptr sample) { "Failed to add sample to PesPacketGenerator."); } - current_segment_total_sample_duration_ += sample->duration() / kTsTimescale; + const double scaled_sample_duration = sample->duration() * timescale_scale_; + current_segment_total_sample_duration_ += + scaled_sample_duration / kTsTimescale; return WritePesPacketsToFile(); } diff --git a/packager/media/formats/mp2t/ts_segmenter.h b/packager/media/formats/mp2t/ts_segmenter.h index dce0ed77ab..57ae232ac4 100644 --- a/packager/media/formats/mp2t/ts_segmenter.h +++ b/packager/media/formats/mp2t/ts_segmenter.h @@ -66,7 +66,14 @@ class TsSegmenter { const MuxerOptions& muxer_options_; - // in seconds. + // Scale used to scale the input stream to TS's timesccale (which is 90000). + // Used for calculating the duration in seconds fo the current segment. + double timescale_scale_ = 1.0; + + // This is the sum of the durations of the samples that were added to + // PesPacketGenerator for the current segment (in seconds). Note that this is + // not necessarily the same as the length of the PesPackets that have been + // written to the current segment in WritePesPacketsToFile(). double current_segment_total_sample_duration_ = 0.0; // Used for segment template. diff --git a/packager/media/formats/mp2t/ts_segmenter_unittest.cc b/packager/media/formats/mp2t/ts_segmenter_unittest.cc index d4a1835e54..3b04677af9 100644 --- a/packager/media/formats/mp2t/ts_segmenter_unittest.cc +++ b/packager/media/formats/mp2t/ts_segmenter_unittest.cc @@ -72,9 +72,6 @@ class MockTsWriter : public TsWriter { // No need to keep the pes packet around for the current tests. return AddPesPacketMock(pes_packet.get()); } - - MOCK_METHOD0(NotifyReinjectPsi, bool()); - MOCK_CONST_METHOD0(TimeScale, uint32_t()); }; } // namespace @@ -120,9 +117,6 @@ TEST_F(TsSegmenterTest, AddSample) { options.segment_template = "file$Number$.ts"; TsSegmenter segmenter(options); - ON_CALL(*mock_ts_writer_, TimeScale()) - .WillByDefault(Return(kTimeScale)); - EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_)) .WillOnce(Return(true)); @@ -169,17 +163,18 @@ TEST_F(TsSegmenterTest, AddSample) { // This will add 2 samples and verify that the first segment is closed when the // second sample is added. TEST_F(TsSegmenterTest, PassedSegmentDuration) { + // Use something significantly smaller than 90000 to check that the scaling is + // done correctly in the segmenter. + const uint32_t kInputTimescale = 1001; scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264VideoCodec, kCodecString, kLanguage, - kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, + kTrackId, kInputTimescale, kDuration, kH264VideoCodec, kCodecString, + kLanguage, kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kExtraData, arraysize(kExtraData), kIsEncrypted)); MuxerOptions options; options.segment_duration = 10.0; options.segment_template = "file$Number$.ts"; TsSegmenter segmenter(options); - ON_CALL(*mock_ts_writer_, TimeScale()).WillByDefault(Return(kTimeScale)); - EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_)) .WillOnce(Return(true)); @@ -194,10 +189,10 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) { // 11 seconds > 10 seconds (segment duration). // Expect the segment to be finalized. - sample1->set_duration(kTimeScale * 11); + sample1->set_duration(kInputTimescale * 11); // Doesn't really matter how long this is. - sample2->set_duration(kTimeScale * 7); + sample2->set_duration(kInputTimescale * 7); Sequence writer_sequence; EXPECT_CALL(*mock_ts_writer_, NewSegment(StrEq("file1.ts"))) @@ -328,8 +323,6 @@ TEST_F(TsSegmenterTest, SegmentOnlyBeforeKeyFrame) { options.segment_template = "file$Number$.ts"; TsSegmenter segmenter(options); - ON_CALL(*mock_ts_writer_, TimeScale()).WillByDefault(Return(kTimeScale)); - EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_)) .WillOnce(Return(true));