diff --git a/mkvmuxer.cpp b/mkvmuxer.cpp index 6730414..42aab31 100644 --- a/mkvmuxer.cpp +++ b/mkvmuxer.cpp @@ -662,7 +662,18 @@ Tracks::~Tracks() { } } -bool Tracks::AddTrack(Track* track) { +bool Tracks::AddTrack(Track* track, int32 number) { + if (number < 0) + return false; + + int32 track_num = number; + + // Check to make sure a track does not already have |track_num|. + for (uint32 i = 0; i < track_entries_size_; ++i) { + if (track_entries_[i]->number() == track_num) + return false; + } + const uint32 count = track_entries_size_ + 1; Track** const track_entries = new (std::nothrow) Track*[count]; @@ -675,7 +686,24 @@ bool Tracks::AddTrack(Track* track) { delete [] track_entries_; - track->set_number(count); + // Find the lowest availible track number > 0. + if (track_num == 0) { + track_num = count; + + // Check to make sure a track does not already have |track_num|. + bool exit = false; + do { + exit = true; + for (uint32 i = 0; i < track_entries_size_; ++i) { + if (track_entries[i]->number() == track_num) { + track_num++; + exit = false; + break; + } + } + } while (!exit); + } + track->set_number(track_num); track_entries_ = track_entries; track_entries_[track_entries_size_] = track; @@ -1128,7 +1156,7 @@ Segment::Segment(IMkvWriter* writer) has_video_(false), header_written_(false), last_timestamp_(0), - max_cluster_duration_(30000000000), + max_cluster_duration_(kDefaultMaxClusterDuration), max_cluster_size_(0), mode_(kFile), new_cluster_(true), @@ -1215,6 +1243,10 @@ bool Segment::Finalize() { } uint64 Segment::AddVideoTrack(int32 width, int32 height) { + return AddVideoTrack(width, height, 0); +} + +uint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) { VideoTrack* const vid_track = new (std::nothrow) VideoTrack(); if (!vid_track) return 0; @@ -1224,13 +1256,19 @@ uint64 Segment::AddVideoTrack(int32 width, int32 height) { vid_track->set_width(width); vid_track->set_height(height); - tracks_.AddTrack(vid_track); + tracks_.AddTrack(vid_track, number); has_video_ = true; return vid_track->number(); } uint64 Segment::AddAudioTrack(int32 sample_rate, int32 channels) { + return AddAudioTrack(sample_rate, channels, 0); +} + +uint64 Segment::AddAudioTrack(int32 sample_rate, + int32 channels, + int32 number) { AudioTrack* const aud_track = new (std::nothrow) AudioTrack(); if (!aud_track) return 0; @@ -1240,7 +1278,7 @@ uint64 Segment::AddAudioTrack(int32 sample_rate, int32 channels) { aud_track->set_sample_rate(sample_rate); aud_track->set_channels(channels); - tracks_.AddTrack(aud_track); + tracks_.AddTrack(aud_track, number); return aud_track->number(); } diff --git a/mkvmuxer.hpp b/mkvmuxer.hpp index 77bc3b8..ba7e4cc 100644 --- a/mkvmuxer.hpp +++ b/mkvmuxer.hpp @@ -335,8 +335,10 @@ class Tracks { ~Tracks(); // Adds a Track element to the Tracks object. |track| will be owned and - // deleted by the Tracks object. Returns true on success. - bool AddTrack(Track* track); + // deleted by the Tracks object. Returns true on success. |number| is the + // number to use for the track. |number| must be >= 0. If |number| == 0 + // then the muxer will decide on the track number. + bool AddTrack(Track* track, int32 number); // Returns the track by index. Returns NULL if there is no track match. const Track* GetTrackByIndex(uint32 idx) const; @@ -525,6 +527,8 @@ class Segment { kFile = 0x2 }; + const static uint64 kDefaultMaxClusterDuration = 30000000000ULL; + explicit Segment(IMkvWriter* writer); virtual ~Segment(); @@ -532,6 +536,12 @@ class Segment { // success, 0 on error. uint64 AddAudioTrack(int32 sample_rate, int32 channels); + // Adds an audio track to the segment. Returns the number of the track on + // success, 0 on error. |number| is the number to use for the audio track. + // |number| must be >= 0. If |number| == 0 then the muxer will decide on + // the track number. + uint64 AddAudioTrack(int32 sample_rate, int32 channels, int32 number); + // Adds a frame to be output in the file. Returns true on success. // Inputs: // frame: Pointer to the data @@ -550,6 +560,12 @@ class Segment { // success, 0 on error. uint64 AddVideoTrack(int32 width, int32 height); + // Adds a video track to the segment. Returns the number of the track on + // success, 0 on error. |number| is the number to use for the video track. + // |number| must be >= 0. If |number| == 0 then the muxer will decide on + // the track number. + uint64 AddVideoTrack(int32 width, int32 height, int32 number); + // Sets which track to use for the Cues element. Must have added the track // before calling this function. Returns true on success. |track_number| is // returned by the Add track functions. diff --git a/sample_muxer/sample_muxer.cpp b/sample_muxer/sample_muxer.cpp index 95b29a9..449e625 100644 --- a/sample_muxer/sample_muxer.cpp +++ b/sample_muxer/sample_muxer.cpp @@ -36,6 +36,8 @@ void Usage() { printf(" -max_cluster_duration in seconds\n"); printf(" -max_cluster_size in bytes\n"); printf(" -switch_tracks >0 switches tracks in output\n"); + printf(" -audio_track_number >0 Changes the audio track number\n"); + printf(" -video_track_number >0 Changes the video track number\n"); printf("\n"); printf("Video options:\n"); printf(" -display_width Display width in pixels\n"); @@ -64,6 +66,8 @@ int main(int argc, char* argv[]) { uint64 max_cluster_duration = 0; uint64 max_cluster_size = 0; bool switch_tracks = false; + int audio_track_number = 0; // 0 tells muxer to decide. + int video_track_number = 0; // 0 tells muxer to decide. bool output_cues_block_number = true; @@ -101,6 +105,10 @@ int main(int argc, char* argv[]) { max_cluster_size = strtol(argv[++i], &end, 10); } else if (!strcmp("-switch_tracks", argv[i])) { switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true; + } else if (!strcmp("-audio_track_number", argv[i])) { + audio_track_number = strtol(argv[++i], &end, 10); + } else if (!strcmp("-video_track_number", argv[i])) { + video_track_number = strtol(argv[++i], &end, 10); } else if (!strcmp("-display_width", argv[i])) { display_width = strtol(argv[++i], &end, 10); } else if (!strcmp("-display_height", argv[i])) { @@ -206,7 +214,8 @@ int main(int argc, char* argv[]) { // Add the video track to the muxer vid_track = muxer_segment.AddVideoTrack(static_cast(width), - static_cast(height)); + static_cast(height), + video_track_number); if (!vid_track) { printf("\n Could not add video track.\n"); return -1; @@ -243,7 +252,8 @@ int main(int argc, char* argv[]) { // Add the audio track to the muxer aud_track = muxer_segment.AddAudioTrack(static_cast(sample_rate), - static_cast(channels)); + static_cast(channels), + audio_track_number); if (!aud_track) { printf("\n Could not add audio track.\n"); return -1; @@ -279,14 +289,10 @@ int main(int argc, char* argv[]) { // Set Cues element attributes mkvmuxer::Cues* const cues = muxer_segment.GetCues(); cues->set_output_block_number(output_cues_block_number); - if (cues_on_video_track) { - if (vid_track) - muxer_segment.CuesTrack(vid_track); - } - if (cues_on_audio_track) { - if (aud_track) - muxer_segment.CuesTrack(aud_track); - } + if (cues_on_video_track && vid_track) + muxer_segment.CuesTrack(vid_track); + if (cues_on_audio_track && aud_track) + muxer_segment.CuesTrack(aud_track); // Write clusters unsigned char* data = NULL;