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:
parent
02bc809f9d
commit
c0160e0ab5
@ -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);
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
BIN
testing/testdata/set_segment_duration.webm
vendored
Normal file
BIN
testing/testdata/set_segment_duration.webm
vendored
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user