summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/matroskaenc.c74
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;