1 /*****************************************************************************
2 * mpeg4video.c: mpeg 4 video packetizer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: mpeg4video.c,v 1.15 2003/11/17 18:48:08 gbazin Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
9 * Gildas Bazin <gbazin@netcourrier.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
30 #include <vlc/decoder.h>
31 #include <vlc/input.h>
34 #include <stdlib.h> /* malloc(), free() */
35 #include <string.h> /* strdup() */
39 /*****************************************************************************
40 * decoder_sys_t : decoder descriptor
41 *****************************************************************************/
50 /****************************************************************************
52 ****************************************************************************/
53 static int OpenPacketizer ( vlc_object_t * );
54 static void ClosePacketizer( vlc_object_t * );
56 static block_t *PacketizeBlock( decoder_t *, block_t ** );
58 static int m4v_FindVol( decoder_t *p_dec, block_t *p_block );
60 #define VIDEO_OBJECT_MASK 0x01f
61 #define VIDEO_OBJECT_LAYER_MASK 0x00f
63 #define VIDEO_OBJECT_START_CODE 0x100
64 #define VIDEO_OBJECT_LAYER_START_CODE 0x120
65 #define VISUAL_OBJECT_SEQUENCE_START_CODE 0x1b0
66 #define VISUAL_OBJECT_SEQUENCE_END_CODE 0x1b1
67 #define USER_DATA_START_CODE 0x1b2
68 #define GROUP_OF_VOP_START_CODE 0x1b3
69 #define VIDEO_SESSION_ERROR_CODE 0x1b4
70 #define VISUAL_OBJECT_START_CODE 0x1b5
71 #define VOP_START_CODE 0x1b6
72 #define FACE_OBJECT_START_CODE 0x1ba
73 #define FACE_OBJECT_PLANE_START_CODE 0x1bb
74 #define MESH_OBJECT_START_CODE 0x1bc
75 #define MESH_OBJECT_PLANE_START_CODE 0x1bd
76 #define STILL_TEXTURE_OBJECT_START_CODE 0x1be
77 #define TEXTURE_SPATIAL_LAYER_START_CODE 0x1bf
78 #define TEXTURE_SNR_LAYER_START_CODE 0x1c0
80 /*****************************************************************************
82 *****************************************************************************/
84 set_description( _("MPEG4 Video packetizer") );
85 set_capability( "packetizer", 50 );
86 set_callbacks( OpenPacketizer, ClosePacketizer );
89 /*****************************************************************************
90 * OpenPacketizer: probe the packetizer and return score
91 *****************************************************************************/
92 static int OpenPacketizer( vlc_object_t *p_this )
94 decoder_t *p_dec = (decoder_t*)p_this;
97 switch( p_dec->p_fifo->i_fourcc )
99 case VLC_FOURCC( 'm', '4', 's', '2'):
100 case VLC_FOURCC( 'M', '4', 'S', '2'):
101 case VLC_FOURCC( 'm', 'p', '4', 's'):
102 case VLC_FOURCC( 'M', 'P', '4', 'S'):
103 case VLC_FOURCC( 'm', 'p', '4', 'v'):
104 case VLC_FOURCC( 'D', 'I', 'V', 'X'):
105 case VLC_FOURCC( 'd', 'i', 'v', 'x'):
106 case VLC_FOURCC( 'X', 'V', 'I', 'D'):
107 case VLC_FOURCC( 'X', 'v', 'i', 'D'):
108 case VLC_FOURCC( 'x', 'v', 'i', 'd'):
109 case VLC_FOURCC( 'D', 'X', '5', '0'):
110 case VLC_FOURCC( 0x04, 0, 0, 0):
111 case VLC_FOURCC( '3', 'I', 'V', '2'):
118 /* Allocate the memory needed to store the decoder's structure */
119 if( ( p_dec->p_sys = p_sys =
120 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
122 msg_Err( p_dec, "out of memory" );
126 /* Setup properties */
127 p_dec->fmt_out = p_dec->fmt_in;
128 p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
130 if( p_dec->fmt_in.i_extra )
133 p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
134 p_dec->fmt_out.p_extra = malloc( p_dec->fmt_in.i_extra );
135 memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra,
136 p_dec->fmt_in.i_extra );
138 msg_Dbg( p_dec, "opening with vol size:%d", p_dec->fmt_in.i_extra );
142 /* No vol, we'll have to look for one later on */
143 p_dec->fmt_out.i_extra = 0;
144 p_dec->fmt_out.p_extra = 0;
148 p_dec->pf_packetize = PacketizeBlock;
153 /****************************************************************************
154 * PacketizeBlock: the whole thing
155 ****************************************************************************/
156 static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
160 if( !pp_block || !*pp_block ) return NULL;
164 if( !p_dec->fmt_out.i_extra )
166 m4v_FindVol( p_dec, p_block );
169 /* Drop blocks until we have a VOL */
170 if( !p_dec->fmt_out.i_extra )
172 block_Release( p_block );
176 /* TODO: Date management */
177 p_block->i_length = 1000000 / 25;
183 /****************************************************************************
185 ****************************************************************************/
186 static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end )
188 for( ; *pp_data < p_end - 4; (*pp_data)++ )
190 if( (*pp_data)[0] == 0 && (*pp_data)[1] == 0 && (*pp_data)[2] == 1 )
198 static int m4v_FindVol( decoder_t *p_dec, block_t *p_block )
200 uint8_t *p_vol_begin, *p_vol_end, *p_end;
202 /* search if p_block contains with a vol */
203 p_vol_begin = p_block->p_buffer;
205 p_end = p_block->p_buffer + p_block->i_buffer;
209 if( m4v_FindStartCode( &p_vol_begin, p_end ) )
214 msg_Dbg( p_dec, "starcode 0x%2.2x%2.2x%2.2x%2.2x",
215 p_vol_begin[0], p_vol_begin[1],
216 p_vol_begin[2], p_vol_begin[3] );
218 if( ( p_vol_begin[3] & ~VIDEO_OBJECT_MASK ) ==
219 ( VIDEO_OBJECT_START_CODE&0xff ) )
221 p_vol_end = p_vol_begin + 4;
222 if( m4v_FindStartCode( &p_vol_end, p_end ) )
227 if( ( p_vol_end[3] & ~VIDEO_OBJECT_LAYER_MASK ) ==
228 ( VIDEO_OBJECT_LAYER_START_CODE&0xff ) )
231 if( m4v_FindStartCode( &p_vol_end, p_end ) )
242 else if( ( p_vol_begin[3] & ~VIDEO_OBJECT_LAYER_MASK ) ==
243 ( VIDEO_OBJECT_LAYER_START_CODE&0xff) )
245 p_vol_end = p_vol_begin + 4;
246 if( m4v_FindStartCode( &p_vol_end, p_end ) )
252 if( p_vol_end != NULL && p_vol_begin < p_vol_end )
254 p_dec->fmt_out.i_extra = p_vol_end - p_vol_begin;
255 msg_Dbg( p_dec, "Found VOL" );
257 p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra );
258 memcpy( p_dec->fmt_out.p_extra, p_vol_begin,
259 p_dec->fmt_out.i_extra );
271 /*****************************************************************************
272 * ClosePacketizer: clean up the packetizer
273 *****************************************************************************/
274 static void ClosePacketizer( vlc_object_t *p_this )
276 decoder_t *p_dec = (decoder_t*)p_this;
278 free( p_dec->p_sys );