From a09f15f00e233fd0873120078adbca0f21fcb8b3 Mon Sep 17 00:00:00 2001 From: Frank Galligan Date: Sun, 14 Aug 2011 10:49:50 -0400 Subject: [PATCH] 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 --- mkvmuxer.cpp | 64 +++++++++++++++++++---------------- mkvmuxer.hpp | 9 +++-- sample_muxer/sample_muxer.cpp | 7 +++- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/mkvmuxer.cpp b/mkvmuxer.cpp index 383751c..6730414 100644 --- a/mkvmuxer.cpp +++ b/mkvmuxer.cpp @@ -1128,7 +1128,7 @@ Segment::Segment(IMkvWriter* writer) has_video_(false), header_written_(false), last_timestamp_(0), - max_cluster_duration_(0), + max_cluster_duration_(30000000000), max_cluster_size_(0), mode_(kFile), new_cluster_(true), @@ -1252,34 +1252,8 @@ bool Segment::AddFrame(uint8* frame, bool is_key) { assert(frame); - 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(); - } - } - } + if (!CheckHeaderInfo()) + return false; // 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 @@ -1472,6 +1446,38 @@ bool Segment::WriteSegmentHeader() { 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) { assert(cluster_list_size_ > 0); const Cluster* const cluster = cluster_list_[cluster_list_size_-1]; diff --git a/mkvmuxer.hpp b/mkvmuxer.hpp index 4a2c76c..77bc3b8 100644 --- a/mkvmuxer.hpp +++ b/mkvmuxer.hpp @@ -592,6 +592,11 @@ class Segment { // nanoseconds of the cue's time. Returns true on success. 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. bool QueueFrame(Frame* frame); @@ -648,8 +653,8 @@ class Segment { uint64 last_timestamp_; // Maximum time in nanoseconds for a cluster duration. This variable is a - // guideline and some clusters may have a longer duration. Default is 0 - // which signifies that the muxer will decide. + // guideline and some clusters may have a longer duration. Default is 30 + // seconds. uint64 max_cluster_duration_; // Maximum size in bytes for a cluster. This variable is a guideline and diff --git a/sample_muxer/sample_muxer.cpp b/sample_muxer/sample_muxer.cpp index b0f9386..95b29a9 100644 --- a/sample_muxer/sample_muxer.cpp +++ b/sample_muxer/sample_muxer.cpp @@ -31,6 +31,7 @@ void Usage() { printf(" 0 puts the muxer into file mode\n"); printf(" -output_cues >0 outputs cues element\n"); printf(" -cues_on_video_track >0 outputs cues on video track\n"); + printf(" -cues_on_audio_track >0 outputs cues on audio track\n"); printf(" 0 outputs cues on audio track\n"); printf(" -max_cluster_duration in seconds\n"); printf(" -max_cluster_size in bytes\n"); @@ -59,6 +60,7 @@ int main(int argc, char* argv[]) { bool live_mode = false; bool output_cues = true; bool cues_on_video_track = true; + bool cues_on_audio_track = true; uint64 max_cluster_duration = 0; uint64 max_cluster_size = 0; bool switch_tracks = false; @@ -89,6 +91,8 @@ int main(int argc, char* argv[]) { output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true; } else if (!strcmp("-cues_on_video_track", argv[i])) { 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])) { const double seconds = strtod(argv[++i], &end); max_cluster_duration = @@ -278,7 +282,8 @@ int main(int argc, char* argv[]) { if (cues_on_video_track) { if (vid_track) muxer_segment.CuesTrack(vid_track); - } else { + } + if (cues_on_audio_track) { if (aud_track) muxer_segment.CuesTrack(aud_track); }