Option to write timecode using fixed # of bytes
Add an option to write the cluster timecode using exactly 8 bytes irrespective of the actual number of bytes required to write it as an ebml integer. This could be useful for players that want to rewrite the timecode in-place (e.g. live streaming). Change-Id: I1a049251f00ab65591d71e169129f5145a8c8863
This commit is contained in:
parent
c1991fea81
commit
eb50da8e38
@ -2112,9 +2112,10 @@ bool Tags::ExpandTagsArray() {
|
|||||||
// Cluster class
|
// Cluster class
|
||||||
|
|
||||||
Cluster::Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
|
Cluster::Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
|
||||||
bool write_last_frame_with_duration)
|
bool write_last_frame_with_duration, bool fixed_size_timecode)
|
||||||
: blocks_added_(0),
|
: blocks_added_(0),
|
||||||
finalized_(false),
|
finalized_(false),
|
||||||
|
fixed_size_timecode_(fixed_size_timecode),
|
||||||
header_written_(false),
|
header_written_(false),
|
||||||
payload_size_(0),
|
payload_size_(0),
|
||||||
position_for_cues_(cues_pos),
|
position_for_cues_(cues_pos),
|
||||||
@ -2386,9 +2387,12 @@ bool Cluster::WriteClusterHeader() {
|
|||||||
if (SerializeInt(writer_, kEbmlUnknownValue, 8))
|
if (SerializeInt(writer_, kEbmlUnknownValue, 8))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!WriteEbmlElement(writer_, libwebm::kMkvTimecode, timecode()))
|
if (!WriteEbmlElement(writer_, libwebm::kMkvTimecode, timecode(),
|
||||||
|
fixed_size_timecode_ ? 8 : 0)) {
|
||||||
return false;
|
return false;
|
||||||
AddPayloadSize(EbmlElementSize(libwebm::kMkvTimecode, timecode()));
|
}
|
||||||
|
AddPayloadSize(EbmlElementSize(libwebm::kMkvTimecode, timecode(),
|
||||||
|
fixed_size_timecode_ ? 8 : 0));
|
||||||
header_written_ = true;
|
header_written_ = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2720,6 +2724,7 @@ Segment::Segment()
|
|||||||
new_cuepoint_(false),
|
new_cuepoint_(false),
|
||||||
output_cues_(true),
|
output_cues_(true),
|
||||||
accurate_cluster_duration_(false),
|
accurate_cluster_duration_(false),
|
||||||
|
fixed_size_cluster_timecode_(false),
|
||||||
payload_pos_(0),
|
payload_pos_(0),
|
||||||
size_position_(0),
|
size_position_(0),
|
||||||
doc_type_version_(kDefaultDocTypeVersion),
|
doc_type_version_(kDefaultDocTypeVersion),
|
||||||
@ -3186,6 +3191,10 @@ void Segment::AccurateClusterDuration(bool accurate_cluster_duration) {
|
|||||||
accurate_cluster_duration_ = accurate_cluster_duration;
|
accurate_cluster_duration_ = accurate_cluster_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Segment::UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode) {
|
||||||
|
fixed_size_cluster_timecode_ = fixed_size_cluster_timecode;
|
||||||
|
}
|
||||||
|
|
||||||
bool Segment::SetChunking(bool chunking, const char* filename) {
|
bool Segment::SetChunking(bool chunking, const char* filename) {
|
||||||
if (chunk_count_ > 0)
|
if (chunk_count_ > 0)
|
||||||
return false;
|
return false;
|
||||||
@ -3490,7 +3499,7 @@ bool Segment::MakeNewCluster(uint64_t frame_timestamp_ns) {
|
|||||||
const int64_t offset = MaxOffset();
|
const int64_t offset = MaxOffset();
|
||||||
cluster = new (std::nothrow)
|
cluster = new (std::nothrow)
|
||||||
Cluster(cluster_timecode, offset, segment_info_.timecode_scale(),
|
Cluster(cluster_timecode, offset, segment_info_.timecode_scale(),
|
||||||
accurate_cluster_duration_);
|
accurate_cluster_duration_, fixed_size_cluster_timecode_);
|
||||||
if (!cluster)
|
if (!cluster)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -3757,4 +3766,4 @@ bool Segment::WriteFramesLessThan(uint64_t timestamp) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mkvmuxer
|
} // namespace mkvmuxer
|
||||||
|
@ -993,7 +993,8 @@ class Cluster {
|
|||||||
// position for the cluster within the segment that should be written in
|
// position for the cluster within the segment that should be written in
|
||||||
// the cues element. |timecode_scale| is the timecode scale of the segment.
|
// the cues element. |timecode_scale| is the timecode scale of the segment.
|
||||||
Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
|
Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
|
||||||
bool write_last_frame_with_duration = false);
|
bool write_last_frame_with_duration = false,
|
||||||
|
bool fixed_size_timecode = false);
|
||||||
~Cluster();
|
~Cluster();
|
||||||
|
|
||||||
bool Init(IMkvWriter* ptr_writer);
|
bool Init(IMkvWriter* ptr_writer);
|
||||||
@ -1137,6 +1138,10 @@ class Cluster {
|
|||||||
// Flag telling if the cluster has been closed.
|
// Flag telling if the cluster has been closed.
|
||||||
bool finalized_;
|
bool finalized_;
|
||||||
|
|
||||||
|
// Flag indicating whether the cluster's timecode will always be written out
|
||||||
|
// using 8 bytes.
|
||||||
|
bool fixed_size_timecode_;
|
||||||
|
|
||||||
// Flag telling if the cluster's header has been written.
|
// Flag telling if the cluster's header has been written.
|
||||||
bool header_written_;
|
bool header_written_;
|
||||||
|
|
||||||
@ -1448,6 +1453,9 @@ class Segment {
|
|||||||
// Toggles whether to write the last frame in each Cluster with Duration.
|
// Toggles whether to write the last frame in each Cluster with Duration.
|
||||||
void AccurateClusterDuration(bool accurate_cluster_duration);
|
void AccurateClusterDuration(bool accurate_cluster_duration);
|
||||||
|
|
||||||
|
// Toggles whether to write the Cluster Timecode using exactly 8 bytes.
|
||||||
|
void UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode);
|
||||||
|
|
||||||
// Sets if the muxer will output files in chunks or not. |chunking| is a
|
// Sets if the muxer will output files in chunks or not. |chunking| is a
|
||||||
// flag telling whether or not to turn on chunking. |filename| is the base
|
// flag telling whether or not to turn on chunking. |filename| is the base
|
||||||
// filename for the chunk files. The header chunk file will be named
|
// filename for the chunk files. The header chunk file will be named
|
||||||
@ -1654,6 +1662,9 @@ class Segment {
|
|||||||
// element in it.
|
// element in it.
|
||||||
bool accurate_cluster_duration_;
|
bool accurate_cluster_duration_;
|
||||||
|
|
||||||
|
// Flag whether or not to write the Cluster Timecode using exactly 8 bytes.
|
||||||
|
bool fixed_size_cluster_timecode_;
|
||||||
|
|
||||||
// The size of the EBML header, used to validate the header if
|
// The size of the EBML header, used to validate the header if
|
||||||
// WriteEbmlHeader() is called more than once.
|
// WriteEbmlHeader() is called more than once.
|
||||||
int32_t ebml_header_size_;
|
int32_t ebml_header_size_;
|
||||||
@ -1681,4 +1692,4 @@ class Segment {
|
|||||||
|
|
||||||
} // namespace mkvmuxer
|
} // namespace mkvmuxer
|
||||||
|
|
||||||
#endif // MKVMUXER_MKVMUXER_H_
|
#endif // MKVMUXER_MKVMUXER_H_
|
||||||
|
@ -246,11 +246,15 @@ uint64_t EbmlElementSize(uint64_t type, int64_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t EbmlElementSize(uint64_t type, uint64_t value) {
|
uint64_t EbmlElementSize(uint64_t type, uint64_t value) {
|
||||||
|
return EbmlElementSize(type, value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t EbmlElementSize(uint64_t type, uint64_t value, uint64_t fixed_size) {
|
||||||
// Size of EBML ID
|
// Size of EBML ID
|
||||||
int32_t ebml_size = GetUIntSize(type);
|
int32_t ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
// Datasize
|
// Datasize
|
||||||
ebml_size += GetUIntSize(value);
|
ebml_size += (fixed_size > 0) ? fixed_size : GetUIntSize(value);
|
||||||
|
|
||||||
// Size of Datasize
|
// Size of Datasize
|
||||||
ebml_size++;
|
ebml_size++;
|
||||||
@ -432,13 +436,23 @@ bool WriteEbmlMasterElement(IMkvWriter* writer, uint64_t type, uint64_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value) {
|
bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value) {
|
||||||
|
return WriteEbmlElement(writer, type, value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value,
|
||||||
|
uint64_t fixed_size) {
|
||||||
if (!writer)
|
if (!writer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (WriteID(writer, type))
|
if (WriteID(writer, type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const uint64_t size = GetUIntSize(value);
|
uint64_t size = GetUIntSize(value);
|
||||||
|
if (fixed_size > 0) {
|
||||||
|
if (size > fixed_size)
|
||||||
|
return false;
|
||||||
|
size = fixed_size;
|
||||||
|
}
|
||||||
if (WriteUInt(writer, size))
|
if (WriteUInt(writer, size))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -33,6 +33,11 @@ uint64_t EbmlElementSize(uint64_t type, const char* value);
|
|||||||
uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size);
|
uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size);
|
||||||
uint64_t EbmlDateElementSize(uint64_t type);
|
uint64_t EbmlDateElementSize(uint64_t type);
|
||||||
|
|
||||||
|
// Returns the size in bytes of the element assuming that the element was
|
||||||
|
// written using |fixed_size| bytes. If |fixed_size| is set to zero, then it
|
||||||
|
// computes the necessary number of bytes based on |value|.
|
||||||
|
uint64_t EbmlElementSize(uint64_t type, uint64_t value, uint64_t fixed_size);
|
||||||
|
|
||||||
// Creates an EBML coded number from |value| and writes it out. The size of
|
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||||
// the coded number is determined by the value of |value|. |value| must not
|
// the coded number is determined by the value of |value|. |value| must not
|
||||||
// be in a coded form. Returns 0 on success.
|
// be in a coded form. Returns 0 on success.
|
||||||
@ -59,6 +64,13 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const uint8_t* value,
|
|||||||
uint64_t size);
|
uint64_t size);
|
||||||
bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value);
|
bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value);
|
||||||
|
|
||||||
|
// Output an Mkv non-master element using fixed size. The element will be
|
||||||
|
// written out using exactly |fixed_size| bytes. If |fixed_size| is set to zero
|
||||||
|
// then it computes the necessary number of bytes based on |value|. Returns true
|
||||||
|
// if the element was written.
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value,
|
||||||
|
uint64_t fixed_size);
|
||||||
|
|
||||||
// Output a Mkv Frame. It decides the correct element to write (Block vs
|
// Output a Mkv Frame. It decides the correct element to write (Block vs
|
||||||
// SimpleBlock) based on the parameters of the Frame.
|
// SimpleBlock) based on the parameters of the Frame.
|
||||||
uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
||||||
|
@ -52,6 +52,8 @@ void Usage() {
|
|||||||
printf(" -copy_tags <int> >0 Copies the tags\n");
|
printf(" -copy_tags <int> >0 Copies the tags\n");
|
||||||
printf(" -accurate_cluster_duration <int> ");
|
printf(" -accurate_cluster_duration <int> ");
|
||||||
printf(">0 Writes the last frame in each cluster with Duration\n");
|
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("\n");
|
printf("\n");
|
||||||
printf("Video options:\n");
|
printf("Video options:\n");
|
||||||
printf(" -display_width <int> Display width in pixels\n");
|
printf(" -display_width <int> Display width in pixels\n");
|
||||||
@ -163,6 +165,7 @@ int main(int argc, char* argv[]) {
|
|||||||
bool copy_tags = false;
|
bool copy_tags = false;
|
||||||
const char* chunk_name = NULL;
|
const char* chunk_name = NULL;
|
||||||
bool accurate_cluster_duration = false;
|
bool accurate_cluster_duration = false;
|
||||||
|
bool fixed_size_cluster_timecode = false;
|
||||||
|
|
||||||
bool output_cues_block_number = true;
|
bool output_cues_block_number = true;
|
||||||
|
|
||||||
@ -221,6 +224,10 @@ int main(int argc, char* argv[]) {
|
|||||||
i < argc_check) {
|
i < argc_check) {
|
||||||
accurate_cluster_duration =
|
accurate_cluster_duration =
|
||||||
strtol(argv[++i], &end, 10) == 0 ? false : true;
|
strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-fixed_size_cluster_timecode", argv[i]) &&
|
||||||
|
i < argc_check) {
|
||||||
|
fixed_size_cluster_timecode =
|
||||||
|
strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
|
||||||
display_width = strtol(argv[++i], &end, 10);
|
display_width = strtol(argv[++i], &end, 10);
|
||||||
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
|
} else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
|
||||||
@ -297,6 +304,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
muxer_segment.AccurateClusterDuration(accurate_cluster_duration);
|
muxer_segment.AccurateClusterDuration(accurate_cluster_duration);
|
||||||
|
muxer_segment.UseFixedSizeClusterTimecode(fixed_size_cluster_timecode);
|
||||||
|
|
||||||
if (live_mode)
|
if (live_mode)
|
||||||
muxer_segment.set_mode(mkvmuxer::Segment::kLive);
|
muxer_segment.set_mode(mkvmuxer::Segment::kLive);
|
||||||
|
@ -91,7 +91,8 @@ class MuxerTest : public testing::Test {
|
|||||||
is_writer_open_ = false;
|
is_writer_open_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SegmentInit(bool output_cues, bool accurate_cluster_duration) {
|
bool SegmentInit(bool output_cues, bool accurate_cluster_duration,
|
||||||
|
bool fixed_size_cluster_timecode) {
|
||||||
if (!segment_.Init(writer_.get()))
|
if (!segment_.Init(writer_.get()))
|
||||||
return false;
|
return false;
|
||||||
SegmentInfo* const info = segment_.GetSegmentInfo();
|
SegmentInfo* const info = segment_.GetSegmentInfo();
|
||||||
@ -99,6 +100,7 @@ class MuxerTest : public testing::Test {
|
|||||||
info->set_muxing_app(kAppString);
|
info->set_muxing_app(kAppString);
|
||||||
segment_.OutputCues(output_cues);
|
segment_.OutputCues(output_cues);
|
||||||
segment_.AccurateClusterDuration(accurate_cluster_duration);
|
segment_.AccurateClusterDuration(accurate_cluster_duration);
|
||||||
|
segment_.UseFixedSizeClusterTimecode(fixed_size_cluster_timecode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +114,7 @@ class MuxerTest : public testing::Test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(MuxerTest, SegmentInfo) {
|
TEST_F(MuxerTest, SegmentInfo) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
SegmentInfo* const info = segment_.GetSegmentInfo();
|
SegmentInfo* const info = segment_.GetSegmentInfo();
|
||||||
info->set_timecode_scale(kTimeCodeScale);
|
info->set_timecode_scale(kTimeCodeScale);
|
||||||
info->set_duration(2.345);
|
info->set_duration(2.345);
|
||||||
@ -129,7 +131,7 @@ TEST_F(MuxerTest, SegmentInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, AddTracks) {
|
TEST_F(MuxerTest, AddTracks) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
|
|
||||||
// Add a Video Track
|
// Add a Video Track
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
@ -173,7 +175,7 @@ TEST_F(MuxerTest, AddTracks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, AddChapters) {
|
TEST_F(MuxerTest, AddChapters) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
// Add a Chapter
|
// Add a Chapter
|
||||||
@ -190,7 +192,7 @@ TEST_F(MuxerTest, AddChapters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, SimpleBlock) {
|
TEST_F(MuxerTest, SimpleBlock) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
// Valid Frame
|
// Valid Frame
|
||||||
@ -218,7 +220,7 @@ TEST_F(MuxerTest, SimpleBlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, SimpleBlockWithAddGenericFrame) {
|
TEST_F(MuxerTest, SimpleBlockWithAddGenericFrame) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
@ -250,7 +252,7 @@ TEST_F(MuxerTest, SimpleBlockWithAddGenericFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, MetadataBlock) {
|
TEST_F(MuxerTest, MetadataBlock) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
Track* const track = segment_.AddTrack(kMetadataTrackNumber);
|
Track* const track = segment_.AddTrack(kMetadataTrackNumber);
|
||||||
track->set_uid(kMetadataTrackNumber);
|
track->set_uid(kMetadataTrackNumber);
|
||||||
track->set_type(kMetadataTrackType);
|
track->set_type(kMetadataTrackType);
|
||||||
@ -281,7 +283,7 @@ TEST_F(MuxerTest, MetadataBlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, TrackType) {
|
TEST_F(MuxerTest, TrackType) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
Track* const track = segment_.AddTrack(kMetadataTrackNumber);
|
Track* const track = segment_.AddTrack(kMetadataTrackNumber);
|
||||||
track->set_uid(kMetadataTrackNumber);
|
track->set_uid(kMetadataTrackNumber);
|
||||||
track->set_codec_id(kMetadataCodecId);
|
track->set_codec_id(kMetadataCodecId);
|
||||||
@ -301,7 +303,7 @@ TEST_F(MuxerTest, TrackType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, BlockWithAdditional) {
|
TEST_F(MuxerTest, BlockWithAdditional) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
// Valid Frame
|
// Valid Frame
|
||||||
@ -342,7 +344,7 @@ TEST_F(MuxerTest, BlockWithAdditional) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, BlockAdditionalWithAddGenericFrame) {
|
TEST_F(MuxerTest, BlockAdditionalWithAddGenericFrame) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
@ -377,7 +379,7 @@ TEST_F(MuxerTest, BlockAdditionalWithAddGenericFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, SegmentDurationComputation) {
|
TEST_F(MuxerTest, SegmentDurationComputation) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
@ -405,7 +407,7 @@ TEST_F(MuxerTest, SegmentDurationComputation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, ForceNewCluster) {
|
TEST_F(MuxerTest, ForceNewCluster) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
|
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
|
||||||
@ -427,7 +429,7 @@ TEST_F(MuxerTest, ForceNewCluster) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, OutputCues) {
|
TEST_F(MuxerTest, OutputCues) {
|
||||||
EXPECT_TRUE(SegmentInit(true, false));
|
EXPECT_TRUE(SegmentInit(true, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
@ -447,7 +449,7 @@ TEST_F(MuxerTest, OutputCues) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, CuesBeforeClusters) {
|
TEST_F(MuxerTest, CuesBeforeClusters) {
|
||||||
EXPECT_TRUE(SegmentInit(true, false));
|
EXPECT_TRUE(SegmentInit(true, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
@ -480,7 +482,7 @@ TEST_F(MuxerTest, CuesBeforeClusters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, MaxClusterSize) {
|
TEST_F(MuxerTest, MaxClusterSize) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
const uint64_t kMaxClusterSize = 20;
|
const uint64_t kMaxClusterSize = 20;
|
||||||
segment_.set_max_cluster_size(kMaxClusterSize);
|
segment_.set_max_cluster_size(kMaxClusterSize);
|
||||||
@ -505,7 +507,7 @@ TEST_F(MuxerTest, MaxClusterSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, MaxClusterDuration) {
|
TEST_F(MuxerTest, MaxClusterDuration) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
const uint64_t kMaxClusterDuration = 4000000;
|
const uint64_t kMaxClusterDuration = 4000000;
|
||||||
segment_.set_max_cluster_duration(kMaxClusterDuration);
|
segment_.set_max_cluster_duration(kMaxClusterDuration);
|
||||||
@ -533,7 +535,7 @@ TEST_F(MuxerTest, MaxClusterDuration) {
|
|||||||
|
|
||||||
TEST_F(MuxerTest, SetCuesTrackNumber) {
|
TEST_F(MuxerTest, SetCuesTrackNumber) {
|
||||||
const uint64_t kTrackNumber = 10;
|
const uint64_t kTrackNumber = 10;
|
||||||
EXPECT_TRUE(SegmentInit(true, false));
|
EXPECT_TRUE(SegmentInit(true, false, false));
|
||||||
const uint64_t vid_track =
|
const uint64_t vid_track =
|
||||||
segment_.AddVideoTrack(kWidth, kHeight, kTrackNumber);
|
segment_.AddVideoTrack(kWidth, kHeight, kTrackNumber);
|
||||||
EXPECT_EQ(kTrackNumber, vid_track);
|
EXPECT_EQ(kTrackNumber, vid_track);
|
||||||
@ -562,7 +564,7 @@ TEST_F(MuxerTest, SetCuesTrackNumber) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, BlockWithDiscardPadding) {
|
TEST_F(MuxerTest, BlockWithDiscardPadding) {
|
||||||
EXPECT_TRUE(SegmentInit(false, false));
|
EXPECT_TRUE(SegmentInit(false, false, false));
|
||||||
AddAudioTrack();
|
AddAudioTrack();
|
||||||
|
|
||||||
int timecode = 1000;
|
int timecode = 1000;
|
||||||
@ -585,7 +587,7 @@ TEST_F(MuxerTest, BlockWithDiscardPadding) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, AccurateClusterDuration) {
|
TEST_F(MuxerTest, AccurateClusterDuration) {
|
||||||
EXPECT_TRUE(SegmentInit(false, true));
|
EXPECT_TRUE(SegmentInit(false, true, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
@ -614,7 +616,7 @@ TEST_F(MuxerTest, AccurateClusterDuration) {
|
|||||||
// Tests AccurateClusterDuration flag with the duration of the very last block
|
// Tests AccurateClusterDuration flag with the duration of the very last block
|
||||||
// of the file set explicitly.
|
// of the file set explicitly.
|
||||||
TEST_F(MuxerTest, AccurateClusterDurationExplicitLastFrameDuration) {
|
TEST_F(MuxerTest, AccurateClusterDurationExplicitLastFrameDuration) {
|
||||||
EXPECT_TRUE(SegmentInit(false, true));
|
EXPECT_TRUE(SegmentInit(false, true, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
@ -645,7 +647,7 @@ TEST_F(MuxerTest, AccurateClusterDurationExplicitLastFrameDuration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MuxerTest, AccurateClusterDurationTwoTracks) {
|
TEST_F(MuxerTest, AccurateClusterDurationTwoTracks) {
|
||||||
EXPECT_TRUE(SegmentInit(false, true));
|
EXPECT_TRUE(SegmentInit(false, true, false));
|
||||||
AddVideoTrack();
|
AddVideoTrack();
|
||||||
AddAudioTrack();
|
AddAudioTrack();
|
||||||
|
|
||||||
@ -698,6 +700,30 @@ TEST_F(MuxerTest, AccurateClusterDurationTwoTracks) {
|
|||||||
GetTestFilePath("accurate_cluster_duration_two_tracks.webm"), filename_));
|
GetTestFilePath("accurate_cluster_duration_two_tracks.webm"), filename_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MuxerTest, UseFixedSizeClusterTimecode) {
|
||||||
|
EXPECT_TRUE(SegmentInit(false, false, true));
|
||||||
|
AddVideoTrack();
|
||||||
|
|
||||||
|
Frame frame;
|
||||||
|
frame.Init(dummy_data_, kFrameLength);
|
||||||
|
frame.set_track_number(kVideoTrackNumber);
|
||||||
|
frame.set_timestamp(0);
|
||||||
|
frame.set_is_key(true);
|
||||||
|
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
|
||||||
|
segment_.ForceNewClusterOnNextFrame();
|
||||||
|
frame.set_timestamp(2000000);
|
||||||
|
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
|
||||||
|
segment_.ForceNewClusterOnNextFrame();
|
||||||
|
frame.set_timestamp(4000000);
|
||||||
|
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
|
||||||
|
segment_.Finalize();
|
||||||
|
|
||||||
|
CloseWriter();
|
||||||
|
|
||||||
|
EXPECT_TRUE(CompareFiles(GetTestFilePath("fixed_size_cluster_timecode.webm"),
|
||||||
|
filename_));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
BIN
testing/testdata/fixed_size_cluster_timecode.webm
vendored
Normal file
BIN
testing/testdata/fixed_size_cluster_timecode.webm
vendored
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user