mkv_cues cues;
int64_t cues_pos;
- AVPacket cur_audio_pkt;
+ AVPacket *cur_audio_pkt;
unsigned nb_attachments;
int have_video;
{
MatroskaMuxContext *mkv = s->priv_data;
- av_packet_unref(&mkv->cur_audio_pkt);
+ av_packet_free(&mkv->cur_audio_pkt);
ffio_free_dyn_buf(&mkv->cluster_bc);
ffio_free_dyn_buf(&mkv->info.bc);
put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value);
tag = av_dict_get(st->metadata, "language", NULL, 0);
put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE,
- tag && tag->value ? tag->value : "und");
+ tag && tag->value[0] ? tag->value : "und");
// The default value for TRACKFLAGDEFAULT is 1, so add element
// if we need to clear it.
put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id);
} else {
+ if (st->disposition & AV_DISPOSITION_COMMENT)
+ put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGCOMMENTARY, 1);
+ if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
+ put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, 1);
+ if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
+ put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, 1);
+ if (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB) &&
+ (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
+ != (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
+ put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGORIGINAL,
+ !!(st->disposition & AV_DISPOSITION_ORIGINAL));
+
// look for a codec ID string specific to mkv to use,
// if none are found, use AVI codes
if (par->codec_id != AV_CODEC_ID_RAWVIDEO || par->codec_tag) {
av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id);
return AVERROR(ENOSYS);
}
+ if (mkv->mode != MODE_WEBM && st->disposition & AV_DISPOSITION_DESCRIPTIONS)
+ put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1);
if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT)
native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
return 0;
}
+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;
- uint64_t chapter_id_offset = 0;
AVRational scale = {1, 1E9};
- int i, ret;
+ int ret, create_new_ids;
if (!s->nb_chapters || mkv->wrote_chapters)
return 0;
- for (i = 0; i < s->nb_chapters; i++)
- if (!s->chapters[i]->id) {
- chapter_id_offset = 1;
- break;
- }
-
ret = start_ebml_master_crc32(&dyn_cp, mkv);
if (ret < 0)
return ret;
} else
tags = NULL;
- for (i = 0; i < s->nb_chapters; i++) {
+ create_new_ids = mkv_new_chapter_ids_needed(s);
+
+ for (unsigned i = 0; i < s->nb_chapters; i++) {
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 FF_API_CHAPTER_ID_INT
+ uint64_t uid = create_new_ids ? i + 1ULL : (uint32_t)c->id;
+#else
+ uint64_t uid = create_new_ids ? i + 1ULL : c->id;
+#endif
if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) {
av_log(s, AV_LOG_ERROR,
"Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
}
chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0);
- 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))) {
if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) {
ret = mkv_write_tag(mkv, c->metadata, tags, NULL,
- MATROSKA_ID_TAGTARGETS_CHAPTERUID,
- (uint32_t)c->id + chapter_id_offset);
+ MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid);
if (ret < 0)
goto fail;
}
mkv->reserve_cues_space = -1;
}
- av_init_packet(&mkv->cur_audio_pkt);
- mkv->cur_audio_pkt.size = 0;
mkv->cluster_pos = -1;
// start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
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, side_data_size;
+ buffer_size_t side_data_size;
+ int err = 0, offset = 0, size = pkt->size;
int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
uint64_t additional_id;
int64_t discard_padding = 0;
MatroskaMuxContext *mkv = s->priv_data;
mkv_track *track = &mkv->tracks[pkt->stream_index];
ebml_master blockgroup;
- int id_size, settings_size, size;
+ buffer_size_t id_size, settings_size;
+ int size;
const char *id, *settings;
int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
const int flags = 0;
mkv_track *track = &mkv->tracks[pkt->stream_index];
AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
uint8_t *side_data;
- int side_data_size, ret;
+ buffer_size_t side_data_size;
+ int ret;
side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
&side_data_size);
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);
if (ret < 0) {
av_log(s, AV_LOG_ERROR,
"Could not write cached audio packet ret:%d\n", ret);
// keyframe's timecode is contained in the same cluster for WebM
if (codec_type == AVMEDIA_TYPE_AUDIO) {
if (pkt->size > 0)
- ret = av_packet_ref(&mkv->cur_audio_pkt, pkt);
+ ret = av_packet_ref(mkv->cur_audio_pkt, pkt);
} else
ret = mkv_write_packet_internal(s, pkt);
return ret;
int ret, ret2 = 0;
// 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);
+ if (mkv->cur_audio_pkt->size > 0) {
+ ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
if (ret < 0) {
av_log(s, AV_LOG_ERROR,
"Could not write cached audio packet ret:%d\n", ret);
} else
mkv->mode = MODE_MATROSKAv2;
+ mkv->cur_audio_pkt = av_packet_alloc();
+ if (!mkv->cur_audio_pkt)
+ return AVERROR(ENOMEM);
mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
if (!mkv->tracks)
return AVERROR(ENOMEM);