comparison matroskaenc.c @ 2432:68743e7fa627 libavformat

First stab at writing the tracks element, still needs some additional cases for certain codecs
author conrad
date Wed, 05 Sep 2007 00:22:50 +0000
parents 435ebfec86cf
children 0c047310f205
comparison
equal deleted inserted replaced
2431:435ebfec86cf 2432:68743e7fa627
110 static int mkv_write_header(AVFormatContext *s) 110 static int mkv_write_header(AVFormatContext *s)
111 { 111 {
112 MatroskaMuxContext *mkv = s->priv_data; 112 MatroskaMuxContext *mkv = s->priv_data;
113 ByteIOContext *pb = &s->pb; 113 ByteIOContext *pb = &s->pb;
114 offset_t ebml_header, segment_info, tracks; 114 offset_t ebml_header, segment_info, tracks;
115 int i; 115 int i, j;
116 116
117 ebml_header = start_ebml_master(pb, EBML_ID_HEADER); 117 ebml_header = start_ebml_master(pb, EBML_ID_HEADER);
118 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); 118 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
119 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); 119 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
120 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); 120 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4);
139 end_ebml_master(pb, segment_info); 139 end_ebml_master(pb, segment_info);
140 140
141 tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS); 141 tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS);
142 for (i = 0; i < s->nb_streams; i++) { 142 for (i = 0; i < s->nb_streams; i++) {
143 AVStream *st = s->streams[i]; 143 AVStream *st = s->streams[i];
144 offset_t track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY); 144 AVCodecContext *codec = st->codec;
145 145 offset_t subinfo, track;
146 int native_id = 0;
147
148 track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY);
149 put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i);
150 // XXX: random number for UID? and can we use the same UID when copying
151 // from another MKV as the specs recommend?
152 put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i);
153 put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet)
154
155 if (st->language[0])
156 put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, st->language);
157
158 // look for a codec id string specific to mkv to use, if none are found, use AVI codes
159 for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) {
160 if (ff_mkv_codec_tags[j].id == codec->codec_id) {
161 put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
162 native_id = 1;
163 break;
164 }
165 }
166
167 // XXX: CodecPrivate for vorbis, theora, aac, native mpeg4, ...
168 if (native_id) {
169 put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codec->extradata, codec->extradata_size);
170 }
171
172 switch (codec->codec_type) {
173 case CODEC_TYPE_VIDEO:
174 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
175
176 if (!native_id) {
177 offset_t bmp_header;
178 // if there is no mkv-specific codec id, use VFW mode
179 if (!codec->codec_tag)
180 codec->codec_tag = codec_get_tag(codec_bmp_tags, codec->codec_id);
181
182 put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
183 // XXX: codec private isn't a master; is there a better way to re-use put_bmp_header?
184 bmp_header = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE);
185 put_bmp_header(pb, codec, codec_bmp_tags, 0);
186 end_ebml_master(pb, bmp_header);
187 }
188 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO);
189 // XXX: interlace flag?
190 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
191 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
192 // XXX: display width/height
193 end_ebml_master(pb, subinfo);
194 break;
195
196 case CODEC_TYPE_AUDIO:
197 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
198
199 // XXX: A_MS/ACM
200 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO);
201 put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels);
202 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, codec->sample_rate);
203 // XXX: output sample freq (for sbr) and bitdepth (for pcm)
204 end_ebml_master(pb, subinfo);
205 break;
206
207 default:
208 av_log(s, AV_LOG_ERROR, "Only audio and video are supported for Matroska.");
209 break;
210 }
146 end_ebml_master(pb, track); 211 end_ebml_master(pb, track);
212
213 // ms precision is the de-facto standard timescale for mkv files
214 av_set_pts_info(st, 64, 1, 1000);
147 } 215 }
148 end_ebml_master(pb, tracks); 216 end_ebml_master(pb, tracks);
149 217
150 return 0; 218 return 0;
151 } 219 }