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:
parent
bbf9c6849b
commit
102f3f7062
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in New Issue