Commit cf0633ae authored by David Flynn's avatar David Flynn Committed by Laurent Aimar

rawvideo: Fix timestamps & input options

demux:
 - Use accurate timestamps (date_t)
 - Signal frame rate in fmt_out
 - Fix aspect ratio for YUV4MPEG2
 - Reoganise input options to allow sensible overrides
   Ie: extension gussing < yuv4mpeg < cmdline

codec/packetizer:
 - Fix incorrect assumption of 25 fps video
 - Use accurate timestamps (date_t)
 - Copy input format as output format (to preserve frame rate)
 - Set progressive flag per picture

TODO:
 - Have module option for interlaced
 - Detect interlaced in demux for YUV4MPEG2
 - Have codec read set the interlaced flags in the video
 All seems rather tricky for the moment (well, YUV4MPEG2 bit does,
 since the demuxer strips the headers that reveal the interlace
 mode).
Signed-off-by: default avatarDavid Flynn <davidf@rd.bbc.co.uk>
Signed-off-by: default avatarLaurent Aimar <fenrir@videolan.org>
parent 038ff7b2
...@@ -50,8 +50,7 @@ struct decoder_sys_t ...@@ -50,8 +50,7 @@ struct decoder_sys_t
/* /*
* Common properties * Common properties
*/ */
mtime_t i_pts; date_t pts;
}; };
/**************************************************************************** /****************************************************************************
...@@ -135,7 +134,6 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -135,7 +134,6 @@ static int OpenDecoder( vlc_object_t *p_this )
return VLC_ENOMEM; return VLC_ENOMEM;
/* Misc init */ /* Misc init */
p_dec->p_sys->b_packetizer = false; p_dec->p_sys->b_packetizer = false;
p_sys->i_pts = 0;
p_sys->b_invert = 0; p_sys->b_invert = 0;
if( (int)p_dec->fmt_in.video.i_height < 0 ) if( (int)p_dec->fmt_in.video.i_height < 0 )
...@@ -153,6 +151,19 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -153,6 +151,19 @@ static int OpenDecoder( vlc_object_t *p_this )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
if( p_dec->fmt_out.video.i_frame_rate == 0 ||
p_dec->fmt_out.video.i_frame_rate_base == 0)
{
msg_Err( p_dec, "invalid frame rate %d/%d",
p_dec->fmt_out.video.i_frame_rate,
p_dec->fmt_out.video.i_frame_rate_base);
return VLC_EGENERIC;
}
date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate,
p_dec->fmt_out.video.i_frame_rate_base);
/* Find out p_vdec->i_raw_size */ /* Find out p_vdec->i_raw_size */
vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec,
p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_width,
...@@ -161,22 +172,11 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -161,22 +172,11 @@ static int OpenDecoder( vlc_object_t *p_this )
p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel * p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel *
p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8; p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8;
/* Set output properties */
p_dec->fmt_out.i_cat = VIDEO_ES;
p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
if( !p_dec->fmt_in.video.i_aspect ) if( !p_dec->fmt_in.video.i_aspect )
{ {
p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
} }
else p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
if( p_dec->fmt_in.video.i_rmask )
p_dec->fmt_out.video.i_rmask = p_dec->fmt_in.video.i_rmask;
if( p_dec->fmt_in.video.i_gmask )
p_dec->fmt_out.video.i_gmask = p_dec->fmt_in.video.i_gmask;
if( p_dec->fmt_in.video.i_bmask )
p_dec->fmt_out.video.i_bmask = p_dec->fmt_in.video.i_bmask;
/* Set callbacks */ /* Set callbacks */
p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
...@@ -213,18 +213,25 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -213,18 +213,25 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_block = *pp_block; p_block = *pp_block;
if( !p_sys->i_pts && !p_block->i_pts && !p_block->i_dts ) if( (!p_block->i_pts || !p_block->i_dts) && !date_Get( &p_sys->pts ) )
{ {
/* We've just started the stream, wait for the first PTS. */ /* We've just started the stream, wait for the first PTS. */
block_Release( p_block ); block_Release( p_block );
return NULL; return NULL;
} }
/* Date management */ /* Date management: If there is a pts avaliable, use that. */
if( p_block->i_pts > 0 || p_block->i_dts > 0 ) if( p_block->i_pts )
{
date_Set( &p_sys->pts, p_block->i_pts );
}
else if( p_block->i_dts )
{ {
if( p_block->i_pts > 0 ) p_sys->i_pts = p_block->i_pts; /* NB, davidf doesn't quite agree with this in general, it is ok
else if( p_block->i_dts > 0 ) p_sys->i_pts = p_block->i_dts; * for rawvideo since it is in order (ie pts=dts), however, it
* may not be ok for an out-of-order codec, so don't copy this
* without thinking */
date_Set( &p_sys->pts, p_block->i_dts );
} }
if( p_block->i_buffer < p_sys->i_raw_size ) if( p_block->i_buffer < p_sys->i_raw_size )
...@@ -246,7 +253,7 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -246,7 +253,7 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
} }
/* Date management: 1 frame per packet */ /* Date management: 1 frame per packet */
p_sys->i_pts += ( INT64_C(1000000) * 1.0 / 25 /*FIXME*/ ); date_Increment( &p_sys->pts, 1 );
*pp_block = NULL; *pp_block = NULL;
return p_buf; return p_buf;
...@@ -298,7 +305,8 @@ static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block ) ...@@ -298,7 +305,8 @@ static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block )
FillPicture( p_dec, p_block, p_pic ); FillPicture( p_dec, p_block, p_pic );
p_pic->date = p_sys->i_pts; p_pic->date = date_Get( &p_sys->pts );
p_pic->b_progressive = true;
block_Release( p_block ); block_Release( p_block );
return p_pic; return p_pic;
...@@ -311,7 +319,7 @@ static block_t *SendFrame( decoder_t *p_dec, block_t *p_block ) ...@@ -311,7 +319,7 @@ static block_t *SendFrame( decoder_t *p_dec, block_t *p_block )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
p_block->i_dts = p_block->i_pts = p_sys->i_pts; p_block->i_dts = p_block->i_pts = date_Get( &p_sys->pts );
if( p_sys->b_invert ) if( p_sys->b_invert )
{ {
......
...@@ -43,7 +43,7 @@ static void Close( vlc_object_t * ); ...@@ -43,7 +43,7 @@ static void Close( vlc_object_t * );
#define FPS_TEXT N_("Frames per Second") #define FPS_TEXT N_("Frames per Second")
#define FPS_LONGTEXT N_("This is the desired frame rate when " \ #define FPS_LONGTEXT N_("This is the desired frame rate when " \
"playing raw video streams.") "playing raw video streams. In the form 30000/1001 or 29.97")
#define WIDTH_TEXT N_("Width") #define WIDTH_TEXT N_("Width")
#define WIDTH_LONGTEXT N_("This specifies the width in pixels of the raw " \ #define WIDTH_LONGTEXT N_("This specifies the width in pixels of the raw " \
...@@ -58,7 +58,7 @@ static void Close( vlc_object_t * ); ...@@ -58,7 +58,7 @@ static void Close( vlc_object_t * );
#define ASPECT_RATIO_TEXT N_("Aspect ratio") #define ASPECT_RATIO_TEXT N_("Aspect ratio")
#define ASPECT_RATIO_LONGTEXT N_( \ #define ASPECT_RATIO_LONGTEXT N_( \
"Aspect ratio (4:3, 16:9). Default is square pixels." ) "Aspect ratio (4:3, 16:9). Default assumes square pixels." )
vlc_module_begin () vlc_module_begin ()
set_shortname( "Raw Video" ) set_shortname( "Raw Video" )
...@@ -68,7 +68,7 @@ vlc_module_begin () ...@@ -68,7 +68,7 @@ vlc_module_begin ()
set_subcategory( SUBCAT_INPUT_DEMUX ) set_subcategory( SUBCAT_INPUT_DEMUX )
set_callbacks( Open, Close ) set_callbacks( Open, Close )
add_shortcut( "rawvideo" ) add_shortcut( "rawvideo" )
add_float( "rawvid-fps", 0, 0, FPS_TEXT, FPS_LONGTEXT, false ) add_string( "rawvid-fps", NULL, NULL, FPS_TEXT, FPS_LONGTEXT, false )
add_integer( "rawvid-width", 0, 0, WIDTH_TEXT, WIDTH_LONGTEXT, 0 ) add_integer( "rawvid-width", 0, 0, WIDTH_TEXT, WIDTH_LONGTEXT, 0 )
add_integer( "rawvid-height", 0, 0, HEIGHT_TEXT, HEIGHT_LONGTEXT, 0 ) add_integer( "rawvid-height", 0, 0, HEIGHT_TEXT, HEIGHT_LONGTEXT, 0 )
add_string( "rawvid-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, add_string( "rawvid-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
...@@ -83,12 +83,11 @@ vlc_module_end () ...@@ -83,12 +83,11 @@ vlc_module_end ()
struct demux_sys_t struct demux_sys_t
{ {
int frame_size; int frame_size;
float f_fps;
es_out_id_t *p_es_video; es_out_id_t *p_es_video;
es_format_t fmt_video; es_format_t fmt_video;
mtime_t i_pcr; date_t pcr;
bool b_y4m; bool b_y4m;
}; };
...@@ -104,20 +103,22 @@ struct preset_t ...@@ -104,20 +103,22 @@ struct preset_t
const char *psz_ext; const char *psz_ext;
int i_width; int i_width;
int i_height; int i_height;
double f_fps; unsigned u_fps_num;
const char *psz_aspect_ratio; unsigned u_fps_den;
const char *psz_chroma; unsigned u_ar_num;
unsigned u_ar_den;
int i_chroma;
}; };
static const struct preset_t p_presets[] = static const struct preset_t p_presets[] =
{ {
{ "sqcif", 128, 96, 29.97, "4:3", "YV12" }, { "sqcif", 128, 96, 30000, 1001, 4,3, VLC_FOURCC('Y','V','1','2') },
{ "qcif", 176, 144, 29.97, "4:3", "YV12" }, { "qcif", 176, 144, 30000, 1001, 4,3, VLC_FOURCC('Y','V','1','2') },
{ "cif", 352, 288, 29.97, "4:3", "YV12" }, { "cif", 352, 288, 30000, 1001, 4,3, VLC_FOURCC('Y','V','1','2') },
{ "4cif", 704, 576, 29.97, "4:3", "YV12" }, { "4cif", 704, 576, 30000, 1001, 4,3, VLC_FOURCC('Y','V','1','2') },
{ "16cif", 1408, 1152, 29.97, "4:3", "YV12" }, { "16cif", 1408, 1152, 30000, 1001, 4,3, VLC_FOURCC('Y','V','1','2') },
{ "yuv", 176, 144, 25, "4:3", "YV12" }, { "yuv", 176, 144, 25, 1, 4,3, VLC_FOURCC('Y','V','1','2') },
{ "", 0, 0, 0., "", "" } { NULL, 0, 0, 0, 0, 0,0, 0 }
}; };
/***************************************************************************** /*****************************************************************************
...@@ -127,11 +128,10 @@ static int Open( vlc_object_t * p_this ) ...@@ -127,11 +128,10 @@ static int Open( vlc_object_t * p_this )
{ {
demux_t *p_demux = (demux_t*)p_this; demux_t *p_demux = (demux_t*)p_this;
demux_sys_t *p_sys; demux_sys_t *p_sys;
int i_width, i_height; int i_width=-1, i_height=-1;
unsigned u_fps_num=0, u_fps_den=1;
char *psz_ext; char *psz_ext;
char *psz_chroma;
uint32_t i_chroma; uint32_t i_chroma;
char *psz_aspect_ratio;
unsigned int i_aspect = 0; unsigned int i_aspect = 0;
const struct preset_t *p_preset = NULL; const struct preset_t *p_preset = NULL;
const uint8_t *p_peek; const uint8_t *p_peek;
...@@ -148,16 +148,20 @@ static int Open( vlc_object_t * p_this ) ...@@ -148,16 +148,20 @@ static int Open( vlc_object_t * p_this )
} }
} }
/* guess preset based on file extension */
psz_ext = strrchr( p_demux->psz_path, '.' ); psz_ext = strrchr( p_demux->psz_path, '.' );
if( psz_ext ) if( psz_ext )
{ {
psz_ext++; psz_ext++;
for( p_preset = p_presets; *p_preset->psz_ext; p_preset++ ) for( int i = 0; p_presets[i].psz_ext ; i++ )
if( !strcasecmp( psz_ext, p_preset->psz_ext ) ) {
if( !strcasecmp( psz_ext, p_presets[i].psz_ext ) )
{ {
p_preset = &p_presets[i];
b_valid = true; b_valid = true;
break; break;
} }
}
} }
if( !b_valid && !p_demux->b_force ) if( !b_valid && !p_demux->b_force )
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -169,15 +173,20 @@ static int Open( vlc_object_t * p_this ) ...@@ -169,15 +173,20 @@ static int Open( vlc_object_t * p_this )
if( !p_sys ) if( !p_sys )
return VLC_ENOMEM; return VLC_ENOMEM;
p_sys->i_pcr = 1;
p_sys->b_y4m = b_y4m; p_sys->b_y4m = b_y4m;
p_sys->f_fps = var_CreateGetFloat( p_demux, "rawvid-fps" );
i_width = var_CreateGetInteger( p_demux, "rawvid-width" );
i_height = var_CreateGetInteger( p_demux, "rawvid-height" );
psz_chroma = var_CreateGetString( p_demux, "rawvid-chroma" );
psz_aspect_ratio = var_CreateGetString( p_demux, "rawvid-aspect-ratio" );
/* guess the parameters based on the preset */
if( p_preset )
{
i_width = p_preset->i_width;
i_height = p_preset->i_height;
u_fps_num = p_preset->u_fps_num;
u_fps_den = p_preset->u_fps_den;
i_aspect = VOUT_ASPECT_FACTOR * p_preset->u_ar_num / p_preset->u_ar_den;
i_chroma = p_preset->i_chroma;
}
/* override presets if yuv4mpeg2 */
if( b_y4m ) if( b_y4m )
{ {
char *psz; char *psz;
...@@ -186,7 +195,8 @@ static int Open( vlc_object_t * p_this ) ...@@ -186,7 +195,8 @@ static int Open( vlc_object_t * p_this )
int b = 1; int b = 1;
psz = stream_ReadLine( p_demux->s ); psz = stream_ReadLine( p_demux->s );
/* TODO: handle interlacing */ /* NB, it is not possible to handle interlaced here, since the
* interlaced picture flags are in picture_t not block_t */
#define READ_FRAC( key, num, den ) \ #define READ_FRAC( key, num, den ) \
buf = strstr( psz+9, key );\ buf = strstr( psz+9, key );\
...@@ -211,10 +221,13 @@ static int Open( vlc_object_t * p_this ) ...@@ -211,10 +221,13 @@ static int Open( vlc_object_t * p_this )
} }
READ_FRAC( " W", i_width, a ) READ_FRAC( " W", i_width, a )
READ_FRAC( " H", i_height, a ) READ_FRAC( " H", i_height, a )
READ_FRAC( " F", a, b ) READ_FRAC( " F", u_fps_num, u_fps_den )
p_sys->f_fps = (double)a/(double)b;
READ_FRAC( " A", a, b ) READ_FRAC( " A", a, b )
if( b != 0 ) i_aspect = a * VOUT_ASPECT_FACTOR / b; /* Try to calculate aspect ratio here, rather than store ratio
* in u_ar_{num,den}, since width may be overridden by then.
* Plus, a:b is sar. */
if( b != 0 )
i_aspect = VOUT_ASPECT_FACTOR * a * i_width / (b * i_height);
buf = strstr( psz+9, " C" ); buf = strstr( psz+9, " C" );
if( buf ) if( buf )
...@@ -222,34 +235,26 @@ static int Open( vlc_object_t * p_this ) ...@@ -222,34 +235,26 @@ static int Open( vlc_object_t * p_this )
char *end = strchr( buf+1, ' ' ); char *end = strchr( buf+1, ' ' );
if( end ) *end = '\0'; if( end ) *end = '\0';
buf+=2; buf+=2;
if( !strncmp( buf, "420jpeg", 7 ) ) if( !strncmp( buf, "420jpeg", 7 ) ) {
{ i_chroma = VLC_FOURCC('I','4','2','0');
psz_chroma = strdup( "I420" );
} }
else if( !strncmp( buf, "420paldv", 8 ) ) else if( !strncmp( buf, "420paldv", 8 ) ) {
{ i_chroma = VLC_FOURCC('I','4','2','0');
psz_chroma = strdup( "I420" );
} }
else if( !strncmp( buf, "420", 3 ) ) else if( !strncmp( buf, "420", 3 ) ) {
{ i_chroma = VLC_FOURCC('I','4','2','0');
psz_chroma = strdup( "I420" );
} }
else if( !strncmp( buf, "422", 3 ) ) else if( !strncmp( buf, "422", 3 ) ) {
{ i_chroma = VLC_FOURCC('I','4','2','2');
psz_chroma = strdup( "I422" );
} }
else if( !strncmp( buf, "444", 3 ) ) else if( !strncmp( buf, "444", 3 ) ) {
{ i_chroma = VLC_FOURCC('I','4','4','4');
psz_chroma = strdup( "I444" );
} }
else if( !strncmp( buf, "mono", 4 ) ) else if( !strncmp( buf, "mono", 4 ) ) {
{ i_chroma = VLC_FOURCC('G','R','E','Y');
psz_chroma = strdup( "GREY" );
} }
else else {
{ msg_Warn( p_demux, "Unknown YUV4MPEG2 chroma type \"%s\"", buf );
msg_Warn( p_demux, "Unknown YUV4MPEG2 chroma type \"%s\"",
buf );
} }
if( end ) *end = ' '; if( end ) *end = ' ';
} }
...@@ -257,84 +262,118 @@ static int Open( vlc_object_t * p_this ) ...@@ -257,84 +262,118 @@ static int Open( vlc_object_t * p_this )
free( psz ); free( psz );
} }
if( p_preset && *p_preset->psz_ext ) /* allow the user to override anything guessed from the input */
int i_tmp;
i_tmp = var_CreateGetInteger( p_demux, "rawvid-width" );
if( i_tmp ) i_width = i_tmp;
i_tmp = var_CreateGetInteger( p_demux, "rawvid-height" );
if( i_tmp ) i_height = i_tmp;
char *psz_tmp;
psz_tmp = var_CreateGetString( p_demux, "rawvid-chroma" );
if( psz_tmp )
{ {
if( !i_width ) i_width = p_preset->i_width; if( strlen( psz_tmp ) != 4 )
if( !i_height ) i_height = p_preset->i_height; {
if( !p_sys->f_fps ) p_sys->f_fps = p_preset->f_fps; msg_Err( p_demux, "Invalid fourcc format/chroma specification %s"
if( !*psz_aspect_ratio ) " expecting four characters eg, UYVY", psz_tmp );
free( psz_tmp );
goto error;
}
memcpy( &i_chroma, psz_tmp, 4 );
msg_Dbg( p_demux, "Forcing chroma to 0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma );
free( psz_tmp );
}
psz_tmp = var_CreateGetString( p_demux, "rawvid-fps" );
if( psz_tmp ) {
char *p_ptr;
/* fps can either be n/d or q.f
* for accuracy, avoid representation in float */
u_fps_num = strtol( psz_tmp, &p_ptr, 10 );
if( *p_ptr == '/' )
{ {
free( psz_aspect_ratio ); p_ptr++;
psz_aspect_ratio = strdup( psz_aspect_ratio ); u_fps_den = strtol( p_ptr, NULL, 10 );
} }
if( !*psz_chroma ) else if( *p_ptr == '.' )
{ {
free( psz_chroma ); char *p_end;
psz_chroma = strdup( psz_chroma ); p_ptr++;
int i_frac = strtol( p_ptr, &p_end, 10 );
u_fps_den = (p_end - p_ptr) * 10;
if( !u_fps_den )
u_fps_den = 1;
u_fps_num = u_fps_num * u_fps_den + i_frac;
} }
else if( *p_ptr == '\0')
{
u_fps_den = 1;
}
free( psz_tmp );
} }
if( i_width <= 0 || i_height <= 0 ) psz_tmp = var_CreateGetString( p_demux, "rawvid-aspect-ratio" );
if( psz_tmp )
{ {
msg_Err( p_demux, "width and height must be strictly positive." ); char *psz_denominator = strchr( psz_tmp, ':' );
free( psz_aspect_ratio ); if( psz_denominator )
free( psz_chroma ); {
free( p_sys ); *psz_denominator++ = '\0';
return VLC_EGENERIC; i_aspect = atoi( psz_tmp ) * VOUT_ASPECT_FACTOR
/ atoi( psz_denominator );
}
free( psz_tmp );
} }
if( !i_aspect ) /* moan about anything wrong */
if( i_width <= 0 || i_height <= 0 )
{ {
if( psz_aspect_ratio && *psz_aspect_ratio ) msg_Err( p_demux, "width and height must be strictly positive." );
{ goto error;
char *psz_parser = strchr( psz_aspect_ratio, ':' );
if( psz_parser )
{
*psz_parser++ = '\0';
i_aspect = atoi( psz_aspect_ratio ) * VOUT_ASPECT_FACTOR
/ atoi( psz_parser );
}
else
{
i_aspect = atof( psz_aspect_ratio ) * VOUT_ASPECT_FACTOR;
}
}
else
{
i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height;
}
} }
free( psz_aspect_ratio );
if( psz_chroma && strlen( psz_chroma ) >= 4 ) if( !u_fps_num || !u_fps_den )
{ {
memcpy( &i_chroma, psz_chroma, 4 ); msg_Err( p_demux, "invalid or no framerate specified." );
msg_Dbg( p_demux, "Forcing chroma to 0x%.8x (%4.4s)", i_chroma, goto error;
(char*)&i_chroma );
} }
else
/* fixup anything missing with sensible assumptions */
if( !i_aspect )
{ {
i_chroma = VLC_FOURCC('Y','V','1','2'); /* assume 1:1 sar */
msg_Dbg( p_demux, "Using default chroma 0x%.8x (%4.4s)", i_chroma, i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height;
(char*)&i_chroma );
} }
free( psz_chroma );
es_format_Init( &p_sys->fmt_video, VIDEO_ES, i_chroma ); es_format_Init( &p_sys->fmt_video, VIDEO_ES, i_chroma );
vout_InitFormat( &p_sys->fmt_video.video, i_chroma, i_width, i_height, vout_InitFormat( &p_sys->fmt_video.video, i_chroma, i_width, i_height,
i_aspect ); i_aspect );
vlc_ureduce( &p_sys->fmt_video.video.i_frame_rate,
&p_sys->fmt_video.video.i_frame_rate_base,
u_fps_num, u_fps_den, 0);
date_Init( &p_sys->pcr, p_sys->fmt_video.video.i_frame_rate,
p_sys->fmt_video.video.i_frame_rate_base );
date_Set( &p_sys->pcr, 1 );
if( !p_sys->fmt_video.video.i_bits_per_pixel ) if( !p_sys->fmt_video.video.i_bits_per_pixel )
{ {
msg_Err( p_demux, "Unsupported chroma 0x%.8x (%4.4s)", i_chroma, msg_Err( p_demux, "Unsupported chroma 0x%.8x (%4.4s)", i_chroma,
(char*)&i_chroma ); (char*)&i_chroma );
free( p_sys ); goto error;
return VLC_EGENERIC;
} }
p_sys->frame_size = i_width * i_height p_sys->frame_size = i_width * i_height
* p_sys->fmt_video.video.i_bits_per_pixel / 8; * p_sys->fmt_video.video.i_bits_per_pixel / 8;
p_sys->p_es_video = es_out_Add( p_demux->out, &p_sys->fmt_video ); p_sys->p_es_video = es_out_Add( p_demux->out, &p_sys->fmt_video );
return VLC_SUCCESS; return VLC_SUCCESS;
error:
if( p_sys )
free( p_sys );
return VLC_EGENERIC;
} }
/***************************************************************************** /*****************************************************************************
...@@ -356,9 +395,10 @@ static int Demux( demux_t *p_demux ) ...@@ -356,9 +395,10 @@ static int Demux( demux_t *p_demux )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
block_t *p_block; block_t *p_block;
mtime_t i_pcr = date_Get( &p_sys->pcr );
/* Call the pace control */ /* Call the pace control */
es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr ); es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pcr );
if( p_sys->b_y4m ) if( p_sys->b_y4m )
{ {
...@@ -379,10 +419,10 @@ static int Demux( demux_t *p_demux ) ...@@ -379,10 +419,10 @@ static int Demux( demux_t *p_demux )
return 0; return 0;
} }
p_block->i_dts = p_block->i_pts = p_sys->i_pcr; p_block->i_dts = p_block->i_pts = i_pcr;
es_out_Send( p_demux->out, p_sys->p_es_video, p_block ); es_out_Send( p_demux->out, p_sys->p_es_video, p_block );
p_sys->i_pcr += ( INT64_C(1000000) / p_sys->f_fps ); date_Increment( &p_sys->pcr, 1 );
return 1; return 1;
} }
...@@ -394,8 +434,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -394,8 +434,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
/* NB, demux_vaControlHelper only takes int for i_bps currently;
* (2**31)-1 is insufficient to store 1080p50 4:4:4. */
int64_t i_bps = 8LL * p_sys->frame_size * p_sys->pcr.i_divider_num
/ p_sys->pcr.i_divider_den;
/* XXX: DEMUX_SET_TIME is precise here */ /* XXX: DEMUX_SET_TIME is precise here */
return demux_vaControlHelper( p_demux->s, 0, -1, return demux_vaControlHelper( p_demux->s, 0, -1, i_bps,
p_sys->frame_size * p_sys->f_fps * 8,
p_sys->frame_size, i_query, args ); p_sys->frame_size, i_query, args );
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment