put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , tracks[idx].track_num);
put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos);
put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos);
put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , tracks[idx].track_num);
put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos);
put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos);
put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration);
end_ebml_master(cuepoint, track_positions);
} while (++entry < end && entry->pts == pts);
put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration);
end_ebml_master(cuepoint, track_positions);
} while (++entry < end && entry->pts == pts);
+static int mkv_new_chapter_ids_needed(const AVFormatContext *s)
+{
+ for (unsigned i = 0; i < s->nb_chapters; i++) {
+ if (!s->chapters[i]->id)
+ return 1;
+ for (unsigned j = 0; j < i; j++)
+ if (s->chapters[j]->id == s->chapters[i]->id)
+ return 1;
+ }
+ return 0;
+}
+
static int mkv_write_chapters(AVFormatContext *s)
{
MatroskaMuxContext *mkv = s->priv_data;
AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb;
ebml_master editionentry;
static int mkv_write_chapters(AVFormatContext *s)
{
MatroskaMuxContext *mkv = s->priv_data;
AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb;
ebml_master editionentry;
ebml_master chapteratom, chapterdisplay;
const AVChapter *c = s->chapters[i];
int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale);
int64_t chapterend = av_rescale_q(c->end, c->time_base, scale);
const AVDictionaryEntry *t;
ebml_master chapteratom, chapterdisplay;
const AVChapter *c = s->chapters[i];
int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale);
int64_t chapterend = av_rescale_q(c->end, c->time_base, scale);
const AVDictionaryEntry *t;
if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) {
av_log(s, AV_LOG_ERROR,
"Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) {
av_log(s, AV_LOG_ERROR,
"Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
- put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID,
- (uint32_t)c->id + chapter_id_offset);
+ put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, uid);
put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) {
ret = mkv_write_tag(mkv, c->metadata, tags, NULL,
if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) {
ret = mkv_write_tag(mkv, c->metadata, tags, NULL,
put_ebml_string(dyn_cp, MATROSKA_ID_FILEDESC, t->value);
if (!(t = av_dict_get(st->metadata, "filename", NULL, 0))) {
av_log(s, AV_LOG_ERROR, "Attachment stream %d has no filename tag.\n", i);
put_ebml_string(dyn_cp, MATROSKA_ID_FILEDESC, t->value);
if (!(t = av_dict_get(st->metadata, "filename", NULL, 0))) {
av_log(s, AV_LOG_ERROR, "Attachment stream %d has no filename tag.\n", i);
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
mkv_track *track = &mkv->tracks[pkt->stream_index];
uint8_t *data = NULL, *side_data = NULL;
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
mkv_track *track = &mkv->tracks[pkt->stream_index];
uint8_t *data = NULL, *side_data = NULL;
int err = 0, offset = 0, size = pkt->size;
int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
uint64_t additional_id;
int err = 0, offset = 0, size = pkt->size;
int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
uint64_t additional_id;
- buffer_size_t id_size, settings_size;
- int size;
+ size_t id_size, settings_size;
+ int size, id_size_int, settings_size_int;
const char *id, *settings;
int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
const int flags = 0;
const char *id, *settings;
int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
const int flags = 0;
size = id_size + 1 + settings_size + 1 + pkt->size;
/* The following string is identical to the one in mkv_write_block so that
size = id_size + 1 + settings_size + 1 + pkt->size;
/* The following string is identical to the one in mkv_write_block so that
put_ebml_num(pb, track->track_num, track->track_num_size);
avio_wb16(pb, ts - mkv->cluster_pts);
avio_w8(pb, flags);
put_ebml_num(pb, track->track_num, track->track_num_size);
avio_wb16(pb, ts - mkv->cluster_pts);
avio_w8(pb, flags);
- avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size, id, settings_size, settings, pkt->size, pkt->data);
+
+ id_size_int = id_size;
+ settings_size_int = settings_size;
+ avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size_int, id, settings_size_int, settings, pkt->size, pkt->data);
put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, pkt->duration);
end_ebml_master(pb, blockgroup);
put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, pkt->duration);
end_ebml_master(pb, blockgroup);
mkv_track *track = &mkv->tracks[pkt->stream_index];
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
uint8_t *side_data;
mkv_track *track = &mkv->tracks[pkt->stream_index];
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
uint8_t *side_data;
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
mkv_track *track = &mkv->tracks[pkt->stream_index];
int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
mkv_track *track = &mkv->tracks[pkt->stream_index];
int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
if (ret < 0)
return ret;
if (keyframe && IS_SEEKABLE(s->pb, mkv) &&
ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
if (ret < 0)
return ret;
if (keyframe && IS_SEEKABLE(s->pb, mkv) &&
- (par->codec_type == AVMEDIA_TYPE_VIDEO || !mkv->have_video && !track->has_cue)) {
+ (par->codec_type == AVMEDIA_TYPE_VIDEO ||
+ par->codec_type == AVMEDIA_TYPE_SUBTITLE ||
+ !mkv->have_video && !track->has_cue)) {
ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts,
ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts,
} else {
ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP,
mkv_blockgroup_size(pkt->size,
track->track_num_size));
} else {
ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP,
mkv_blockgroup_size(pkt->size,
track->track_num_size));
-#if FF_API_CONVERGENCE_DURATION
-FF_DISABLE_DEPRECATION_WARNINGS
- /* For backward compatibility, prefer convergence_duration. */
- if (pkt->convergence_duration > 0) {
- duration = pkt->convergence_duration;
- }
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
/* All subtitle blocks are considered to be keyframes. */
mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 1);
put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration);
/* All subtitle blocks are considered to be keyframes. */
mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 1);
put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration);
keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
// check if we have an audio packet cached
keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
// check if we have an audio packet cached
- if (mkv->cur_audio_pkt.size > 0) {
- ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
- av_packet_unref(&mkv->cur_audio_pkt);
+ if (mkv->cur_audio_pkt->size > 0) {
+ ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
+ av_packet_unref(mkv->cur_audio_pkt);
// keyframe's timecode is contained in the same cluster for WebM
if (codec_type == AVMEDIA_TYPE_AUDIO) {
if (pkt->size > 0)
// keyframe's timecode is contained in the same cluster for WebM
if (codec_type == AVMEDIA_TYPE_AUDIO) {
if (pkt->size > 0)
- if (mkv->cur_audio_pkt.size > 0) {
- ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
+ if (mkv->cur_audio_pkt->size > 0) {
+ ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
.name = "matroska",
.long_name = NULL_IF_CONFIG_SMALL("Matroska"),
.mime_type = "video/x-matroska",
.name = "matroska",
.long_name = NULL_IF_CONFIG_SMALL("Matroska"),
.mime_type = "video/x-matroska",
.name = "webm",
.long_name = NULL_IF_CONFIG_SMALL("WebM"),
.mime_type = "video/webm",
.name = "webm",
.long_name = NULL_IF_CONFIG_SMALL("WebM"),
.mime_type = "video/webm",
.name = "matroska",
.long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"),
.mime_type = "audio/x-matroska",
.name = "matroska",
.long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"),
.mime_type = "audio/x-matroska",