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
This commit is contained in:
Rintaro Kuroiwa 2016-04-18 18:00:06 -07:00
parent bbf9c6849b
commit 102f3f7062
3 changed files with 20 additions and 17 deletions

View File

@ -16,7 +16,7 @@ namespace media {
namespace mp2t { namespace mp2t {
namespace { namespace {
const int kTsTimescale = 90000; const double kTsTimescale = 90000;
} // namespace } // namespace
TsSegmenter::TsSegmenter(const MuxerOptions& options) TsSegmenter::TsSegmenter(const MuxerOptions& options)
@ -35,6 +35,7 @@ Status TsSegmenter::Initialize(const StreamInfo& stream_info) {
"Failed to initialize PesPacketGenerator."); "Failed to initialize PesPacketGenerator.");
} }
timescale_scale_ = kTsTimescale / stream_info.time_scale();
return Status::OK; return Status::OK;
} }
@ -62,7 +63,9 @@ Status TsSegmenter::AddSample(scoped_refptr<MediaSample> sample) {
"Failed to add sample to PesPacketGenerator."); "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(); return WritePesPacketsToFile();
} }

View File

@ -66,7 +66,14 @@ class TsSegmenter {
const MuxerOptions& muxer_options_; 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; double current_segment_total_sample_duration_ = 0.0;
// Used for segment template. // Used for segment template.

View File

@ -72,9 +72,6 @@ class MockTsWriter : public TsWriter {
// No need to keep the pes packet around for the current tests. // No need to keep the pes packet around for the current tests.
return AddPesPacketMock(pes_packet.get()); return AddPesPacketMock(pes_packet.get());
} }
MOCK_METHOD0(NotifyReinjectPsi, bool());
MOCK_CONST_METHOD0(TimeScale, uint32_t());
}; };
} // namespace } // namespace
@ -120,9 +117,6 @@ TEST_F(TsSegmenterTest, AddSample) {
options.segment_template = "file$Number$.ts"; options.segment_template = "file$Number$.ts";
TsSegmenter segmenter(options); TsSegmenter segmenter(options);
ON_CALL(*mock_ts_writer_, TimeScale())
.WillByDefault(Return(kTimeScale));
EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true));
EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_)) EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_))
.WillOnce(Return(true)); .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 // This will add 2 samples and verify that the first segment is closed when the
// second sample is added. // second sample is added.
TEST_F(TsSegmenterTest, PassedSegmentDuration) { 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<VideoStreamInfo> stream_info(new VideoStreamInfo( scoped_refptr<VideoStreamInfo> stream_info(new VideoStreamInfo(
kTrackId, kTimeScale, kDuration, kH264VideoCodec, kCodecString, kLanguage, kTrackId, kInputTimescale, kDuration, kH264VideoCodec, kCodecString,
kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kLanguage, kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate,
kNaluLengthSize, kExtraData, arraysize(kExtraData), kIsEncrypted)); kNaluLengthSize, kExtraData, arraysize(kExtraData), kIsEncrypted));
MuxerOptions options; MuxerOptions options;
options.segment_duration = 10.0; options.segment_duration = 10.0;
options.segment_template = "file$Number$.ts"; options.segment_template = "file$Number$.ts";
TsSegmenter segmenter(options); TsSegmenter segmenter(options);
ON_CALL(*mock_ts_writer_, TimeScale()).WillByDefault(Return(kTimeScale));
EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true));
EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_)) EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_))
.WillOnce(Return(true)); .WillOnce(Return(true));
@ -194,10 +189,10 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) {
// 11 seconds > 10 seconds (segment duration). // 11 seconds > 10 seconds (segment duration).
// Expect the segment to be finalized. // Expect the segment to be finalized.
sample1->set_duration(kTimeScale * 11); sample1->set_duration(kInputTimescale * 11);
// Doesn't really matter how long this is. // Doesn't really matter how long this is.
sample2->set_duration(kTimeScale * 7); sample2->set_duration(kInputTimescale * 7);
Sequence writer_sequence; Sequence writer_sequence;
EXPECT_CALL(*mock_ts_writer_, NewSegment(StrEq("file1.ts"))) EXPECT_CALL(*mock_ts_writer_, NewSegment(StrEq("file1.ts")))
@ -328,8 +323,6 @@ TEST_F(TsSegmenterTest, SegmentOnlyBeforeKeyFrame) {
options.segment_template = "file$Number$.ts"; options.segment_template = "file$Number$.ts";
TsSegmenter segmenter(options); TsSegmenter segmenter(options);
ON_CALL(*mock_ts_writer_, TimeScale()).WillByDefault(Return(kTimeScale));
EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_ts_writer_, Initialize(_)).WillOnce(Return(true));
EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_)) EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_))
.WillOnce(Return(true)); .WillOnce(Return(true));