Add support to explicitly set segment duration.

Adds a flag to sample muxer to copy input file's duration.

BUG=https://bugs.chromium.org/p/webm/issues/detail?id=1100

Change-Id: I9138f0301fa5c9f467c802d75e6ba32db156ae4f
This commit is contained in:
Frank Galligan 2016-10-13 14:56:57 -07:00
parent 02bc809f9d
commit c0160e0ab5
5 changed files with 50 additions and 14 deletions

View File

@ -3047,6 +3047,7 @@ Segment::Segment()
size_position_(0),
doc_type_version_(kDefaultDocTypeVersion),
doc_type_version_written_(0),
duration_(0.0),
writer_cluster_(NULL),
writer_cues_(NULL),
writer_header_(NULL) {
@ -3220,21 +3221,25 @@ bool Segment::Finalize() {
double duration =
(static_cast<double>(last_timestamp_) + last_block_duration_) /
segment_info_.timecode_scale();
if (last_block_duration_ == 0 && estimate_file_duration_) {
const int num_tracks = static_cast<int>(tracks_.track_entries_size());
for (int i = 0; i < num_tracks; ++i) {
if (track_frames_written_[i] < 2)
continue;
if (duration_ > 0.0) {
duration = duration_;
} else {
if (last_block_duration_ == 0 && estimate_file_duration_) {
const int num_tracks = static_cast<int>(tracks_.track_entries_size());
for (int i = 0; i < num_tracks; ++i) {
if (track_frames_written_[i] < 2)
continue;
// Estimate the duration for the last block of a Track.
const double nano_per_frame =
static_cast<double>(last_track_timestamp_[i]) /
(track_frames_written_[i] - 1);
const double track_duration =
(last_track_timestamp_[i] + nano_per_frame) /
segment_info_.timecode_scale();
if (track_duration > duration)
duration = track_duration;
// Estimate the duration for the last block of a Track.
const double nano_per_frame =
static_cast<double>(last_track_timestamp_[i]) /
(track_frames_written_[i] - 1);
const double track_duration =
(last_track_timestamp_[i] + nano_per_frame) /
segment_info_.timecode_scale();
if (track_duration > duration)
duration = track_duration;
}
}
}
segment_info_.set_duration(duration);

View File

@ -1688,6 +1688,8 @@ class Segment {
}
bool estimate_file_duration() const { return estimate_file_duration_; }
const SegmentInfo* segment_info() const { return &segment_info_; }
void set_duration(double duration) { duration_ = duration; }
double duration() const { return duration_; }
// Returns true when codec IDs are valid for WebM.
bool DocTypeIsWebm() const;
@ -1897,6 +1899,9 @@ class Segment {
uint32_t doc_type_version_;
uint32_t doc_type_version_written_;
// If |duration_| is > 0, then explicitly set the duration of the segment.
double duration_;
// Pointer to the writer objects. Not owned by this class.
IMkvWriter* writer_cluster_;
IMkvWriter* writer_cues_;

View File

@ -54,6 +54,7 @@ void Usage() {
printf(">0 Writes the last frame in each cluster with Duration\n");
printf(" -fixed_size_cluster_timecode <int> ");
printf(">0 Writes the cluster timecode using exactly 8 bytes\n");
printf(" -copy_input_duration >0 Copies the input duration\n");
printf("\n");
printf("Video options:\n");
printf(" -display_width <int> Display width in pixels\n");
@ -170,6 +171,7 @@ int main(int argc, char* argv[]) {
const char* chunk_name = NULL;
bool accurate_cluster_duration = false;
bool fixed_size_cluster_timecode = false;
bool copy_input_duration = false;
bool output_cues_block_number = true;
@ -234,6 +236,8 @@ int main(int argc, char* argv[]) {
i < argc_check) {
fixed_size_cluster_timecode =
strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-copy_input_duration", argv[i]) && i < argc_check) {
copy_input_duration = strtol(argv[++i], &end, 10) == 0 ? false : true;
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
display_width = strtol(argv[++i], &end, 10);
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
@ -655,6 +659,12 @@ int main(int argc, char* argv[]) {
if (!metadata.Write(-1))
return EXIT_FAILURE;
if (copy_input_duration) {
const double input_duration =
static_cast<double>(segment_info->GetDuration()) / timeCodeScale;
muxer_segment.set_duration(input_duration);
}
if (!muxer_segment.Finalize()) {
printf("Finalization of segment failed.\n");
return EXIT_FAILURE;

View File

@ -409,6 +409,22 @@ TEST_F(MuxerTest, SegmentDurationComputation) {
CompareFiles(GetTestFilePath("segment_duration.webm"), filename_));
}
TEST_F(MuxerTest, SetSegmentDuration) {
EXPECT_TRUE(SegmentInit(false, false, false));
AddVideoTrack();
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
2000000, false));
segment_.set_duration(10500.0);
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("set_segment_duration.webm"), filename_));
}
TEST_F(MuxerTest, ForceNewCluster) {
EXPECT_TRUE(SegmentInit(false, false, false));
segment_.set_estimate_file_duration(false);

Binary file not shown.