]> git.sesse.net Git - x264/blob - output/matroska_ebml.c
dc0d44d0a041ca817fca950f91d7921289d00ffb
[x264] / output / matroska_ebml.c
1 /*****************************************************************************
2  * matroska_ebml.c: matroska muxer utilities
3  *****************************************************************************
4  * Copyright (C) 2005-2015 x264 project
5  *
6  * Authors: Mike Matsnev <mike@haali.su>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
21  *
22  * This program is also available under a commercial proprietary license.
23  * For more information, contact us at licensing@x264.com.
24  *****************************************************************************/
25
26 #include "output.h"
27 #include "matroska_ebml.h"
28
29 #define CLSIZE 1048576
30 #define CHECK(x)\
31 do {\
32     if( (x) < 0 )\
33         return -1;\
34 } while( 0 )
35
36 struct mk_context
37 {
38     struct mk_context *next, **prev, *parent;
39     mk_writer *owner;
40     unsigned id;
41
42     void *data;
43     unsigned d_cur, d_max;
44 };
45
46 typedef struct mk_context mk_context;
47
48 struct mk_writer
49 {
50     FILE *fp;
51
52     unsigned duration_ptr;
53
54     mk_context *root, *cluster, *frame;
55     mk_context *freelist;
56     mk_context *actlist;
57
58     int64_t def_duration;
59     int64_t timescale;
60     int64_t cluster_tc_scaled;
61     int64_t frame_tc, max_frame_tc;
62
63     char wrote_header, in_frame, keyframe, skippable;
64 };
65
66 static mk_context *mk_create_context( mk_writer *w, mk_context *parent, unsigned id )
67 {
68     mk_context *c;
69
70     if( w->freelist )
71     {
72         c = w->freelist;
73         w->freelist = w->freelist->next;
74     }
75     else
76     {
77         c = calloc( 1, sizeof(mk_context) );
78         if( !c )
79             return NULL;
80     }
81
82     c->parent = parent;
83     c->owner = w;
84     c->id = id;
85
86     if( c->owner->actlist )
87         c->owner->actlist->prev = &c->next;
88     c->next = c->owner->actlist;
89     c->prev = &c->owner->actlist;
90     c->owner->actlist = c;
91
92     return c;
93 }
94
95 static int mk_append_context_data( mk_context *c, const void *data, unsigned size )
96 {
97     unsigned ns = c->d_cur + size;
98
99     if( ns > c->d_max )
100     {
101         void *dp;
102         unsigned dn = c->d_max ? c->d_max << 1 : 16;
103         while( ns > dn )
104             dn <<= 1;
105
106         dp = realloc( c->data, dn );
107         if( !dp )
108             return -1;
109
110         c->data = dp;
111         c->d_max = dn;
112     }
113
114     memcpy( (char*)c->data + c->d_cur, data, size );
115
116     c->d_cur = ns;
117
118     return 0;
119 }
120
121 static int mk_write_id( mk_context *c, unsigned id )
122 {
123     unsigned char c_id[4] = { id >> 24, id >> 16, id >> 8, id };
124
125     if( c_id[0] )
126         return mk_append_context_data( c, c_id, 4 );
127     if( c_id[1] )
128         return mk_append_context_data( c, c_id+1, 3 );
129     if( c_id[2] )
130         return mk_append_context_data( c, c_id+2, 2 );
131     return mk_append_context_data( c, c_id+3, 1 );
132 }
133
134 static int mk_write_size( mk_context *c, unsigned size )
135 {
136     unsigned char c_size[5] = { 0x08, size >> 24, size >> 16, size >> 8, size };
137
138     if( size < 0x7f )
139     {
140         c_size[4] |= 0x80;
141         return mk_append_context_data( c, c_size+4, 1 );
142     }
143     if( size < 0x3fff )
144     {
145         c_size[3] |= 0x40;
146         return mk_append_context_data( c, c_size+3, 2 );
147     }
148     if( size < 0x1fffff )
149     {
150         c_size[2] |= 0x20;
151         return mk_append_context_data( c, c_size+2, 3 );
152     }
153     if( size < 0x0fffffff )
154     {
155         c_size[1] |= 0x10;
156         return mk_append_context_data( c, c_size+1, 4 );
157     }
158     return mk_append_context_data( c, c_size, 5 );
159 }
160
161 static int mk_flush_context_id( mk_context *c )
162 {
163     unsigned char ff = 0xff;
164
165     if( !c->id )
166         return 0;
167
168     CHECK( mk_write_id( c->parent, c->id ) );
169     CHECK( mk_append_context_data( c->parent, &ff, 1 ) );
170
171     c->id = 0;
172
173     return 0;
174 }
175
176 static int mk_flush_context_data( mk_context *c )
177 {
178     if( !c->d_cur )
179         return 0;
180
181     if( c->parent )
182         CHECK( mk_append_context_data( c->parent, c->data, c->d_cur ) );
183     else if( fwrite( c->data, c->d_cur, 1, c->owner->fp ) != 1 )
184         return -1;
185
186     c->d_cur = 0;
187
188     return 0;
189 }
190
191 static int mk_close_context( mk_context *c, unsigned *off )
192 {
193     if( c->id )
194     {
195         CHECK( mk_write_id( c->parent, c->id ) );
196         CHECK( mk_write_size( c->parent, c->d_cur ) );
197     }
198
199     if( c->parent && off )
200         *off += c->parent->d_cur;
201
202     CHECK( mk_flush_context_data( c ) );
203
204     if( c->next )
205         c->next->prev = c->prev;
206     *(c->prev) = c->next;
207     c->next = c->owner->freelist;
208     c->owner->freelist = c;
209
210     return 0;
211 }
212
213 static void mk_destroy_contexts( mk_writer *w )
214 {
215     mk_context *next;
216
217     for( mk_context *cur = w->freelist; cur; cur = next )
218     {
219         next = cur->next;
220         free( cur->data );
221         free( cur );
222     }
223
224     for( mk_context *cur = w->actlist; cur; cur = next )
225     {
226         next = cur->next;
227         free( cur->data );
228         free( cur );
229     }
230
231     w->freelist = w->actlist = w->root = NULL;
232 }
233
234 static int mk_write_string( mk_context *c, unsigned id, const char *str )
235 {
236     size_t len = strlen( str );
237
238     CHECK( mk_write_id( c, id ) );
239     CHECK( mk_write_size( c, len ) );
240     CHECK( mk_append_context_data( c, str, len ) );
241     return 0;
242 }
243
244 static int mk_write_bin( mk_context *c, unsigned id, const void *data, unsigned size )
245 {
246     CHECK( mk_write_id( c, id ) );
247     CHECK( mk_write_size( c, size ) );
248     CHECK( mk_append_context_data( c, data, size ) ) ;
249     return 0;
250 }
251
252 static int mk_write_uint( mk_context *c, unsigned id, int64_t ui )
253 {
254     unsigned char c_ui[8] = { ui >> 56, ui >> 48, ui >> 40, ui >> 32, ui >> 24, ui >> 16, ui >> 8, ui };
255     unsigned i = 0;
256
257     CHECK( mk_write_id( c, id ) );
258     while( i < 7 && !c_ui[i] )
259         ++i;
260     CHECK( mk_write_size( c, 8 - i ) );
261     CHECK( mk_append_context_data( c, c_ui+i, 8 - i ) );
262     return 0;
263 }
264
265 static int mk_write_float_raw( mk_context *c, float f )
266 {
267     union
268     {
269         float f;
270         unsigned u;
271     } u;
272     unsigned char c_f[4];
273
274     u.f = f;
275     c_f[0] = u.u >> 24;
276     c_f[1] = u.u >> 16;
277     c_f[2] = u.u >> 8;
278     c_f[3] = u.u;
279
280     return mk_append_context_data( c, c_f, 4 );
281 }
282
283 static int mk_write_float( mk_context *c, unsigned id, float f )
284 {
285     CHECK( mk_write_id( c, id ) );
286     CHECK( mk_write_size( c, 4 ) );
287     CHECK( mk_write_float_raw( c, f ) );
288     return 0;
289 }
290
291 mk_writer *mk_create_writer( const char *filename )
292 {
293     mk_writer *w = calloc( 1, sizeof(mk_writer) );
294     if( !w )
295         return NULL;
296
297     w->root = mk_create_context( w, NULL, 0 );
298     if( !w->root )
299     {
300         free( w );
301         return NULL;
302     }
303
304     if( !strcmp( filename, "-" ) )
305         w->fp = stdout;
306     else
307         w->fp = x264_fopen( filename, "wb" );
308     if( !w->fp )
309     {
310         mk_destroy_contexts( w );
311         free( w );
312         return NULL;
313     }
314
315     w->timescale = 1000000;
316
317     return w;
318 }
319
320 int mk_write_header( mk_writer *w, const char *writing_app,
321                      const char *codec_id,
322                      const void *codec_private, unsigned codec_private_size,
323                      int64_t default_frame_duration,
324                      int64_t timescale,
325                      unsigned width, unsigned height,
326                      unsigned d_width, unsigned d_height, int display_size_units, int stereo_mode )
327 {
328     mk_context  *c, *ti, *v;
329
330     if( w->wrote_header )
331         return -1;
332
333     w->timescale = timescale;
334     w->def_duration = default_frame_duration;
335
336     if( !(c = mk_create_context( w, w->root, 0x1a45dfa3 )) ) // EBML
337         return -1;
338     CHECK( mk_write_uint( c, 0x4286, 1 ) ); // EBMLVersion
339     CHECK( mk_write_uint( c, 0x42f7, 1 ) ); // EBMLReadVersion
340     CHECK( mk_write_uint( c, 0x42f2, 4 ) ); // EBMLMaxIDLength
341     CHECK( mk_write_uint( c, 0x42f3, 8 ) ); // EBMLMaxSizeLength
342     CHECK( mk_write_string( c, 0x4282, "matroska") ); // DocType
343     CHECK( mk_write_uint( c, 0x4287, stereo_mode >= 0 ? 3 : 2 ) ); // DocTypeVersion
344     CHECK( mk_write_uint( c, 0x4285, 2 ) ); // DocTypeReadVersion
345     CHECK( mk_close_context( c, 0 ) );
346
347     if( !(c = mk_create_context( w, w->root, 0x18538067 )) ) // Segment
348         return -1;
349     CHECK( mk_flush_context_id( c ) );
350     CHECK( mk_close_context( c, 0 ) );
351
352     if( !(c = mk_create_context( w, w->root, 0x1549a966 )) ) // SegmentInfo
353         return -1;
354     CHECK( mk_write_string( c, 0x4d80, "Haali Matroska Writer b0" ) ); // MuxingApp
355     CHECK( mk_write_string( c, 0x5741, writing_app ) ); // WritingApp
356     CHECK( mk_write_uint( c, 0x2ad7b1, w->timescale ) ); // TimecodeScale
357     CHECK( mk_write_float( c, 0x4489, 0) ); // Duration
358     w->duration_ptr = c->d_cur - 4;
359     CHECK( mk_close_context( c, &w->duration_ptr ) );
360
361     if( !(c = mk_create_context( w, w->root, 0x1654ae6b )) ) // Tracks
362         return -1;
363     if( !(ti = mk_create_context( w, c, 0xae )) ) // TrackEntry
364         return -1;
365     CHECK( mk_write_uint( ti, 0xd7, 1 ) ); // TrackNumber
366     CHECK( mk_write_uint( ti, 0x73c5, 1 ) ); // TrackUID
367     CHECK( mk_write_uint( ti, 0x83, 1 ) ); // TrackType
368     CHECK( mk_write_uint( ti, 0x9c, 0 ) ); // FlagLacing
369     CHECK( mk_write_string( ti, 0x86, codec_id ) ); // CodecID
370     if( codec_private_size )
371         CHECK( mk_write_bin( ti, 0x63a2, codec_private, codec_private_size ) ); // CodecPrivate
372     if( default_frame_duration )
373         CHECK( mk_write_uint( ti, 0x23e383, default_frame_duration ) ); // DefaultDuration
374
375     if( !(v = mk_create_context( w, ti, 0xe0 ) ) ) // Video
376         return -1;
377     CHECK( mk_write_uint( v, 0xb0, width ) ); // PixelWidth
378     CHECK( mk_write_uint( v, 0xba, height ) ); // PixelHeight
379     CHECK( mk_write_uint( v, 0x54b2, display_size_units ) ); // DisplayUnit
380     CHECK( mk_write_uint( v, 0x54b0, d_width ) ); // DisplayWidth
381     CHECK( mk_write_uint( v, 0x54ba, d_height ) ); // DisplayHeight
382     if( stereo_mode >= 0 )
383         CHECK( mk_write_uint( v, 0x53b8, stereo_mode ) ); // StereoMode
384     CHECK( mk_close_context( v, 0 ) );
385
386     CHECK( mk_close_context( ti, 0 ) );
387
388     CHECK( mk_close_context( c, 0 ) );
389
390     CHECK( mk_flush_context_data( w->root ) );
391
392     w->wrote_header = 1;
393
394     return 0;
395 }
396
397 static int mk_close_cluster( mk_writer *w )
398 {
399     if( w->cluster == NULL )
400         return 0;
401     CHECK( mk_close_context( w->cluster, 0 ) );
402     w->cluster = NULL;
403     CHECK( mk_flush_context_data( w->root ) );
404     return 0;
405 }
406
407 static int mk_flush_frame( mk_writer *w )
408 {
409     int64_t delta;
410     unsigned fsize;
411     unsigned char c_delta_flags[3];
412
413     if( !w->in_frame )
414         return 0;
415
416     delta = w->frame_tc/w->timescale - w->cluster_tc_scaled;
417     if( delta > 32767ll || delta < -32768ll )
418         CHECK( mk_close_cluster( w ) );
419
420     if( !w->cluster )
421     {
422         w->cluster_tc_scaled = w->frame_tc / w->timescale;
423         w->cluster = mk_create_context( w, w->root, 0x1f43b675 ); // Cluster
424         if( !w->cluster )
425             return -1;
426
427         CHECK( mk_write_uint( w->cluster, 0xe7, w->cluster_tc_scaled ) ); // Timecode
428
429         delta = 0;
430     }
431
432     fsize = w->frame ? w->frame->d_cur : 0;
433
434     CHECK( mk_write_id( w->cluster, 0xa3 ) ); // SimpleBlock
435     CHECK( mk_write_size( w->cluster, fsize + 4 ) ); // Size
436     CHECK( mk_write_size( w->cluster, 1 ) ); // TrackNumber
437
438     c_delta_flags[0] = delta >> 8;
439     c_delta_flags[1] = delta;
440     c_delta_flags[2] = (w->keyframe << 7) | w->skippable;
441     CHECK( mk_append_context_data( w->cluster, c_delta_flags, 3 ) ); // Timecode, Flags
442     if( w->frame )
443     {
444         CHECK( mk_append_context_data( w->cluster, w->frame->data, w->frame->d_cur ) ); // Data
445         w->frame->d_cur = 0;
446     }
447
448     w->in_frame = 0;
449
450     if( w->cluster->d_cur > CLSIZE )
451         CHECK( mk_close_cluster( w ) );
452
453     return 0;
454 }
455
456 int mk_start_frame( mk_writer *w )
457 {
458     if( mk_flush_frame( w ) < 0 )
459         return -1;
460
461     w->in_frame  = 1;
462     w->keyframe  = 0;
463     w->skippable = 0;
464
465     return 0;
466 }
467
468 int mk_set_frame_flags( mk_writer *w, int64_t timestamp, int keyframe, int skippable )
469 {
470     if( !w->in_frame )
471         return -1;
472
473     w->frame_tc  = timestamp;
474     w->keyframe  = keyframe  != 0;
475     w->skippable = skippable != 0;
476
477     if( w->max_frame_tc < timestamp )
478         w->max_frame_tc = timestamp;
479
480     return 0;
481 }
482
483 int mk_add_frame_data( mk_writer *w, const void *data, unsigned size )
484 {
485     if( !w->in_frame )
486         return -1;
487
488     if( !w->frame )
489         if( !(w->frame = mk_create_context( w, NULL, 0 )) )
490         return -1;
491
492     return mk_append_context_data( w->frame, data, size );
493 }
494
495 int mk_close( mk_writer *w, int64_t last_delta )
496 {
497     int ret = 0;
498     if( mk_flush_frame( w ) < 0 || mk_close_cluster( w ) < 0 )
499         ret = -1;
500     if( w->wrote_header && x264_is_regular_file( w->fp ) )
501     {
502         fseek( w->fp, w->duration_ptr, SEEK_SET );
503         int64_t last_frametime = w->def_duration ? w->def_duration : last_delta;
504         int64_t total_duration = w->max_frame_tc+last_frametime;
505         if( mk_write_float_raw( w->root, (float)((double)total_duration / w->timescale) ) < 0 ||
506             mk_flush_context_data( w->root ) < 0 )
507             ret = -1;
508     }
509     mk_destroy_contexts( w );
510     fclose( w->fp );
511     free( w );
512     return ret;
513 }