Better support for audio only webm files.
Changed max_cluster_duration to 30 seconds so default command line will not crash on audio only WebM files. Added support to the sample muxer to output cues on the audio track. Created a muxer helper function to clean up the code a little. Change-Id: I2871836b64cef7defd10aa51a209b4abd9046832
This commit is contained in:
64
mkvmuxer.cpp
64
mkvmuxer.cpp
@@ -1128,7 +1128,7 @@ Segment::Segment(IMkvWriter* writer)
|
|||||||
has_video_(false),
|
has_video_(false),
|
||||||
header_written_(false),
|
header_written_(false),
|
||||||
last_timestamp_(0),
|
last_timestamp_(0),
|
||||||
max_cluster_duration_(0),
|
max_cluster_duration_(30000000000),
|
||||||
max_cluster_size_(0),
|
max_cluster_size_(0),
|
||||||
mode_(kFile),
|
mode_(kFile),
|
||||||
new_cluster_(true),
|
new_cluster_(true),
|
||||||
@@ -1252,34 +1252,8 @@ bool Segment::AddFrame(uint8* frame,
|
|||||||
bool is_key) {
|
bool is_key) {
|
||||||
assert(frame);
|
assert(frame);
|
||||||
|
|
||||||
if (!header_written_) {
|
if (!CheckHeaderInfo())
|
||||||
if (!WriteSegmentHeader())
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!seek_head_.AddSeekEntry(kMkvCluster,
|
|
||||||
writer_->Position() - payload_pos_))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (output_cues_ && cues_track_ == 0) {
|
|
||||||
// Check for a video track
|
|
||||||
for (uint32 i = 0; i < tracks_.track_entries_size(); ++i) {
|
|
||||||
const Track* const track = tracks_.GetTrackByIndex(i);
|
|
||||||
assert(track);
|
|
||||||
|
|
||||||
if (tracks_.TrackIsVideo(track->number())) {
|
|
||||||
cues_track_ = track->number();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set first track found
|
|
||||||
if (cues_track_ == 0) {
|
|
||||||
const Track* const track = tracks_.GetTrackByIndex(0);
|
|
||||||
assert(track);
|
|
||||||
cues_track_ = track->number();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the segment has a video track hold onto audio frames to make sure the
|
// If the segment has a video track hold onto audio frames to make sure the
|
||||||
// audio that is associated with the start time of a video key-frame is
|
// audio that is associated with the start time of a video key-frame is
|
||||||
@@ -1472,6 +1446,38 @@ bool Segment::WriteSegmentHeader() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Segment::CheckHeaderInfo() {
|
||||||
|
if (!header_written_) {
|
||||||
|
if (!WriteSegmentHeader())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!seek_head_.AddSeekEntry(kMkvCluster,
|
||||||
|
writer_->Position() - payload_pos_))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (output_cues_ && cues_track_ == 0) {
|
||||||
|
// Check for a video track
|
||||||
|
for (uint32 i = 0; i < tracks_.track_entries_size(); ++i) {
|
||||||
|
const Track* const track = tracks_.GetTrackByIndex(i);
|
||||||
|
assert(track);
|
||||||
|
|
||||||
|
if (tracks_.TrackIsVideo(track->number())) {
|
||||||
|
cues_track_ = track->number();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set first track found
|
||||||
|
if (cues_track_ == 0) {
|
||||||
|
const Track* const track = tracks_.GetTrackByIndex(0);
|
||||||
|
assert(track);
|
||||||
|
cues_track_ = track->number();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Segment::AddCuePoint(uint64 timestamp) {
|
bool Segment::AddCuePoint(uint64 timestamp) {
|
||||||
assert(cluster_list_size_ > 0);
|
assert(cluster_list_size_ > 0);
|
||||||
const Cluster* const cluster = cluster_list_[cluster_list_size_-1];
|
const Cluster* const cluster = cluster_list_[cluster_list_size_-1];
|
||||||
|
|||||||
@@ -592,6 +592,11 @@ class Segment {
|
|||||||
// nanoseconds of the cue's time. Returns true on success.
|
// nanoseconds of the cue's time. Returns true on success.
|
||||||
bool AddCuePoint(uint64 timestamp);
|
bool AddCuePoint(uint64 timestamp);
|
||||||
|
|
||||||
|
// Checks if header information has been output and initialized. If not it
|
||||||
|
// will output the Segment element and initialize the SeekHead elment and
|
||||||
|
// Cues elements.
|
||||||
|
bool CheckHeaderInfo();
|
||||||
|
|
||||||
// Adds the frame to our frame array.
|
// Adds the frame to our frame array.
|
||||||
bool QueueFrame(Frame* frame);
|
bool QueueFrame(Frame* frame);
|
||||||
|
|
||||||
@@ -648,8 +653,8 @@ class Segment {
|
|||||||
uint64 last_timestamp_;
|
uint64 last_timestamp_;
|
||||||
|
|
||||||
// Maximum time in nanoseconds for a cluster duration. This variable is a
|
// Maximum time in nanoseconds for a cluster duration. This variable is a
|
||||||
// guideline and some clusters may have a longer duration. Default is 0
|
// guideline and some clusters may have a longer duration. Default is 30
|
||||||
// which signifies that the muxer will decide.
|
// seconds.
|
||||||
uint64 max_cluster_duration_;
|
uint64 max_cluster_duration_;
|
||||||
|
|
||||||
// Maximum size in bytes for a cluster. This variable is a guideline and
|
// Maximum size in bytes for a cluster. This variable is a guideline and
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ void Usage() {
|
|||||||
printf(" 0 puts the muxer into file mode\n");
|
printf(" 0 puts the muxer into file mode\n");
|
||||||
printf(" -output_cues <int> >0 outputs cues element\n");
|
printf(" -output_cues <int> >0 outputs cues element\n");
|
||||||
printf(" -cues_on_video_track <int> >0 outputs cues on video track\n");
|
printf(" -cues_on_video_track <int> >0 outputs cues on video track\n");
|
||||||
|
printf(" -cues_on_audio_track <int> >0 outputs cues on audio track\n");
|
||||||
printf(" 0 outputs cues on audio track\n");
|
printf(" 0 outputs cues on audio track\n");
|
||||||
printf(" -max_cluster_duration <double> in seconds\n");
|
printf(" -max_cluster_duration <double> in seconds\n");
|
||||||
printf(" -max_cluster_size <int> in bytes\n");
|
printf(" -max_cluster_size <int> in bytes\n");
|
||||||
@@ -59,6 +60,7 @@ int main(int argc, char* argv[]) {
|
|||||||
bool live_mode = false;
|
bool live_mode = false;
|
||||||
bool output_cues = true;
|
bool output_cues = true;
|
||||||
bool cues_on_video_track = true;
|
bool cues_on_video_track = true;
|
||||||
|
bool cues_on_audio_track = true;
|
||||||
uint64 max_cluster_duration = 0;
|
uint64 max_cluster_duration = 0;
|
||||||
uint64 max_cluster_size = 0;
|
uint64 max_cluster_size = 0;
|
||||||
bool switch_tracks = false;
|
bool switch_tracks = false;
|
||||||
@@ -89,6 +91,8 @@ int main(int argc, char* argv[]) {
|
|||||||
output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
} else if (!strcmp("-cues_on_video_track", argv[i])) {
|
} else if (!strcmp("-cues_on_video_track", argv[i])) {
|
||||||
cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-cues_on_audio_track", argv[i])) {
|
||||||
|
cues_on_audio_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
} else if (!strcmp("-max_cluster_duration", argv[i])) {
|
} else if (!strcmp("-max_cluster_duration", argv[i])) {
|
||||||
const double seconds = strtod(argv[++i], &end);
|
const double seconds = strtod(argv[++i], &end);
|
||||||
max_cluster_duration =
|
max_cluster_duration =
|
||||||
@@ -278,7 +282,8 @@ int main(int argc, char* argv[]) {
|
|||||||
if (cues_on_video_track) {
|
if (cues_on_video_track) {
|
||||||
if (vid_track)
|
if (vid_track)
|
||||||
muxer_segment.CuesTrack(vid_track);
|
muxer_segment.CuesTrack(vid_track);
|
||||||
} else {
|
}
|
||||||
|
if (cues_on_audio_track) {
|
||||||
if (aud_track)
|
if (aud_track)
|
||||||
muxer_segment.CuesTrack(aud_track);
|
muxer_segment.CuesTrack(aud_track);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user