00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031 #include "vlc_codec.h"
00032
00033
00034
00035
00036 static int Open ( vlc_object_t * );
00037 static void Close( vlc_object_t * );
00038
00039 vlc_module_begin();
00040 set_category( CAT_INPUT );
00041 set_subcategory( SUBCAT_INPUT_DEMUX );
00042 set_description( _("MPEG-4 video demuxer" ) );
00043 set_capability( "demux2", 0 );
00044 set_callbacks( Open, Close );
00045 add_shortcut( "m4v" );
00046 add_shortcut( "mp4v" );
00047 vlc_module_end();
00048
00049
00050
00051
00052 struct demux_sys_t
00053 {
00054 mtime_t i_dts;
00055 es_out_id_t *p_es;
00056
00057 decoder_t *p_packetizer;
00058 };
00059
00060 static int Demux( demux_t * );
00061 static int Control( demux_t *, int, va_list );
00062
00063 #define M4V_PACKET_SIZE 4096
00064
00065
00066
00067
00068 static int Open( vlc_object_t * p_this )
00069 {
00070 demux_t *p_demux = (demux_t*)p_this;
00071 demux_sys_t *p_sys;
00072 vlc_bool_t b_forced = VLC_FALSE;
00073
00074 uint8_t *p_peek;
00075
00076 es_format_t fmt;
00077
00078 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
00079 {
00080 msg_Err( p_demux, "cannot peek" );
00081 return VLC_EGENERIC;
00082 }
00083
00084 if( !strncmp( p_demux->psz_demux, "mp4v", 4 ) ||
00085 !strncmp( p_demux->psz_demux, "m4v", 4 ) )
00086 {
00087 b_forced = VLC_TRUE;
00088 }
00089
00090 if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 || p_peek[3] > 0x2f )
00091 {
00092 if( !b_forced )
00093 {
00094 msg_Warn( p_demux, "m4v module discarded (no startcode)" );
00095 return VLC_EGENERIC;
00096 }
00097
00098 msg_Warn( p_demux, "this doesn't look like an MPEG-4 ES stream, continuing anyway" );
00099 }
00100
00101 p_demux->pf_demux = Demux;
00102 p_demux->pf_control= Control;
00103 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00104 p_sys->p_es = NULL;
00105 p_sys->i_dts = 1;
00106
00107
00108
00109
00110 p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_PACKETIZER );
00111 p_sys->p_packetizer->pf_decode_audio = NULL;
00112 p_sys->p_packetizer->pf_decode_video = NULL;
00113 p_sys->p_packetizer->pf_decode_sub = NULL;
00114 p_sys->p_packetizer->pf_packetize = NULL;
00115 es_format_Init( &p_sys->p_packetizer->fmt_in, VIDEO_ES,
00116 VLC_FOURCC( 'm', 'p', '4', 'v' ) );
00117 es_format_Init( &p_sys->p_packetizer->fmt_out, UNKNOWN_ES, 0 );
00118 p_sys->p_packetizer->p_module =
00119 module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
00120
00121 if( p_sys->p_packetizer->p_module == NULL)
00122 {
00123 vlc_object_destroy( p_sys->p_packetizer );
00124 msg_Err( p_demux, "cannot find mp4v packetizer" );
00125 free( p_sys );
00126 return VLC_EGENERIC;
00127 }
00128
00129
00130
00131
00132 es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', '4', 'v' ) );
00133 p_sys->p_es = es_out_Add( p_demux->out, &fmt );
00134
00135 return VLC_SUCCESS;
00136 }
00137
00138
00139
00140
00141 static void Close( vlc_object_t * p_this )
00142 {
00143 demux_t *p_demux = (demux_t*)p_this;
00144 demux_sys_t *p_sys = p_demux->p_sys;
00145
00146 module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
00147 vlc_object_destroy( p_sys->p_packetizer );
00148
00149 free( p_sys );
00150 }
00151
00152
00153
00154
00155
00156
00157 static int Demux( demux_t *p_demux)
00158 {
00159 demux_sys_t *p_sys = p_demux->p_sys;
00160 block_t *p_block_in, *p_block_out;
00161
00162 if( ( p_block_in = stream_Block( p_demux->s, M4V_PACKET_SIZE ) ) == NULL )
00163 {
00164 return 0;
00165 }
00166
00167
00168 p_block_in->i_dts = p_sys->i_dts;
00169 p_block_in->i_pts = 0;
00170
00171 while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) )
00172 {
00173 while( p_block_out )
00174 {
00175 block_t *p_next = p_block_out->p_next;
00176
00177 if( p_sys->p_es == NULL )
00178 {
00179 p_sys->p_packetizer->fmt_out.b_packetized = VLC_TRUE;
00180 p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
00181 }
00182
00183 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_dts );
00184
00185 p_block_out->p_next = NULL;
00186 if( p_block_out->i_pts == p_block_out->i_dts )
00187 {
00188 p_block_out->i_pts = p_sys->i_dts;
00189 }
00190 else
00191 {
00192 p_block_out->i_pts = 0;
00193 }
00194 p_block_out->i_dts = p_sys->i_dts;
00195
00196 es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
00197
00198 p_block_out = p_next;
00199
00200
00201 p_sys->i_dts += (mtime_t)1000000 / 25;
00202
00203 }
00204 }
00205 return 1;
00206 }
00207
00208
00209
00210
00211 static int Control( demux_t *p_demux, int i_query, va_list args )
00212 {
00213
00214
00215 if( i_query == DEMUX_SET_TIME )
00216 return VLC_EGENERIC;
00217 else
00218 return demux2_vaControlHelper( p_demux->s,
00219 0, -1,
00220 0, 1, i_query, args );
00221 }
00222