static int mkv_write_tracks(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; ebml_master tracks; int i, j, ret; ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, avio_tell(pb)); if (ret < 0) return ret; tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; AVCodecContext *codec = st->codec; ebml_master subinfo, track; int native_id = 0; int qt_id = 0; int bit_depth = av_get_bits_per_sample(codec->codec_id); int sample_rate = codec->sample_rate; int output_sample_rate = 0; AVDictionaryEntry *tag; if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { mkv->have_attachments = 1; continue; } if (!bit_depth) bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; if (codec->codec_id == AV_CODEC_ID_AAC) get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) 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:"und"); if (st->disposition) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT)); // look for a codec ID string specific to mkv to use, // if none are found, use AVI codes for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { if (ff_mkv_codec_tags[j].id == codec->codec_id) { put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); native_id = 1; break; } } if (mkv->mode == MODE_WEBM && !(codec->codec_id == AV_CODEC_ID_VP8 || codec->codec_id == AV_CODEC_ID_VORBIS)) { av_log(s, AV_LOG_ERROR, "Only VP8 video and Vorbis audio are supported for WebM.\n"); return AVERROR(EINVAL); } switch (codec->codec_type) { case AVMEDIA_TYPE_VIDEO: put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); if(st->avg_frame_rate.num && st->avg_frame_rate.den && 1.0/av_q2d(st->avg_frame_rate) > av_q2d(codec->time_base)) put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9/av_q2d(st->avg_frame_rate)); else put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9); if (!native_id && ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id) && (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id) || codec->codec_id == AV_CODEC_ID_SVQ1 || codec->codec_id == AV_CODEC_ID_SVQ3 || codec->codec_id == AV_CODEC_ID_CINEPAK)) qt_id = 1; if (qt_id) put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME"); else if (!native_id) { // if there is no mkv-specific codec ID, use VFW mode put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); mkv->tracks[i].write_dts = 1; } subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); // 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; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++) if (!strcmp(tag->value, ff_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 = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height); } if (codec->codec_id == AV_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; case AVMEDIA_TYPE_AUDIO: put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); if (!native_id) // no mkv-specific ID, use ACM mode put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM"); subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0); put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels); put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); if (output_sample_rate) put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); if (bit_depth) put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth); end_ebml_master(pb, subinfo); break; case AVMEDIA_TYPE_SUBTITLE: 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(ENOSYS); } break; default: av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n"); break; } ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); if (ret < 0) return ret; end_ebml_master(pb, track); // ms precision is the de-facto standard timescale for mkv files avpriv_set_pts_info(st, 64, 1, 1000); } end_ebml_master(pb, tracks); return 0; }
static int mkv_write_tracks(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; ebml_master tracks; int i, j, ret; ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, avio_tell(pb)); if (ret < 0) return ret; tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; AVCodecContext *codec = st->codec; ebml_master subinfo, track; int native_id = 0; int qt_id = 0; int bit_depth = av_get_bits_per_sample(codec->codec_id); int sample_rate = codec->sample_rate; int output_sample_rate = 0; AVDictionaryEntry *tag; if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { mkv->have_attachments = 1; continue; } if (!bit_depth) bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3; if (codec->codec_id == AV_CODEC_ID_AAC) get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0);  