X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fmpeg%2Fm4v.c;h=88bd4fd2dfac9e7fc448f60df6167b7f02cd5012;hb=806cf5165824be921bf2402ecf11fd3ee6501f9c;hp=007db52a240fd10a7800b90dd88ecc1c6d46b6e4;hpb=bf73ff64ecf2159aabe69d061fedde8e4e268f7b;p=vlc diff --git a/modules/demux/mpeg/m4v.c b/modules/demux/mpeg/m4v.c index 007db52a24..88bd4fd2df 100644 --- a/modules/demux/mpeg/m4v.c +++ b/modules/demux/mpeg/m4v.c @@ -1,8 +1,8 @@ /***************************************************************************** - * m4v.c : MPEG-4 video Stream input module for vlc + * m4v.c : MPEG-4 Video demuxer ***************************************************************************** - * Copyright (C) 2002 VideoLAN - * $Id: m4v.c,v 1.6 2003/08/01 00:05:07 gbazin Exp $ + * Copyright (C) 2002-2004 the VideoLAN team + * $Id$ * * Authors: Laurent Aimar * @@ -18,278 +18,183 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include #include -#include - -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int Activate ( vlc_object_t * ); -static int Demux ( input_thread_t * ); +#include +#include "vlc_codec.h" /***************************************************************************** * Module descriptor *****************************************************************************/ +static int Open ( vlc_object_t * ); +static void Close( vlc_object_t * ); + +#define FPS_TEXT N_("Frames per Second") +#define FPS_LONGTEXT N_("This is the desired frame rate when " \ + "playing MPEG4 video elementary streams.") + vlc_module_begin(); - set_description( _("MPEG-4 video elementary stream demuxer" ) ); - set_capability( "demux", 0 ); - set_callbacks( Activate, NULL ); + set_category( CAT_INPUT ); + set_subcategory( SUBCAT_INPUT_DEMUX ); + set_description( _("MPEG-4 video demuxer" ) ); + set_capability( "demux2", 0 ); + set_callbacks( Open, Close ); add_shortcut( "m4v" ); + add_shortcut( "mp4v" ); + add_float( "m4v-fps", 25, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_FALSE ); + change_safe(); vlc_module_end(); /***************************************************************************** - * Definitions of structures and functions used by this plugins + * Local prototypes *****************************************************************************/ - struct demux_sys_t { - mtime_t i_dts; + mtime_t i_dts; + es_out_id_t *p_es; + float f_fps; - es_descriptor_t *p_es; + decoder_t *p_packetizer; }; +static int Demux( demux_t * ); +static int Control( demux_t *, int, va_list ); + +#define M4V_PACKET_SIZE 4096 /***************************************************************************** - * Activate: initializes MPEGaudio structures + * Open: initializes demux structures *****************************************************************************/ -static int Activate( vlc_object_t * p_this ) +static int Open( vlc_object_t * p_this ) { - input_thread_t * p_input = (input_thread_t *)p_this; - demux_sys_t * p_demux; - input_info_category_t * p_category; - - uint8_t *p_peek; + demux_t *p_demux = (demux_t*)p_this; + demux_sys_t *p_sys; + const uint8_t *p_peek; + vlc_value_t val; - /* Set the demux function */ - p_input->pf_demux = Demux; + if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC; - /* Initialize access plug-in structures. */ - if( p_input->i_mtu == 0 ) + if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 ) { - /* Improve speed. */ - p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE; - } - - /* Have a peep at the show. */ - if( input_Peek( p_input, &p_peek, 4 ) < 4 ) - { - /* Stream shorter than 4 bytes... */ - msg_Err( p_input, "cannot peek()" ); - return( -1 ); - } - - if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 || p_peek[3] > 0x2f ) - { - if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "m4v", 3 ) ) - { - /* user forced */ - msg_Warn( p_input, "this doesn't look like an MPEG-4 ES stream, continuing" ); - } - else + if( !p_demux->b_force ) { - msg_Warn( p_input, "m4v module discarded (invalid startcode)" ); - return( -1 ); + msg_Warn( p_demux, "m4v module discarded (no startcode)" ); + return VLC_EGENERIC; } - } - /* create p_demux and init it */ - if( !( p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t) ) ) ) - { - msg_Err( p_input, "out of memory" ); - return( -1 ); + msg_Warn( p_demux, "this doesn't look like an MPEG-4 ES stream, " + "continuing anyway" ); } - memset( p_demux, 0, sizeof(demux_sys_t) ); - p_demux->i_dts = 0; - vlc_mutex_lock( &p_input->stream.stream_lock ); - if( input_InitStream( p_input, 0 ) == -1) - { - msg_Err( p_input, "cannot init stream" ); - free( p_input->p_demux_data ); - return( -1 ); - } - if( input_AddProgram( p_input, 0, 0) == NULL ) - { - msg_Err( p_input, "cannot add program" ); - free( p_input->p_demux_data ); - return( -1 ); - } - p_input->stream.pp_programs[0]->b_is_ok = 0; - p_input->stream.p_selected_program = p_input->stream.pp_programs[0]; - - /* create our ES */ - p_demux->p_es = input_AddES( p_input, - p_input->stream.p_selected_program, - 1 /* id */, VIDEO_ES, NULL, 0 ); - if( !p_demux->p_es ) - { - vlc_mutex_unlock( &p_input->stream.stream_lock ); - msg_Err( p_input, "out of memory" ); - free( p_input->p_demux_data ); - return( -1 ); - } - p_demux->p_es->i_stream_id = 1; - p_demux->p_es->i_fourcc = VLC_FOURCC('m','p','4','v'); + p_demux->pf_demux = Demux; + p_demux->pf_control= Control; + p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); + p_sys->p_es = NULL; + p_sys->i_dts = 1; - input_SelectES( p_input, p_demux->p_es ); + /* Load the mpeg4video packetizer */ + INIT_VPACKETIZER( p_sys->p_packetizer, 'm', 'p', '4', 'v' ); + es_format_Init( &p_sys->p_packetizer->fmt_out, UNKNOWN_ES, 0 ); - p_input->stream.p_selected_program->b_is_ok = 1; - vlc_mutex_unlock( &p_input->stream.stream_lock ); + LOAD_PACKETIZER_OR_FAIL( p_sys->p_packetizer, "mpeg4 video" ); - vlc_mutex_lock( &p_input->stream.stream_lock ); - p_category = input_InfoCategory( p_input, _("mpeg") ); - input_AddInfo( p_category, _("Input Type"), _("Video MPEG-4 (raw ES)") ); - vlc_mutex_unlock( &p_input->stream.stream_lock ); + /* We need to wait until we get p_extra (VOL header) from the packetizer + * before we create the output */ - return( 0 ); + var_Create( p_demux, "m4v-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); + var_Get( p_demux, "m4v-fps", &val ); + p_sys->f_fps = val.f_float; + + return VLC_SUCCESS; } /***************************************************************************** - * Demux: reads and demuxes data packets - ***************************************************************************** - * Returns -1 in case of error, 0 in case of EOF, 1 otherwise + * Close: frees unused data *****************************************************************************/ -static int FindStartCode( uint8_t *p_data, int i_size, uint8_t i_startcode, uint8_t i_mask ) +static void Close( vlc_object_t * p_this ) { - int i_pos = 0; + demux_t *p_demux = (demux_t*)p_this; + demux_sys_t *p_sys = p_demux->p_sys; - for( i_pos = 0; i_size >= 4; i_pos++,i_size--,p_data++ ) - { - if( p_data[0] == 0 && p_data[1] == 0 && - p_data[2] == 1 && ( p_data[3]&i_mask) == i_startcode ) - { - return( i_pos ); - } - } - return( i_pos ); -} + DESTROY_PACKETIZER( p_sys->p_packetizer) ; -static void PESAddDataPacket( pes_packet_t *p_pes, data_packet_t *p_data ) -{ - if( !p_pes->p_first ) - { - p_pes->p_first = p_data; - p_pes->i_nb_data = 1; - p_pes->i_pes_size = p_data->p_payload_end - p_data->p_payload_start; - } - else - { - p_pes->p_last->p_next = p_data; - p_pes->i_nb_data++; - p_pes->i_pes_size += p_data->p_payload_end - p_data->p_payload_start; - } - p_pes->p_last = p_data; + free( p_sys ); } -static int Demux( input_thread_t * p_input ) +/***************************************************************************** + * Demux: reads and demuxes data packets + ***************************************************************************** + * Returns -1 in case of error, 0 in case of EOF, 1 otherwise + *****************************************************************************/ +static int Demux( demux_t *p_demux) { - demux_sys_t *p_demux = p_input->p_demux_data; - pes_packet_t *p_pes; - data_packet_t *p_data; - uint8_t *p_peek; - int i_peek; - int i_size; - int i_read; - int b_vop; - - input_ClockManageRef( p_input, - p_input->stream.p_selected_program, - p_demux->i_dts ); - - if( (p_pes = input_NewPES( p_input->p_method_data ) ) == NULL ) - { - msg_Err( p_input, "cannot allocate new PES" ); - return( -1 ); - } + demux_sys_t *p_sys = p_demux->p_sys; + block_t *p_block_in, *p_block_out; - /* we will read data into this pes until we found a vop header */ - for( ; ; ) + if( ( p_block_in = stream_Block( p_demux->s, M4V_PACKET_SIZE ) ) == NULL ) { - /* Have a peep at the show. */ - if( ( i_peek = input_Peek( p_input, &p_peek, 512 ) ) < 5 ) - { - /* Stream shorter than 4 bytes... */ - msg_Warn( p_input, "cannot peek()" ); - return( 0 ); - } - - /* vop startcode */ - if( ( i_size = FindStartCode( p_peek, i_peek, 0xb6, 0xff ) ) == 0 ) - { - break; - } - - if( ( i_read = input_SplitBuffer( p_input, - &p_data, - i_size ) ) <= 0 ) - { - msg_Warn( p_input, "error while reading data" ); - break; - } - PESAddDataPacket( p_pes, p_data ); + return 0; } - b_vop = 1; - for( ; ; ) - { - /* Have a peep at the show. */ - if( ( i_peek = input_Peek( p_input, &p_peek, 512 ) ) < 5 ) - { - /* Stream shorter than 4 bytes... */ - msg_Warn( p_input, "cannot peek()" ); - return( 0 ); - } - /* vop startcode */ - if( b_vop ) - i_size = FindStartCode( p_peek + 1, i_peek - 1, 0x00, 0x00 ) + 1; - else - i_size = FindStartCode( p_peek, i_peek, 0x00, 0x00 ); - b_vop = 0; + /* m4v demuxer doesn't set pts/dts at all */ + p_block_in->i_dts = p_sys->i_dts; + p_block_in->i_pts = 0; - if( i_size == 0 ) - { - break; - } - - if( ( i_read = input_SplitBuffer( p_input, - &p_data, - i_size ) ) <= 0 ) + while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) ) + { + while( p_block_out ) { - msg_Warn( p_input, "error while reading data" ); - break; + block_t *p_next = p_block_out->p_next; + + if( p_sys->p_es == NULL ) + { + p_sys->p_packetizer->fmt_out.b_packetized = VLC_TRUE; + p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out); + } + + es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_dts ); + + p_block_out->p_next = NULL; + if( p_block_out->i_pts == p_block_out->i_dts ) + { + p_block_out->i_pts = p_sys->i_dts; + } + else + { + p_block_out->i_pts = 0; + } + p_block_out->i_dts = p_sys->i_dts; + + es_out_Send( p_demux->out, p_sys->p_es, p_block_out ); + + p_block_out = p_next; + + /* FIXME FIXME FIXME FIXME */ + p_sys->i_dts += (mtime_t)1000000 / p_sys->f_fps; + /* FIXME FIXME FIXME FIXME */ } - PESAddDataPacket( p_pes, p_data ); } + return 1; +} - p_pes->i_dts = - p_pes->i_pts = input_ClockGetTS( p_input, - p_input->stream.p_selected_program, - p_demux->i_dts ); - - if( !p_demux->p_es->p_decoder_fifo ) - { - msg_Err( p_input, "no video decoder" ); - input_DeletePES( p_input->p_method_data, p_pes ); - return( -1 ); - } +/***************************************************************************** + * Control: + *****************************************************************************/ +static int Control( demux_t *p_demux, int i_query, va_list args ) +{ + /* demux_sys_t *p_sys = p_demux->p_sys; */ + /* FIXME calculate the bitrate */ + if( i_query == DEMUX_SET_TIME ) + return VLC_EGENERIC; else - { - input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes ); - } - /* FIXME FIXME FIXME FIXME */ - p_demux->i_dts += (mtime_t)90000 / 25; - /* FIXME FIXME FIXME FIXME */ - - return( 1 ); + return demux2_vaControlHelper( p_demux->s, + 0, -1, + 0, 1, i_query, args ); } -