Mercurial > libavformat.hg
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 } |