annotate matroskaenc.c @ 2433:0c047310f205 libavformat

Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
author conrad
date Wed, 05 Sep 2007 00:22:52 +0000
parents 68743e7fa627
children 273c76713989
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
1 /*
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
2 * Matroska file muxer
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
3 * Copyright (c) 2007 David Conrad
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
4 *
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
5 * This file is part of FFmpeg.
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
6 *
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
11 *
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
15 * Lesser General Public License for more details.
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
16 *
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
20 */
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
21
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
22 #include "avformat.h"
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
23 #include "riff.h"
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
24 #include "matroska.h"
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
25
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
26 typedef struct MatroskaMuxContext {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
27 offset_t segment;
2433
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
28 offset_t cluster;
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
29 } MatroskaMuxContext;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
30
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
31 static void put_ebml_id(ByteIOContext *pb, unsigned int id)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
32 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
33 if (id >= 0x3fffff)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
34 put_byte(pb, id >> 24);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
35 if (id >= 0x7fff)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
36 put_byte(pb, id >> 16);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
37 if (id >= 0xff)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
38 put_byte(pb, id >> 8);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
39 put_byte(pb, id);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
40 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
41
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
42 // XXX: test this thoroughly and get rid of minbytes hack (currently needed to
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
43 // use up all of the space reserved in start_ebml_master)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
44 static void put_ebml_size(ByteIOContext *pb, uint64_t size, int minbytes)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
45 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
46 int bytes = minbytes;
2426
3d50766df97d Simplify
conrad
parents: 2425
diff changeset
47 while (size >> (bytes*7 + 7)) bytes++;
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
48
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
49 // sizes larger than this are currently undefined in EBML
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
50 // XXX: error condition?
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
51 if (size > (1ULL<<56)-1) return;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
52
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
53 put_byte(pb, (0x80 >> bytes) | (size >> bytes*8));
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
54 for (bytes -= 1; bytes >= 0; bytes--)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
55 put_byte(pb, size >> bytes*8);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
56 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
57
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
58 static void put_ebml_uint(ByteIOContext *pb, unsigned int elementid, uint64_t val)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
59 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
60 int bytes = 1;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
61 while (val >> bytes*8) bytes++;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
62
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
63 put_ebml_id(pb, elementid);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
64 put_ebml_size(pb, bytes, 0);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
65 for (bytes -= 1; bytes >= 0; bytes--)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
66 put_byte(pb, val >> bytes*8);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
67 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
68
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
69 //static void put_ebml_sint(ByteIOContext *pb, unsigned int elementid, int64_t val)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
70
2430
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
71 static void put_ebml_float(ByteIOContext *pb, unsigned int elementid, double val)
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
72 {
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
73 // XXX: single-precision floats?
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
74 put_ebml_id(pb, elementid);
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
75 put_ebml_size(pb, 8, 0);
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
76 put_be64(pb, av_dbl2int(val));
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
77 }
da0227bd105a put_ebml_float()
conrad
parents: 2429
diff changeset
78
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
79 static void put_ebml_binary(ByteIOContext *pb, unsigned int elementid,
2429
326e6fcf9f85 Const correctness
conrad
parents: 2428
diff changeset
80 const uint8_t *buf, int size)
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
81 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
82 put_ebml_id(pb, elementid);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
83 put_ebml_size(pb, size, 0);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
84 put_buffer(pb, buf, size);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
85 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
86
2429
326e6fcf9f85 Const correctness
conrad
parents: 2428
diff changeset
87 static void put_ebml_string(ByteIOContext *pb, unsigned int elementid, const char *str)
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
88 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
89 put_ebml_binary(pb, elementid, str, strlen(str));
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
90 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
91
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
92 static offset_t start_ebml_master(ByteIOContext *pb, unsigned int elementid)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
93 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
94 put_ebml_id(pb, elementid);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
95 // XXX: this always reserves the maximum needed space to store any size value
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
96 // we should be smarter (additional parameter for expected size?)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
97 put_ebml_size(pb, (1ULL<<56)-1, 0); // largest unknown size
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
98 return url_ftell(pb);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
99 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
100
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
101 static void end_ebml_master(ByteIOContext *pb, offset_t start)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
102 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
103 offset_t pos = url_ftell(pb);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
104
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
105 url_fseek(pb, start - 8, SEEK_SET);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
106 put_ebml_size(pb, pos - start, 7);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
107 url_fseek(pb, pos, SEEK_SET);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
108 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
109
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
110
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
111 static int mkv_write_header(AVFormatContext *s)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
112 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
113 MatroskaMuxContext *mkv = s->priv_data;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
114 ByteIOContext *pb = &s->pb;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
115 offset_t ebml_header, segment_info, tracks;
2432
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
116 int i, j;
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
117
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
118 ebml_header = start_ebml_master(pb, EBML_ID_HEADER);
2427
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
119 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
120 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
121 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4);
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
122 put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8);
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
123 put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska");
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
124 put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 1);
407d3205f02d Cosmetics: align nicely for better readibility
conrad
parents: 2426
diff changeset
125 put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 1);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
126 end_ebml_master(pb, ebml_header);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
127
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
128 mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
129
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
130 segment_info = start_ebml_master(pb, MATROSKA_ID_INFO);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
131 put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
132 if (strlen(s->title))
2428
54f89ce33554 Get rid of put_ebml_utf8(); the error checking that would have distinguished it from put_ebml_string() belongs elsewhere in lavf.
conrad
parents: 2427
diff changeset
133 put_ebml_string(pb, MATROSKA_ID_TITLE, s->title);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
134 if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
2428
54f89ce33554 Get rid of put_ebml_utf8(); the error checking that would have distinguished it from put_ebml_string() belongs elsewhere in lavf.
conrad
parents: 2427
diff changeset
135 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
136 // XXX: both are required; something better for writing app?
2428
54f89ce33554 Get rid of put_ebml_utf8(); the error checking that would have distinguished it from put_ebml_string() belongs elsewhere in lavf.
conrad
parents: 2427
diff changeset
137 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
138 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
139 // XXX: segment UID and duration
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
140 end_ebml_master(pb, segment_info);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
141
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
142 tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
143 for (i = 0; i < s->nb_streams; i++) {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
144 AVStream *st = s->streams[i];
2432
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
145 AVCodecContext *codec = st->codec;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
146 offset_t subinfo, track;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
147 int native_id = 0;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
148
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
149 track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
150 put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
151 // XXX: random number for UID? and can we use the same UID when copying
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
152 // from another MKV as the specs recommend?
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
153 put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
154 put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet)
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
155
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
156 if (st->language[0])
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
157 put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, st->language);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
158
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
159 // look for a codec id string specific to mkv to use, if none are found, use AVI codes
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
160 for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) {
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
161 if (ff_mkv_codec_tags[j].id == codec->codec_id) {
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
162 put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
163 native_id = 1;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
164 break;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
165 }
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
166 }
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
167
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
168 // XXX: CodecPrivate for vorbis, theora, aac, native mpeg4, ...
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
169 if (native_id) {
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
170 put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codec->extradata, codec->extradata_size);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
171 }
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
172
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
173 switch (codec->codec_type) {
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
174 case CODEC_TYPE_VIDEO:
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
175 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
176
2432
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
177 if (!native_id) {
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
178 offset_t bmp_header;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
179 // if there is no mkv-specific codec id, use VFW mode
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
180 if (!codec->codec_tag)
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
181 codec->codec_tag = codec_get_tag(codec_bmp_tags, codec->codec_id);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
182
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
183 put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
184 // XXX: codec private isn't a master; is there a better way to re-use put_bmp_header?
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
185 bmp_header = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
186 put_bmp_header(pb, codec, codec_bmp_tags, 0);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
187 end_ebml_master(pb, bmp_header);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
188 }
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
189 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
190 // XXX: interlace flag?
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
191 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
192 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
193 // XXX: display width/height
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
194 end_ebml_master(pb, subinfo);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
195 break;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
196
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
197 case CODEC_TYPE_AUDIO:
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
198 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
199
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
200 // XXX: A_MS/ACM
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
201 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
202 put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
203 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, codec->sample_rate);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
204 // XXX: output sample freq (for sbr) and bitdepth (for pcm)
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
205 end_ebml_master(pb, subinfo);
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
206 break;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
207
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
208 default:
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
209 av_log(s, AV_LOG_ERROR, "Only audio and video are supported for Matroska.");
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
210 break;
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
211 }
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
212 end_ebml_master(pb, track);
2432
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
213
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
214 // ms precision is the de-facto standard timescale for mkv files
68743e7fa627 First stab at writing the tracks element, still needs some additional cases for certain codecs
conrad
parents: 2431
diff changeset
215 av_set_pts_info(st, 64, 1, 1000);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
216 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
217 end_ebml_master(pb, tracks);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
218
2433
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
219 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER);
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
220 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, 0);
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
221
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
222 return 0;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
223 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
224
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
225 static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
226 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
227 ByteIOContext *pb = &s->pb;
2433
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
228
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
229 block = start_ebml_master(pb, MATROSKA_ID_SIMPLEBLOCK);
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
230 put_byte(pb, 0x80 | pkt->stream_index); // this assumes stream_index is less than 127
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
231 put_be16(pb, pkt->pts);
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
232 put_byte(pb, !!(pkt->flags & PKT_FLAG_KEY));
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
233 put_buffer(pb, pkt->data, pkt->size);
2433
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
234 end_ebml_master(pb, block);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
235 return 0;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
236 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
237
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
238 static int mkv_write_trailer(AVFormatContext *s)
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
239 {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
240 MatroskaMuxContext *mkv = s->priv_data;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
241 ByteIOContext *pb = &s->pb;
2433
0c047310f205 Write one cluster and SimpleBlocks for the frames. Should now create playable mkv files for some video codecs (H.264 and VP3 checked)
conrad
parents: 2432
diff changeset
242 end_ebml_master(pb, mkv->cluster);
2425
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
243 end_ebml_master(pb, mkv->segment);
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
244 return 0;
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
245 }
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
246
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
247 AVOutputFormat matroska_muxer = {
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
248 "matroska",
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
249 "Matroska File Format",
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
250 "video/x-matroska",
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
251 "mkv",
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
252 sizeof(MatroskaMuxContext),
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
253 CODEC_ID_MP2,
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
254 CODEC_ID_MPEG4,
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
255 mkv_write_header,
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
256 mkv_write_packet,
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
257 mkv_write_trailer,
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
258 .codec_tag = (const AVCodecTag*[]){codec_bmp_tags, codec_wav_tags, 0},
8c51e92edd7d Beginning of mkv muxer, only EBML head is written correctly
conrad
parents:
diff changeset
259 };