diff options
-rw-r--r-- | libavformat/matroskaenc.c | 74 |
1 files changed, 33 insertions, 41 deletions
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 433a2b5579..a2901e6aa5 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -170,12 +170,8 @@ typedef struct MatroskaMuxContext { * offset, 4 bytes for target EBML ID */ #define MAX_SEEKENTRY_SIZE 21 -/** per-cuepoint-track - 5 1-byte EBML IDs, 5 1-byte EBML sizes, 3 8-byte uint max - * and one 1-byte uint for the track number (this assumes MAX_TRACKS to be <= 255) */ -#define MAX_CUETRACKPOS_SIZE 35 - -/** per-cuepoint - 1 1-byte EBML ID, 1 1-byte EBML size, 8-byte uint max */ -#define MAX_CUEPOINT_CONTENT_SIZE(num_tracks) 10 + MAX_CUETRACKPOS_SIZE * num_tracks +/** 4 * (1-byte EBML ID, 1-byte EBML size, 8-byte uint max) */ +#define MAX_CUETRACKPOS_SIZE 40 /** Seek preroll value for opus */ #define OPUS_SEEK_PREROLL 80000000 @@ -506,58 +502,54 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int tracknum, i static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tracks, int num_tracks) { MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *dyn_cp, *pb = s->pb; + AVIOContext *dyn_cp, *pb = s->pb, *cuepoint; int64_t currentpos; - int i, j, ret; + int ret; currentpos = avio_tell(pb); ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES); if (ret < 0) return ret; - for (i = 0; i < cues->num_entries; i++) { - ebml_master cuepoint, track_positions; - mkv_cuepoint *entry = &cues->entries[i]; - uint64_t pts = entry->pts; - int ctp_nb = 0; - - // Calculate the number of entries, so we know the element size - for (j = 0; j < num_tracks; j++) - tracks[j].has_cue = 0; - for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { - int idx = entry[j].stream_idx; + ret = avio_open_dyn_buf(&cuepoint); + if (ret < 0) { + ffio_free_dyn_buf(&dyn_cp); + return ret; + } - av_assert0(idx >= 0 && idx < num_tracks); - if (tracks[idx].has_cue && s->streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) - continue; - tracks[idx].has_cue = 1; - ctp_nb ++; - } + for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries; + entry < end;) { + uint64_t pts = entry->pts; + uint8_t *buf; + int size; - cuepoint = start_ebml_master(dyn_cp, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_CONTENT_SIZE(ctp_nb)); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUETIME, pts); + put_ebml_uint(cuepoint, MATROSKA_ID_CUETIME, pts); // put all the entries from different tracks that have the exact same // timestamp into the same CuePoint - for (j = 0; j < num_tracks; j++) + for (int j = 0; j < num_tracks; j++) tracks[j].has_cue = 0; - for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { - int idx = entry[j].stream_idx; + do { + ebml_master track_positions; + int idx = entry->stream_idx; + av_assert0(idx >= 0 && idx < num_tracks); if (tracks[idx].has_cue && s->streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; tracks[idx].has_cue = 1; - track_positions = start_ebml_master(dyn_cp, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUETRACK , entry[j].tracknum ); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUECLUSTERPOSITION , entry[j].cluster_pos); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUERELATIVEPOSITION, entry[j].relative_pos); - if (entry[j].duration != -1) - put_ebml_uint(dyn_cp, MATROSKA_ID_CUEDURATION , entry[j].duration); - end_ebml_master(dyn_cp, track_positions); - } - i += j - 1; - end_ebml_master(dyn_cp, cuepoint); - } + track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); + put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , entry->tracknum ); + put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos); + put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos); + if (entry->duration != -1) + put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration); + end_ebml_master(cuepoint, track_positions); + } while (++entry < end && entry->pts == pts); + size = avio_get_dyn_buf(cuepoint, &buf); + put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size); + ffio_reset_dyn_buf(cuepoint); + } + ffio_free_dyn_buf(&cuepoint); end_ebml_master_crc32(pb, &dyn_cp, mkv); return currentpos; |