Commit 90f12afa authored by Fiona Glaser's avatar Fiona Glaser

Overhaul syntax in muxers.c/matroska.c

The inconsistent syntax in these files has finally come to an end.
parent 7a0fbed7
......@@ -23,492 +23,539 @@
#include "common/osdep.h"
#include "matroska.h"
#define CLSIZE 1048576
#define CHECK(x) do { if ((x) < 0) return -1; } while (0)
struct mk_Context {
struct mk_Context *next, **prev, *parent;
struct mk_Writer *owner;
unsigned id;
#define CLSIZE 1048576
#define CHECK(x)\
do\
{\
if( (x) < 0 ) return -1;\
}\
while( 0 )
struct mk_context
{
struct mk_context *next, **prev, *parent;
struct mk_writer *owner;
unsigned id;
void *data;
unsigned d_cur, d_max;
void *data;
unsigned d_cur, d_max;
};
typedef struct mk_Context mk_Context;
typedef struct mk_context mk_context;
struct mk_Writer {
FILE *fp;
struct mk_writer
{
FILE *fp;
unsigned duration_ptr;
unsigned duration_ptr;
mk_Context *root, *cluster, *frame;
mk_Context *freelist;
mk_Context *actlist;
mk_context *root, *cluster, *frame;
mk_context *freelist;
mk_context *actlist;
int64_t def_duration;
int64_t timescale;
int64_t cluster_tc_scaled;
int64_t frame_tc, prev_frame_tc_scaled, max_frame_tc;
int64_t def_duration;
int64_t timescale;
int64_t cluster_tc_scaled;
int64_t frame_tc, prev_frame_tc_scaled, max_frame_tc;
char wrote_header, in_frame, keyframe;
char wrote_header, in_frame, keyframe;
};
static mk_Context *mk_createContext(mk_Writer *w, mk_Context *parent, unsigned id) {
mk_Context *c;
if (w->freelist) {
c = w->freelist;
w->freelist = w->freelist->next;
} else {
c = malloc(sizeof(*c));
if (c == NULL)
return NULL;
memset(c, 0, sizeof(*c));
}
c->parent = parent;
c->owner = w;
c->id = id;
if (c->owner->actlist)
c->owner->actlist->prev = &c->next;
c->next = c->owner->actlist;
c->prev = &c->owner->actlist;
c->owner->actlist = c;
return c;
static mk_context *mk_create_context( mk_writer *w, mk_context *parent, unsigned id )
{
mk_context *c;
if( w->freelist )
{
c = w->freelist;
w->freelist = w->freelist->next;
}
else
{
c = malloc( sizeof(*c) );
if( !c )
return NULL;
memset( c, 0, sizeof(*c) );
}
c->parent = parent;
c->owner = w;
c->id = id;
if( c->owner->actlist )
c->owner->actlist->prev = &c->next;
c->next = c->owner->actlist;
c->prev = &c->owner->actlist;
c->owner->actlist = c;
return c;
}
static int mk_appendContextData(mk_Context *c, const void *data, unsigned size) {
unsigned ns = c->d_cur + size;
static int mk_append_context_data( mk_context *c, const void *data, unsigned size )
{
unsigned ns = c->d_cur + size;
if (ns > c->d_max) {
void *dp;
unsigned dn = c->d_max ? c->d_max << 1 : 16;
while (ns > dn)
dn <<= 1;
if( ns > c->d_max )
{
void *dp;
unsigned dn = c->d_max ? c->d_max << 1 : 16;
while( ns > dn )
dn <<= 1;
dp = realloc(c->data, dn);
if (dp == NULL)
return -1;
dp = realloc( c->data, dn );
if( !dp )
return -1;
c->data = dp;
c->d_max = dn;
}
c->data = dp;
c->d_max = dn;
}
memcpy((char*)c->data + c->d_cur, data, size);
memcpy( (char*)c->data + c->d_cur, data, size );
c->d_cur = ns;
c->d_cur = ns;
return 0;
return 0;
}
static int mk_writeID(mk_Context *c, unsigned id) {
unsigned char c_id[4] = { id >> 24, id >> 16, id >> 8, id };
if (c_id[0])
return mk_appendContextData(c, c_id, 4);
if (c_id[1])
return mk_appendContextData(c, c_id+1, 3);
if (c_id[2])
return mk_appendContextData(c, c_id+2, 2);
return mk_appendContextData(c, c_id+3, 1);
static int mk_write_id( mk_context *c, unsigned id )
{
unsigned char c_id[4] = { id >> 24, id >> 16, id >> 8, id };
if( c_id[0] )
return mk_append_context_data( c, c_id, 4 );
if( c_id[1] )
return mk_append_context_data( c, c_id+1, 3 );
if( c_id[2] )
return mk_append_context_data( c, c_id+2, 2 );
return mk_append_context_data( c, c_id+3, 1 );
}
static int mk_writeSize(mk_Context *c, unsigned size) {
unsigned char c_size[5] = { 0x08, size >> 24, size >> 16, size >> 8, size };
if (size < 0x7f) {
c_size[4] |= 0x80;
return mk_appendContextData(c, c_size+4, 1);
}
if (size < 0x3fff) {
c_size[3] |= 0x40;
return mk_appendContextData(c, c_size+3, 2);
}
if (size < 0x1fffff) {
c_size[2] |= 0x20;
return mk_appendContextData(c, c_size+2, 3);
}
if (size < 0x0fffffff) {
c_size[1] |= 0x10;
return mk_appendContextData(c, c_size+1, 4);
}
return mk_appendContextData(c, c_size, 5);
static int mk_write_size( mk_context *c, unsigned size )
{
unsigned char c_size[5] = { 0x08, size >> 24, size >> 16, size >> 8, size };
if( size < 0x7f )
{
c_size[4] |= 0x80;
return mk_append_context_data( c, c_size+4, 1 );
}
if( size < 0x3fff )
{
c_size[3] |= 0x40;
return mk_append_context_data( c, c_size+3, 2 );
}
if( size < 0x1fffff )
{
c_size[2] |= 0x20;
return mk_append_context_data( c, c_size+2, 3 );
}
if( size < 0x0fffffff )
{
c_size[1] |= 0x10;
return mk_append_context_data( c, c_size+1, 4 );
}
return mk_append_context_data( c, c_size, 5 );
}
static int mk_flushContextID(mk_Context *c) {
unsigned char ff = 0xff;
static int mk_flush_context_id( mk_context *c )
{
unsigned char ff = 0xff;
if (c->id == 0)
return 0;
if( !c->id )
return 0;
CHECK(mk_writeID(c->parent, c->id));
CHECK(mk_appendContextData(c->parent, &ff, 1));
CHECK( mk_write_id( c->parent, c->id ) );
CHECK( mk_append_context_data( c->parent, &ff, 1 ) );
c->id = 0;
c->id = 0;
return 0;
return 0;
}
static int mk_flushContextData(mk_Context *c) {
if (c->d_cur == 0)
return 0;
static int mk_flush_context_data(mk_context *c)
{
if( !c->d_cur )
return 0;
if (c->parent)
CHECK(mk_appendContextData(c->parent, c->data, c->d_cur));
else
if (fwrite(c->data, c->d_cur, 1, c->owner->fp) != 1)
return -1;
if( c->parent )
CHECK( mk_append_context_data( c->parent, c->data, c->d_cur ) );
else if( fwrite( c->data, c->d_cur, 1, c->owner->fp ) != 1 )
return -1;
c->d_cur = 0;
c->d_cur = 0;
return 0;
return 0;
}
static int mk_closeContext(mk_Context *c, unsigned *off) {
if (c->id) {
CHECK(mk_writeID(c->parent, c->id));
CHECK(mk_writeSize(c->parent, c->d_cur));
}
static int mk_close_context(mk_context *c, unsigned *off)
{
if( c->id )
{
CHECK( mk_write_id( c->parent, c->id ) );
CHECK( mk_write_size( c->parent, c->d_cur ) );
}
if (c->parent && off != NULL)
*off += c->parent->d_cur;
if( c->parent && off )
*off += c->parent->d_cur;
CHECK(mk_flushContextData(c));
CHECK( mk_flush_context_data( c ) );
if (c->next)
c->next->prev = c->prev;
*(c->prev) = c->next;
c->next = c->owner->freelist;
c->owner->freelist = c;
if( c->next )
c->next->prev = c->prev;
*(c->prev) = c->next;
c->next = c->owner->freelist;
c->owner->freelist = c;
return 0;
return 0;
}
static void mk_destroyContexts(mk_Writer *w) {
mk_Context *cur, *next;
for (cur = w->freelist; cur; cur = next) {
next = cur->next;
free(cur->data);
free(cur);
}
for (cur = w->actlist; cur; cur = next) {
next = cur->next;
free(cur->data);
free(cur);
}
w->freelist = w->actlist = w->root = NULL;
static void mk_destroy_contexts( mk_writer *w )
{
mk_context *cur, *next;
for( cur = w->freelist; cur; cur = next )
{
next = cur->next;
free( cur->data );
free( cur );
}
for( cur = w->actlist; cur; cur = next )
{
next = cur->next;
free( cur->data );
free( cur );
}
w->freelist = w->actlist = w->root = NULL;
}
static int mk_writeStr(mk_Context *c, unsigned id, const char *str) {
size_t len = strlen(str);
static int mk_write_string( mk_context *c, unsigned id, const char *str )
{
size_t len = strlen( str );
CHECK(mk_writeID(c, id));
CHECK(mk_writeSize(c, len));
CHECK(mk_appendContextData(c, str, len));
return 0;
CHECK( mk_write_id( c, id ) );
CHECK( mk_write_size( c, len ) );
CHECK( mk_append_context_data( c, str, len ) );
return 0;
}
static int mk_writeBin(mk_Context *c, unsigned id, const void *data, unsigned size) {
CHECK(mk_writeID(c, id));
CHECK(mk_writeSize(c, size));
CHECK(mk_appendContextData(c, data, size));
return 0;
static int mk_write_bin( mk_context *c, unsigned id, const void *data, unsigned size )
{
CHECK( mk_write_id( c, id ) );
CHECK( mk_write_size( c, size ) );
CHECK( mk_append_context_data( c, data, size ) ) ;
return 0;
}
static int mk_writeUInt(mk_Context *c, unsigned id, int64_t ui) {
unsigned char c_ui[8] = { ui >> 56, ui >> 48, ui >> 40, ui >> 32, ui >> 24, ui >> 16, ui >> 8, ui };
unsigned i = 0;
CHECK(mk_writeID(c, id));
while (i < 7 && c_ui[i] == 0)
++i;
CHECK(mk_writeSize(c, 8 - i));
CHECK(mk_appendContextData(c, c_ui+i, 8 - i));
return 0;
static int mk_write_uint( mk_context *c, unsigned id, int64_t ui )
{
unsigned char c_ui[8] = { ui >> 56, ui >> 48, ui >> 40, ui >> 32, ui >> 24, ui >> 16, ui >> 8, ui };
unsigned i = 0;
CHECK( mk_write_id( c, id ) );
while( i < 7 && !c_ui[i] )
++i;
CHECK( mk_write_size( c, 8 - i ) );
CHECK( mk_append_context_data( c, c_ui+i, 8 - i ) );
return 0;
}
static int mk_writeSInt(mk_Context *c, unsigned id, int64_t si) {
unsigned char c_si[8] = { si >> 56, si >> 48, si >> 40, si >> 32, si >> 24, si >> 16, si >> 8, si };
unsigned i = 0;
CHECK(mk_writeID(c, id));
if (si < 0)
while (i < 7 && c_si[i] == 0xff && c_si[i+1] & 0x80)
++i;
else
while (i < 7 && c_si[i] == 0 && !(c_si[i+1] & 0x80))
++i;
CHECK(mk_writeSize(c, 8 - i));
CHECK(mk_appendContextData(c, c_si+i, 8 - i));
return 0;
static int mk_write_sint( mk_context *c, unsigned id, int64_t si )
{
unsigned char c_si[8] = { si >> 56, si >> 48, si >> 40, si >> 32, si >> 24, si >> 16, si >> 8, si };
unsigned i = 0;
CHECK( mk_write_id( c, id ) );
if( si < 0 )
while( i < 7 && c_si[i] == 0xff && c_si[i+1] & 0x80 )
++i;
else
while( i < 7 && c_si[i] == 0 && !(c_si[i+1] & 0x80 ) )
++i;
CHECK( mk_write_size( c, 8 - i ) );
CHECK( mk_append_context_data( c, c_si+i, 8 - i ) );
return 0;
}
static int mk_writeFloatRaw(mk_Context *c, float f) {
union {
float f;
unsigned u;
} u;
unsigned char c_f[4];
u.f = f;
c_f[0] = u.u >> 24;
c_f[1] = u.u >> 16;
c_f[2] = u.u >> 8;
c_f[3] = u.u;
return mk_appendContextData(c, c_f, 4);
static int mk_write_float_raw( mk_context *c, float f )
{
union
{
float f;
unsigned u;
} u;
unsigned char c_f[4];
u.f = f;
c_f[0] = u.u >> 24;
c_f[1] = u.u >> 16;
c_f[2] = u.u >> 8;
c_f[3] = u.u;
return mk_append_context_data( c, c_f, 4 );
}
static int mk_writeFloat(mk_Context *c, unsigned id, float f) {
CHECK(mk_writeID(c, id));
CHECK(mk_writeSize(c, 4));
CHECK(mk_writeFloatRaw(c, f));
return 0;
static int mk_write_float( mk_context *c, unsigned id, float f )
{
CHECK( mk_write_id( c, id ) );
CHECK( mk_write_size( c, 4 ) );
CHECK( mk_write_float_raw( c, f ) );
return 0;
}
static unsigned mk_ebmlSizeSize(unsigned s) {
if (s < 0x7f)
return 1;
if (s < 0x3fff)
return 2;
if (s < 0x1fffff)
return 3;
if (s < 0x0fffffff)
return 4;
return 5;
static unsigned mk_ebml_size_size( unsigned s )
{
if( s < 0x7f )
return 1;
if( s < 0x3fff )
return 2;
if( s < 0x1fffff )
return 3;
if( s < 0x0fffffff )
return 4;
return 5;
}
static unsigned mk_ebmlSIntSize(int64_t si) {
unsigned char c_si[8] = { si >> 56, si >> 48, si >> 40, si >> 32, si >> 24, si >> 16, si >> 8, si };
unsigned i = 0;
static unsigned mk_ebml_sint_size( int64_t si )
{
unsigned char c_si[8] = { si >> 56, si >> 48, si >> 40, si >> 32, si >> 24, si >> 16, si >> 8, si };
unsigned i = 0;
if (si < 0)
while (i < 7 && c_si[i] == 0xff && c_si[i+1] & 0x80)
++i;
else
while (i < 7 && c_si[i] == 0 && !(c_si[i+1] & 0x80))
++i;
if( si < 0 )
while( i < 7 && c_si[i] == 0xff && c_si[i+1] & 0x80 )
++i;
else
while( i < 7 && c_si[i] == 0 && !(c_si[i+1] & 0x80) )
++i;
return 8 - i;
return 8 - i;
}
mk_Writer *mk_createWriter(const char *filename) {
mk_Writer *w = malloc(sizeof(*w));
if (w == NULL)
return NULL;
memset(w, 0, sizeof(*w));
w->root = mk_createContext(w, NULL, 0);
if (w->root == NULL) {
free(w);
return NULL;
}
w->fp = fopen(filename, "wb");
if (w->fp == NULL) {
mk_destroyContexts(w);
free(w);
return NULL;
}
w->timescale = 1000000;
return w;
mk_writer *mk_create_writer( const char *filename )
{
mk_writer *w = malloc( sizeof(*w) );
if( !w )
return NULL;
memset( w, 0, sizeof(*w) );
w->root = mk_create_context( w, NULL, 0 );
if( !w->root )
{
free( w );
return NULL;
}
w->fp = fopen( filename, "wb" );
if( !w->fp )
{
mk_destroy_contexts( w );
free( w );
return NULL;
}
w->timescale = 1000000;
return w;
}
int mk_writeHeader(mk_Writer *w, const char *writingApp,
const char *codecID,
const void *codecPrivate, unsigned codecPrivateSize,
int64_t default_frame_duration,
int64_t timescale,
unsigned width, unsigned height,
unsigned d_width, unsigned d_height)
int mk_writeHeader( mk_writer *w, const char *writing_app,
const char *codec_id,
const void *codec_private, unsigned codec_private_size,
int64_t default_frame_duration,
int64_t timescale,
unsigned width, unsigned height,
unsigned d_width, unsigned d_height )
{
mk_Context *c, *ti, *v;
if (w->wrote_header)
return -1;
w->timescale = timescale;
w->def_duration = default_frame_duration;
if ((c = mk_createContext(w, w->root, 0x1a45dfa3)) == NULL) // EBML
return -1;
CHECK(mk_writeUInt(c, 0x4286, 1)); // EBMLVersion
CHECK(mk_writeUInt(c, 0x42f7, 1)); // EBMLReadVersion
CHECK(mk_writeUInt(c, 0x42f2, 4)); // EBMLMaxIDLength
CHECK(mk_writeUInt(c, 0x42f3, 8)); // EBMLMaxSizeLength
CHECK(mk_writeStr(c, 0x4282, "matroska")); // DocType
CHECK(mk_writeUInt(c, 0x4287, 1)); // DocTypeVersion
CHECK(mk_writeUInt(c, 0x4285, 1)); // DocTypeReadversion
CHECK(mk_closeContext(c, 0));
if ((c = mk_createContext(w, w->root, 0x18538067)) == NULL) // Segment
return -1;