X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmatroskaenc.c;h=e9c977a59fbba86809d1e6fd2253842896b62df9;hb=4ccb7911baa761d373e28068b93db13a76a780b8;hp=5ce2a541da12b6b3aff2c3b8d0492555962f76db;hpb=f6302ad6ee12bd1eeee9fb2d5642290c0ec5bb1b;p=ffmpeg diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 5ce2a541da1..e9c977a59fb 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -30,6 +30,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/random_seed.h" #include "libavutil/lfg.h" +#include "libavutil/dict.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" #include @@ -403,8 +404,6 @@ static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, int num_tracks) } end_ebml_master(pb, cues_element); - av_free(cues->entries); - av_free(cues); return currentpos; } @@ -525,10 +524,10 @@ static int mkv_write_tracks(AVFormatContext *s) int bit_depth = av_get_bits_per_sample(codec->codec_id); int sample_rate = codec->sample_rate; int output_sample_rate = 0; - AVMetadataTag *tag; + AVDictionaryEntry *tag; if (!bit_depth) - bit_depth = av_get_bits_per_sample_fmt(codec->sample_fmt); + bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; if (codec->codec_id == CODEC_ID_AAC) get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); @@ -538,9 +537,9 @@ static int mkv_write_tracks(AVFormatContext *s) put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) - if ((tag = av_metadata_get(st->metadata, "title", NULL, 0))) + if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); - tag = av_metadata_get(st->metadata, "language", NULL, 0); + tag = av_dict_get(st->metadata, "language", NULL, 0); put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); if (st->disposition) @@ -588,12 +587,38 @@ static int mkv_write_tracks(AVFormatContext *s) // XXX: interlace flag? put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); + + if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) || + (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) { + // save stereo mode flag + uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT; + + for (j=0; jvalue, matroska_video_stereo_mode[j])){ + st_mode = j; + break; + } + + if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11) + || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) { + av_log(s, AV_LOG_ERROR, + "The specified stereo mode is not valid.\n"); + return AVERROR(EINVAL); + } else + put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode); + } + if (st->sample_aspect_ratio.num) { int d_width = codec->width*av_q2d(st->sample_aspect_ratio); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, 3); } + + if (codec->codec_id == CODEC_ID_RAWVIDEO) { + uint32_t color_space = av_le2ne32(codec->codec_tag); + put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); + } end_ebml_master(pb, subinfo); break; @@ -618,7 +643,7 @@ static int mkv_write_tracks(AVFormatContext *s) put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE); if (!native_id) { av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id); - return AVERROR_NOTSUPP; + return AVERROR(ENOSYS); } break; default: @@ -658,7 +683,7 @@ static int mkv_write_chapters(AVFormatContext *s) for (i = 0; i < s->nb_chapters; i++) { ebml_master chapteratom, chapterdisplay; AVChapter *c = s->chapters[i]; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; chapteratom = start_ebml_master(pb, MATROSKA_ID_CHAPTERATOM, 0); put_ebml_uint(pb, MATROSKA_ID_CHAPTERUID, c->id); @@ -668,7 +693,7 @@ static int mkv_write_chapters(AVFormatContext *s) av_rescale_q(c->end, c->time_base, scale)); put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGHIDDEN , 0); put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGENABLED, 1); - if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) { + if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { chapterdisplay = start_ebml_master(pb, MATROSKA_ID_CHAPTERDISPLAY, 0); put_ebml_string(pb, MATROSKA_ID_CHAPSTRING, t->value); put_ebml_string(pb, MATROSKA_ID_CHAPLANG , "und"); @@ -681,7 +706,7 @@ static int mkv_write_chapters(AVFormatContext *s) return 0; } -static void mkv_write_simpletag(AVIOContext *pb, AVMetadataTag *t) +static void mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t) { uint8_t *key = av_strdup(t->key); uint8_t *p = key; @@ -711,12 +736,12 @@ static void mkv_write_simpletag(AVIOContext *pb, AVMetadataTag *t) av_freep(&key); } -static int mkv_write_tag(AVFormatContext *s, AVMetadata *m, unsigned int elementid, +static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int elementid, unsigned int uid, ebml_master *tags) { MatroskaMuxContext *mkv = s->priv_data; ebml_master tag, targets; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; int ret; if (!tags->pos) { @@ -732,8 +757,8 @@ static int mkv_write_tag(AVFormatContext *s, AVMetadata *m, unsigned int element put_ebml_uint(s->pb, elementid, uid); end_ebml_master(s->pb, targets); - while ((t = av_metadata_get(m, "", t, AV_METADATA_IGNORE_SUFFIX))) - if (strcasecmp(t->key, "title")) + while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) + if (strcasecmp(t->key, "title") && strcasecmp(t->key, "stereo_mode")) mkv_write_simpletag(s->pb, t); end_ebml_master(s->pb, tag); @@ -747,7 +772,7 @@ static int mkv_write_tags(AVFormatContext *s) ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL); - if (av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) { + if (av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) { ret = mkv_write_tag(s, s->metadata, 0, 0, &tags); if (ret < 0) return ret; } @@ -755,7 +780,7 @@ static int mkv_write_tags(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (!av_metadata_get(st->metadata, "", 0, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(st->metadata, "", 0, AV_DICT_IGNORE_SUFFIX)) continue; ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tags); @@ -765,7 +790,7 @@ static int mkv_write_tags(AVFormatContext *s) for (i = 0; i < s->nb_chapters; i++) { AVChapter *ch = s->chapters[i]; - if (!av_metadata_get(ch->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(ch->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) continue; ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id, &tags); @@ -782,7 +807,7 @@ static int mkv_write_header(AVFormatContext *s) MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; ebml_master ebml_header, segment_info; - AVMetadataTag *tag; + AVDictionaryEntry *tag; int ret, i; if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM; @@ -819,7 +844,7 @@ static int mkv_write_header(AVFormatContext *s) segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0); put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); - if ((tag = av_metadata_get(s->metadata, "title", NULL, 0))) + if ((tag = av_dict_get(s->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value); if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { uint32_t segment_uid[4]; @@ -1164,6 +1189,8 @@ static int mkv_write_trailer(AVFormatContext *s) end_ebml_master(pb, mkv->segment); av_free(mkv->tracks); + av_freep(&mkv->cues->entries); + av_freep(&mkv->cues); av_destruct_packet(&mkv->cur_audio_pkt); avio_flush(pb); return 0; @@ -1199,7 +1226,7 @@ AVOutputFormat ff_webm_muxer = { mkv_write_header, mkv_write_packet, mkv_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, + .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, }; #endif