X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=modules%2Fdemux%2Frawvid.c;h=fcd8c6d8d07c80477054c915c04e268990663d57;hb=b78ed59b346fbca13d4ad0bcacf2b701f6de093f;hp=8aac2489cb84df98897e16703350038f81c0a5ca;hpb=f57013c6a84618d4b9bd943c46f3a1528819e3af;p=vlc diff --git a/modules/demux/rawvid.c b/modules/demux/rawvid.c index 8aac2489cb..fcd8c6d8d0 100644 --- a/modules/demux/rawvid.c +++ b/modules/demux/rawvid.c @@ -2,9 +2,10 @@ * rawvid.c : raw video input module for vlc ***************************************************************************** * Copyright (C) 2007 the VideoLAN team - * $Id: rawdv.c 18062 2006-11-26 14:20:34Z zorglub $ + * $Id$ * * Authors: Gildas Bazin + * Antoine Cellerier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,10 +25,10 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ #include #include +#include /* vout_InitFormat */ /***************************************************************************** * Module descriptor @@ -47,17 +48,28 @@ static void Close( vlc_object_t * ); #define HEIGHT_LONGTEXT N_("This specifies the height in pixels of the raw " \ "video stream.") +#define CHROMA_TEXT N_("Force chroma (Use carefully)") +#define CHROMA_LONGTEXT N_("Force chroma. This is a four character string.") + +#define ASPECT_RATIO_TEXT N_("Aspect ratio") +#define ASPECT_RATIO_LONGTEXT N_( \ + "Aspect ratio (4:3, 16:9). Default is square pixels." ) + vlc_module_begin(); set_shortname( "Raw Video" ); set_description( _("Raw video demuxer") ); - set_capability( "demux2", 2 ); + set_capability( "demux2", 3 ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); set_callbacks( Open, Close ); add_shortcut( "rawvideo" ); - add_float( "rawvid-fps", 25, 0, FPS_TEXT, FPS_LONGTEXT, VLC_FALSE ); - add_integer( "rawvid-width", 176, 0, WIDTH_TEXT, WIDTH_LONGTEXT, 0 ); - add_integer( "rawvid-height", 144, 0, HEIGHT_TEXT, HEIGHT_LONGTEXT, 0 ); + add_float( "rawvid-fps", 0, 0, FPS_TEXT, FPS_LONGTEXT, VLC_FALSE ); + add_integer( "rawvid-width", 0, 0, WIDTH_TEXT, WIDTH_LONGTEXT, 0 ); + add_integer( "rawvid-height", 0, 0, HEIGHT_TEXT, HEIGHT_LONGTEXT, 0 ); + add_string( "rawvid-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, + VLC_TRUE ); + add_string( "rawvid-aspect-ratio", NULL, NULL, + ASPECT_RATIO_TEXT, ASPECT_RATIO_LONGTEXT, VLC_TRUE ); vlc_module_end(); /***************************************************************************** @@ -72,6 +84,8 @@ struct demux_sys_t es_format_t fmt_video; mtime_t i_pcr; + + vlc_bool_t b_y4m; }; /***************************************************************************** @@ -80,6 +94,27 @@ struct demux_sys_t static int Demux( demux_t * ); static int Control( demux_t *, int i_query, va_list args ); +struct preset_t +{ + const char *psz_ext; + int i_width; + int i_height; + double f_fps; + const char *psz_aspect_ratio; + const char *psz_chroma; +}; + +static struct preset_t p_presets[] = +{ + { "sqcif", 128, 96, 29.97, "4:3", "YV12" }, + { "qcif", 176, 144, 29.97, "4:3", "YV12" }, + { "cif", 352, 288, 29.97, "4:3", "YV12" }, + { "4cif", 704, 576, 29.97, "4:3", "YV12" }, + { "16cif", 1408, 1152, 29.97, "4:3", "YV12" }, + { "yuv", 176, 144, 25, "4:3", "YV12" }, + { "", 0, 0, 0., "", "" } +}; + /***************************************************************************** * Open: initializes raw DV demux structures *****************************************************************************/ @@ -88,16 +123,39 @@ static int Open( vlc_object_t * p_this ) demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; int i_width, i_height; - vlc_value_t val; char *psz_ext; + char *psz_chroma; + uint32_t i_chroma; + char *psz_aspect_ratio; + unsigned int i_aspect = 0; + struct preset_t *p_preset = NULL; + const uint8_t *p_peek; + vlc_bool_t b_valid = VLC_FALSE; + vlc_bool_t b_y4m = VLC_FALSE; + + if( stream_Peek( p_demux->s, &p_peek, 9 ) == 9 ) + { + /* http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 */ + if( !strncmp( (char *)p_peek, "YUV4MPEG2", 9 ) ) + { + b_valid = VLC_TRUE; + b_y4m = VLC_TRUE; + } + } - /* Check for YUV file extension */ psz_ext = strrchr( p_demux->psz_path, '.' ); - if( ( !psz_ext || strcasecmp( psz_ext, ".yuv") ) && - strcmp(p_demux->psz_demux, "rawvid") ) + if( psz_ext ) { - return VLC_EGENERIC; + psz_ext++; + for( p_preset = p_presets; *p_preset->psz_ext; p_preset++ ) + if( !strcasecmp( psz_ext, p_preset->psz_ext ) ) + { + b_valid = VLC_TRUE; + break; + } } + if( !b_valid && !p_demux->b_force ) + return VLC_EGENERIC; /* Set p_input field */ p_demux->pf_demux = Demux; @@ -105,21 +163,162 @@ static int Open( vlc_object_t * p_this ) p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->i_pcr = 1; - var_Create( p_demux, "rawvid-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); - var_Get( p_demux, "rawvid-fps", &val ); - p_sys->f_fps = val.f_float; - var_Create( p_demux, "rawvid-width", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); - var_Get( p_demux, "rawvid-width", &val ); - i_width = val.i_int; - var_Create( p_demux, "rawvid-height", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT); - var_Get( p_demux, "rawvid-height", &val ); - i_height = val.i_int; - - /* Only handle YV12 for now */ - es_format_Init( &p_sys->fmt_video, VIDEO_ES, VLC_FOURCC('Y','V','1','2') ); - p_sys->fmt_video.video.i_width = i_width; - p_sys->fmt_video.video.i_height = i_height; - p_sys->frame_size = i_width * i_height * 3 / 2; + 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" ); + + if( b_y4m ) + { + char *psz; + char *buf; + int a, b; + psz = stream_ReadLine( p_demux->s ); + + /* TODO: handle interlacing */ + +#define READ_FRAC( key, num, den ) \ + buf = strchr( psz+9, key );\ + if( buf )\ + {\ + char *end = strchr( buf, ' ' );\ + char *sep;\ + if( end ) *end = '\0';\ + sep = strchr( buf, ':' );\ + if( sep )\ + {\ + *sep = '\0';\ + den = atoi( sep+1 );\ + }\ + else\ + {\ + den = 1;\ + }\ + num = atoi( buf+1 );\ + if( sep ) *sep = ':';\ + if( end ) *end = ' ';\ + } + READ_FRAC( 'W', i_width, a ) + READ_FRAC( 'H', i_height, a ) + READ_FRAC( 'F', a, b ) + p_sys->f_fps = (double)a/(double)b; + READ_FRAC( 'A', a, b ) + if( b != 0 ) i_aspect = a * VOUT_ASPECT_FACTOR / b; + + buf = strchr( psz+9, 'C' ); + if( buf ) + { + char *end = strchr( buf, ' ' ); + if( end ) *end = '\0'; + buf++; + if( !strncmp( buf, "C420jpeg", 8 ) ) + { + psz_chroma = strdup( "I420" ); + } + else if( !strncmp( buf, "C420paldv", 9 ) ) + { + psz_chroma = strdup( "I420" ); + } + else if( !strncmp( buf, "C420", 4 ) ) + { + psz_chroma = strdup( "I420" ); + } + else if( !strncmp( buf, "C422", 4 ) ) + { + psz_chroma = strdup( "I422" ); + } + else if( !strncmp( buf, "C444", 4 ) ) + { + psz_chroma = strdup( "I444" ); + } + else + { + msg_Warn( p_demux, "Unknown YUV4MPEG2 chroma type \"%s\"", + buf ); + } + if( end ) *end = ' '; + } + + free( psz ); + } + + if( p_preset && *p_preset->psz_ext ) + { + if( !i_width ) i_width = p_preset->i_width; + if( !i_height ) i_height = p_preset->i_height; + if( !p_sys->f_fps ) p_sys->f_fps = p_preset->f_fps; + if( !*psz_aspect_ratio ) + { + free( psz_aspect_ratio ); + psz_aspect_ratio = strdup( psz_aspect_ratio ); + } + if( !*psz_chroma ) + { + free( psz_chroma ); + psz_chroma = strdup( psz_chroma ); + } + } + + if( i_width <= 0 || i_height <= 0 ) + { + msg_Err( p_demux, "width and height must be strictly positive." ); + free( psz_aspect_ratio ); + free( psz_chroma ); + free( p_sys ); + return VLC_EGENERIC; + } + + if( !i_aspect ) + { + if( psz_aspect_ratio && *psz_aspect_ratio ) + { + 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 ) + { + memcpy( &i_chroma, psz_chroma, 4 ); + msg_Dbg( p_demux, "Forcing chroma to 0x%.8x (%4.4s)", i_chroma, + (char*)&i_chroma ); + } + else + { + i_chroma = VLC_FOURCC('Y','V','1','2'); + msg_Dbg( p_demux, "Using default chroma 0x%.8x (%4.4s)", i_chroma, + (char*)&i_chroma ); + } + free( psz_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, + i_aspect ); + if( !p_sys->fmt_video.video.i_bits_per_pixel ) + { + msg_Err( p_demux, "Unsupported chroma 0x%.8x (%4.4s)", i_chroma, + (char*)&i_chroma ); + free( p_sys ); + return VLC_EGENERIC; + } + p_sys->frame_size = i_width * i_height + * 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 ); return VLC_SUCCESS; @@ -148,6 +347,19 @@ static int Demux( demux_t *p_demux ) /* Call the pace control */ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr ); + if( p_sys->b_y4m ) + { + /* Skip the frame header */ + unsigned char psz_buf[10]; + psz_buf[9] = '\0'; + stream_Read( p_demux->s, psz_buf, strlen( "FRAME" ) ); + while( psz_buf[0] != 0x0a ) + { + if( stream_Read( p_demux->s, psz_buf, 1 ) < 1 ) + return 0; + } + } + if( ( p_block = stream_Block( p_demux->s, p_sys->frame_size ) ) == NULL ) { /* EOF */