From 9c5a15e467a4a9d2ca804ab03d3925ff21f10390 Mon Sep 17 00:00:00 2001 From: Mike Matsnev Date: Sun, 1 Aug 2010 12:08:20 -0700 Subject: [PATCH] Fix aspect ratio writing in the MKV muxer The braindead Matroska spec dictates aspect ratio to be measured in pixels instead of, well, an actual aspect ratio. --- output/matroska.c | 38 ++++++++++++++++++-------------------- output/matroska_ebml.c | 3 ++- output/matroska_ebml.h | 8 +++++++- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/output/matroska.c b/output/matroska.c index a1219d07..7b265646 100644 --- a/output/matroska.c +++ b/output/matroska.c @@ -27,6 +27,8 @@ typedef struct int width, height, d_width, d_height; + int display_size_units; + int64_t frame_duration; char b_writing_frame; @@ -74,29 +76,25 @@ static int set_param( hnd_t handle, x264_param_t *p_param ) p_mkv->frame_duration = 0; } - p_mkv->width = p_param->i_width; - p_mkv->height = p_param->i_height; - - if( p_param->vui.i_sar_width && p_param->vui.i_sar_height ) - { - dw = (int64_t)p_param->i_width * p_param->vui.i_sar_width; - dh = (int64_t)p_param->i_height * p_param->vui.i_sar_height; - } - else - { - dw = p_param->i_width; - dh = p_param->i_height; - } + p_mkv->width = p_mkv->d_width = p_param->i_width; + p_mkv->height = p_mkv->d_height = p_param->i_height; + p_mkv->display_size_units = DS_PIXELS; - if( dw > 0 && dh > 0 ) + if( p_param->vui.i_sar_width && p_param->vui.i_sar_height + && p_param->vui.i_sar_width != p_param->vui.i_sar_height ) { - int64_t x = gcd( dw, dh ); - dw /= x; - dh /= x; + if ( p_param->vui.i_sar_width > p_param->vui.i_sar_height ) { + dw = (int64_t)p_param->i_width * p_param->vui.i_sar_width / p_param->vui.i_sar_height; + dh = p_param->i_height; + } else { + dw = p_param->i_width; + dh = (int64_t)p_param->i_height * p_param->vui.i_sar_height / p_param->vui.i_sar_width; + } + + p_mkv->d_width = (int)dw; + p_mkv->d_height = (int)dh; } - p_mkv->d_width = (int)dw; - p_mkv->d_height = (int)dh; p_mkv->i_timebase_num = p_param->i_timebase_num; p_mkv->i_timebase_den = p_param->i_timebase_den; @@ -149,7 +147,7 @@ static int write_headers( hnd_t handle, x264_nal_t *p_nal ) ret = mk_writeHeader( p_mkv->w, "x264" X264_VERSION, "V_MPEG4/ISO/AVC", avcC, avcC_len, p_mkv->frame_duration, 50000, p_mkv->width, p_mkv->height, - p_mkv->d_width, p_mkv->d_height ); + p_mkv->d_width, p_mkv->d_height, p_mkv->display_size_units ); if( ret < 0 ) return ret; diff --git a/output/matroska_ebml.c b/output/matroska_ebml.c index adfcaa85..8a502772 100644 --- a/output/matroska_ebml.c +++ b/output/matroska_ebml.c @@ -321,7 +321,7 @@ int mk_writeHeader( mk_writer *w, const char *writing_app, int64_t default_frame_duration, int64_t timescale, unsigned width, unsigned height, - unsigned d_width, unsigned d_height ) + unsigned d_width, unsigned d_height, int display_size_units ) { mk_context *c, *ti, *v; @@ -374,6 +374,7 @@ int mk_writeHeader( mk_writer *w, const char *writing_app, return -1; CHECK( mk_write_uint( v, 0xb0, width ) ); CHECK( mk_write_uint( v, 0xba, height ) ); + CHECK( mk_write_uint( v, 0x54b2, display_size_units ) ); CHECK( mk_write_uint( v, 0x54b0, d_width ) ); CHECK( mk_write_uint( v, 0x54ba, d_height ) ); CHECK( mk_close_context( v, 0 ) ); diff --git a/output/matroska_ebml.h b/output/matroska_ebml.h index 56eb8cce..eb731284 100644 --- a/output/matroska_ebml.h +++ b/output/matroska_ebml.h @@ -21,6 +21,12 @@ #ifndef X264_MATROSKA_EBML_H #define X264_MATROSKA_EBML_H +/* Matroska display size units from the spec */ +#define DS_PIXELS 0 +#define DS_CM 1 +#define DS_INCHES 2 +#define DS_ASPECT_RATIO 3 + typedef struct mk_writer mk_writer; mk_writer *mk_create_writer( const char *filename ); @@ -31,7 +37,7 @@ int mk_writeHeader( mk_writer *w, const char *writing_app, int64_t default_frame_duration, int64_t timescale, unsigned width, unsigned height, - unsigned d_width, unsigned d_height ); + unsigned d_width, unsigned d_height, int display_size_units ); int mk_start_frame( mk_writer *w ); int mk_add_frame_data( mk_writer *w, const void *data, unsigned size ); -- 2.39.2