From b9e0534066ed8877272d0bb2669b0ad18b04af31 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Wed, 14 Jan 2004 19:42:57 +0000 Subject: [PATCH] Write cues for audio only files for each track as well (only one entry every two seconds). --- ChangeLog | 5 ++ src/cluster_helper.cpp | 12 ++- src/output/p_passthrough.cpp | 2 +- src/pr_generic.cpp | 104 +++--------------------- src/pr_generic.h | 149 ++++++++++++++++++++++++----------- 5 files changed, 130 insertions(+), 142 deletions(-) diff --git a/ChangeLog b/ChangeLog index a21f16b0e..4380f340d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-01-14 Moritz Bunkus + + * mkvmerge: new feature: Write cues for audio-only files as well + (not more than one cue entry during a two seconds period). + 2004-01-12 Moritz Bunkus * mkvmerge: bug fix: The default track flags could not be diff --git a/src/cluster_helper.cpp b/src/cluster_helper.cpp index 18b24fec3..74f4200e1 100644 --- a/src/cluster_helper.cpp +++ b/src/cluster_helper.cpp @@ -529,12 +529,20 @@ int cluster_helper_c::render() { // I frames were requested and this is an I frame... if (((source->get_cue_creation() == CUES_IFRAMES) && (pack->bref == -1)) || - // ... or if the user requested entries for all frames. - (source->get_cue_creation() == CUES_ALL)) { + // ... or if the user requested entries for all frames... + (source->get_cue_creation() == CUES_ALL) || + // ... or if this is an audio track, there is no video track and the + // last cue entry was created more than 2s ago. + ((source->get_cue_creation() == CUES_SPARSE) && + (source->get_track_type() == track_audio) && !video_track_present && + ((source->get_last_cue_timecode() < 0) || + ((pack->assigned_timecode - source->get_last_cue_timecode()) >= + 2000)))) { kax_cues->AddBlockGroup(*new_block_group); num_cue_elements++; num_cue_elements_here++; cue_writing_requested = 1; + source->set_last_cue_timecode(pack->assigned_timecode); } } diff --git a/src/output/p_passthrough.cpp b/src/output/p_passthrough.cpp index aa393f2f9..260758f1f 100644 --- a/src/output/p_passthrough.cpp +++ b/src/output/p_passthrough.cpp @@ -51,7 +51,7 @@ passthrough_packetizer_c::process(unsigned char *buf, int64_t duration, int64_t bref, int64_t fref) { - process(buf, size, timecode, duration, bref, fref, false); + return process(buf, size, timecode, duration, bref, fref, false); } int diff --git a/src/pr_generic.cpp b/src/pr_generic.cpp index 805774c52..5e59fe23d 100644 --- a/src/pr_generic.cpp +++ b/src/pr_generic.cpp @@ -61,6 +61,7 @@ generic_packetizer_c::generic_packetizer_c(generic_reader_c *nreader, free_refs = -1; enqueued_bytes = 0; safety_last_timecode = 0; + last_cue_timecode = -1; // Let's see if the user specified audio sync for this track. found = false; @@ -271,34 +272,6 @@ void generic_packetizer_c::set_tag_track_uid() { } } -int generic_packetizer_c::read() { - return reader->read(this); -} - -void generic_packetizer_c::reset() { - track_entry = NULL; -} - -void generic_packetizer_c::set_cue_creation(int ncreate_cue_data) { - ti->cues = ncreate_cue_data; -} - -int generic_packetizer_c::get_cue_creation() { - return ti->cues; -} - -void generic_packetizer_c::set_free_refs(int64_t nfree_refs) { - free_refs = nfree_refs; -} - -int64_t generic_packetizer_c::get_free_refs() { - return free_refs; -} - -KaxTrackEntry *generic_packetizer_c::get_track_entry() { - return track_entry; -} - int generic_packetizer_c::set_uid(uint32_t uid) { if (is_unique_uint32(uid)) { add_unique_uint32(uid); @@ -315,20 +288,14 @@ int generic_packetizer_c::set_uid(uint32_t uid) { void generic_packetizer_c::set_track_type(int type) { htrack_type = type; + if ((type == track_audio) && (ti->cues == CUES_UNSPECIFIED)) + ti->cues = CUES_SPARSE; if (ti->default_track) set_as_default_track(type, DEFAULT_TRACK_PRIORITY_CMDLINE); else set_as_default_track(type, DEFAULT_TRACK_PRIORITY_FROM_TYPE); } -int generic_packetizer_c::get_track_type() { - return htrack_type; -} - -int generic_packetizer_c::get_track_num() { - return hserialno; -} - void generic_packetizer_c::set_track_name(const char *name) { safefree(ti->track_name); if (name == NULL) { @@ -468,10 +435,6 @@ void generic_packetizer_c::set_video_display_height(int height) { } } -void generic_packetizer_c::set_video_aspect_ratio(float ar) { - ti->aspect_ratio = ar; -} - void generic_packetizer_c::set_as_default_track(int type, int priority) { int idx; @@ -504,10 +467,6 @@ void generic_packetizer_c::set_language(const char *language) { (&GetChild(*track_entry))) = ti->language; } -void generic_packetizer_c::set_default_compression_method(int method) { - hcompression = method; -} - void generic_packetizer_c::set_headers() { int idx, disp_width, disp_height; KaxTag *tag; @@ -693,10 +652,6 @@ void generic_packetizer_c::set_headers() { } } -void generic_packetizer_c::duplicate_data_on_add(bool duplicate) { - duplicate_data = duplicate; -} - void generic_packetizer_c::add_packet(unsigned char *data, int length, int64_t timecode, int64_t duration, @@ -772,21 +727,6 @@ packet_t *generic_packetizer_c::get_packet() { return pack; } -int generic_packetizer_c::packet_available() { - return packet_queue.size(); -} - -int64_t generic_packetizer_c::get_smallest_timecode() { - if (packet_queue.size() == 0) - return 0x0FFFFFFF; - - return packet_queue.front()->timecode; -} - -int64_t generic_packetizer_c::get_queued_bytes() { - return enqueued_bytes; -} - void generic_packetizer_c::dump_packet(const void *buffer, int size) { char *path; mm_io_c *out; @@ -835,8 +775,9 @@ void generic_packetizer_c::parse_ext_timecode_file(const char *name) { delete in; } -void generic_packetizer_c:: -parse_ext_timecode_file_v1(mm_io_c *in, const char *name) { +void +generic_packetizer_c::parse_ext_timecode_file_v1(mm_io_c *in, + const char *name) { string line; timecode_range_c t; vector fields; @@ -959,8 +900,9 @@ parse_ext_timecode_file_v1(mm_io_c *in, const char *name) { iit->start_frame, iit->end_frame, iit->fps, iit->base_timecode); } -void generic_packetizer_c:: -parse_ext_timecode_file_v2(mm_io_c *in, const char *name) { +void +generic_packetizer_c::parse_ext_timecode_file_v2(mm_io_c *in, + const char *name) { int line_no; string line; double timecode; @@ -1031,17 +973,6 @@ int64_t generic_packetizer_c::get_next_timecode(int64_t timecode) { return timecode; } -bool generic_packetizer_c::needs_negative_displacement(float duration) { - return ((initial_displacement < 0) && - (ti->async.displacement > initial_displacement)); -} - -bool generic_packetizer_c::needs_positive_displacement(float duration) { - return ((initial_displacement > 0) && - (iabs(ti->async.displacement - initial_displacement) > - (duration / 2))); -} - void generic_packetizer_c::displace(float by_ms) { ti->async.displacement += (int64_t)by_ms; if (initial_displacement < 0) { @@ -1054,14 +985,6 @@ void generic_packetizer_c::displace(float by_ms) { //-------------------------------------------------------------------- -generic_reader_c::generic_reader_c(track_info_c *nti) { - ti = new track_info_c(*nti); -} - -generic_reader_c::~generic_reader_c() { - delete ti; -} - bool generic_reader_c::demuxing_requested(char type, int64_t id) { vector *tracks; int i; @@ -1129,15 +1052,6 @@ track_info_c::track_info_c(): track_order = new vector; } -track_info_c::track_info_c(const track_info_c &src): - initialized(false) { - *this = src; -} - -track_info_c::~track_info_c() { - free_contents(); -} - void track_info_c::free_contents() { uint32_t i; diff --git a/src/pr_generic.h b/src/pr_generic.h index 171e450e4..dd205b18d 100644 --- a/src/pr_generic.h +++ b/src/pr_generic.h @@ -39,10 +39,19 @@ using namespace libmatroska; using namespace std; +// CUES_* control the creation of cue entries for a track. +// UNSPECIFIED: is used for command line parsing. +// NONE: don't create any cue entries. +// IFRAMES: Create cue entries for all I frames. +// ALL: Create cue entries for all frames (not really useful). +// SPARSE: Create cue entries for I frames if no video track exists, but +// create at most one cue entries every two seconds. Used for +// audio only files. #define CUES_UNSPECIFIED -1 #define CUES_NONE 0 #define CUES_IFRAMES 1 #define CUES_ALL 2 +#define CUES_SPARSE 3 typedef struct { int displacement; @@ -157,8 +166,13 @@ public: public: track_info_c(); - track_info_c(const track_info_c &src); - virtual ~track_info_c(); + track_info_c(const track_info_c &src): + initialized(false) { + *this = src; + } + virtual ~track_info_c() { + free_contents(); + } track_info_c &operator =(const track_info_c &src); virtual void free_contents(); @@ -174,7 +188,31 @@ public: } }; -class generic_reader_c; +class generic_packetizer_c; + +class generic_reader_c { +protected: + track_info_c *ti; +public: + generic_reader_c(track_info_c *nti) { + ti = new track_info_c(*nti); + } + virtual ~generic_reader_c() { + delete ti; + } + virtual int read(generic_packetizer_c *ptzr) = 0; + virtual int display_priority() = 0; + virtual void display_progress(bool final = false) = 0; + virtual void set_headers() = 0; + virtual void identify() = 0; + + virtual void add_attachments(KaxAttachments *a) { + }; +// virtual void set_tag_track_uids() = 0; + +protected: + virtual bool demuxing_requested(char type, int64_t id); +}; class generic_packetizer_c { protected: @@ -216,16 +254,23 @@ protected: int ext_timecodes_version; bool ext_timecodes_warning_printed; + int64_t last_cue_timecode; + public: generic_packetizer_c(generic_reader_c *nreader, track_info_c *nti) throw (error_c); virtual ~generic_packetizer_c(); - virtual int read(); + virtual int read() { + return reader->read(this); + } + virtual void reset() { + track_entry = NULL; + } - virtual void reset(); - - virtual void duplicate_data_on_add(bool duplicate); + virtual void duplicate_data_on_add(bool duplicate) { + duplicate_data = duplicate; + } virtual void add_packet(unsigned char *data, int lenth, int64_t timecode, int64_t duration, bool duration_mandatory = false, int64_t bref = -1, int64_t fref = -1, @@ -233,14 +278,25 @@ public: copy_packet_mode_t copy_this = cp_default); virtual void drop_packet(unsigned char *data, copy_packet_mode_t copy_this); virtual packet_t *get_packet(); - virtual int packet_available(); + virtual int packet_available() { + return packet_queue.size(); + } virtual void flush() { - }; - virtual int64_t get_smallest_timecode(); - virtual int64_t get_queued_bytes(); + } + virtual int64_t get_smallest_timecode() { + return (packet_queue.size() == 0) ? 0x0FFFFFFF : + packet_queue.front()->timecode; + } + virtual int64_t get_queued_bytes() { + return enqueued_bytes; + } - virtual void set_free_refs(int64_t nfree_refs); - virtual int64_t get_free_refs(); + virtual void set_free_refs(int64_t nfree_refs) { + free_refs = nfree_refs; + } + virtual int64_t get_free_refs() { + return free_refs; + } virtual void set_headers(); virtual int process(unsigned char *data, int size, int64_t timecode = -1, int64_t length = -1, @@ -248,15 +304,31 @@ public: virtual void dump_debug_info() = 0; - virtual void set_cue_creation(int create_cue_data); - virtual int get_cue_creation(); + virtual void set_cue_creation(int create_cue_data) { + ti->cues = create_cue_data; + } + virtual int get_cue_creation() { + return ti->cues; + } + virtual int64_t get_last_cue_timecode() { + return last_cue_timecode; + } + virtual void set_last_cue_timecode(int64_t timecode) { + last_cue_timecode = timecode; + } - virtual KaxTrackEntry *get_track_entry(); - virtual int get_track_num(); + virtual KaxTrackEntry *get_track_entry() { + return track_entry; + } + virtual int get_track_num() { + return hserialno; + } virtual int set_uid(uint32_t uid); virtual void set_track_type(int type); - virtual int get_track_type(); + virtual int get_track_type() { + return htrack_type; + } virtual void set_language(const char *language); virtual void set_codec_id(const char *id); @@ -276,7 +348,9 @@ public: virtual void set_video_pixel_height(int height); virtual void set_video_display_width(int width); virtual void set_video_display_height(int height); - virtual void set_video_aspect_ratio(float ar); + virtual void set_video_aspect_ratio(float ar) { + ti->aspect_ratio = ar; + } virtual void set_as_default_track(int type, int priority); @@ -284,43 +358,30 @@ public: virtual void set_track_name(const char *name); - virtual void set_default_compression_method(int method); + virtual void set_default_compression_method(int method) { + hcompression = method; + } virtual int64_t get_next_timecode(int64_t timecode); virtual void parse_ext_timecode_file(const char *name); virtual void parse_ext_timecode_file_v1(mm_io_c *in, const char *name); virtual void parse_ext_timecode_file_v2(mm_io_c *in, const char *name); - virtual bool needs_negative_displacement(float duration); - virtual bool needs_positive_displacement(float duration); + virtual bool needs_negative_displacement(float duration) { + return ((initial_displacement < 0) && + (ti->async.displacement > initial_displacement)); + } + virtual bool needs_positive_displacement(float duration) { + return ((initial_displacement > 0) && + (iabs(ti->async.displacement - initial_displacement) > + (duration / 2))); + } virtual void displace(float by_ms); protected: virtual void dump_packet(const void *buffer, int size); }; -class generic_reader_c { -protected: - track_info_c *ti; -public: - generic_reader_c(track_info_c *nti); - virtual ~generic_reader_c(); - virtual int read(generic_packetizer_c *ptzr) = 0; - virtual int display_priority() = 0; - virtual void display_progress(bool final = false) = 0; - virtual void set_headers() = 0; - virtual void identify() = 0; - - virtual void add_attachments(KaxAttachments *a) { - }; -// virtual void set_tag_track_uids() = 0; - -protected: - virtual bool demuxing_requested(char type, int64_t id); -}; - -track_info_c *duplicate_track_info(track_info_c *src); -void free_track_info(track_info_c *ti); void set_pass_data(track_info_c *ti, unsigned char *data, int size); unsigned char *retrieve_pass_data(track_info_c *ti, int &size);