28b9d8620cb919d3d0ae012100eab4de681f6b4b
[vlc.git] / modules / packetizer / mpeg4video.c
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 $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <vlc/vlc.h>
30 #include <vlc/decoder.h>
31 #include <vlc/input.h>
32 #include <vlc/sout.h>
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                              /* strdup() */
36
37 #include "codecs.h"
38
39 /*****************************************************************************
40  * decoder_sys_t : decoder descriptor
41  *****************************************************************************/
42 struct decoder_sys_t
43 {
44     /*
45      * Common properties
46      */
47     mtime_t i_pts;
48 };
49
50 /****************************************************************************
51  * Local prototypes
52  ****************************************************************************/
53 static int  OpenPacketizer ( vlc_object_t * );
54 static void ClosePacketizer( vlc_object_t * );
55
56 static block_t *PacketizeBlock( decoder_t *, block_t ** );
57
58 static int m4v_FindVol( decoder_t *p_dec, block_t *p_block );
59
60 #define VIDEO_OBJECT_MASK                       0x01f
61 #define VIDEO_OBJECT_LAYER_MASK                 0x00f
62
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
79
80 /*****************************************************************************
81  * Module descriptor
82  *****************************************************************************/
83 vlc_module_begin();
84     set_description( _("MPEG4 Video packetizer") );
85     set_capability( "packetizer", 50 );
86     set_callbacks( OpenPacketizer, ClosePacketizer );
87 vlc_module_end();
88
89 /*****************************************************************************
90  * OpenPacketizer: probe the packetizer and return score
91  *****************************************************************************/
92 static int OpenPacketizer( vlc_object_t *p_this )
93 {
94     decoder_t *p_dec = (decoder_t*)p_this;
95     decoder_sys_t *p_sys;
96
97     switch( p_dec->p_fifo->i_fourcc )
98     {
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'):
112             break;
113
114         default:
115             return VLC_EGENERIC;
116     }
117
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 )
121     {
122         msg_Err( p_dec, "out of memory" );
123         return VLC_EGENERIC;
124     }
125
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' );
129
130     if( p_dec->fmt_in.i_extra )
131     {
132         /* We have a vol */
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 );
137
138         msg_Dbg( p_dec, "opening with vol size:%d", p_dec->fmt_in.i_extra );
139     }
140     else
141     {
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;
145     }
146
147     /* Set callback */
148     p_dec->pf_packetize = PacketizeBlock;
149
150     return VLC_SUCCESS;
151 }
152
153 /****************************************************************************
154  * PacketizeBlock: the whole thing
155  ****************************************************************************/
156 static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
157 {
158     block_t *p_block;
159
160     if( !pp_block || !*pp_block ) return NULL;
161
162     p_block = *pp_block;
163
164     if( !p_dec->fmt_out.i_extra )
165     {
166         m4v_FindVol( p_dec, p_block );
167     }
168
169     /* Drop blocks until we have a VOL */
170     if( !p_dec->fmt_out.i_extra )
171     {
172         block_Release( p_block );
173         return NULL;
174     }
175
176     /* TODO: Date management */
177     p_block->i_length = 1000000 / 25;
178
179     *pp_block = NULL;
180     return p_block;
181 }
182
183 /****************************************************************************
184  * m4v_FindStartCode
185  ****************************************************************************/
186 static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end )
187 {
188     for( ; *pp_data < p_end - 4; (*pp_data)++ )
189     {
190         if( (*pp_data)[0] == 0 && (*pp_data)[1] == 0 && (*pp_data)[2] == 1 )
191         {
192             return 0;
193         }
194     }
195     return -1;
196 }
197
198 static int m4v_FindVol( decoder_t *p_dec, block_t *p_block )
199 {
200     uint8_t *p_vol_begin, *p_vol_end, *p_end;
201
202     /* search if p_block contains with a vol */
203     p_vol_begin = p_block->p_buffer;
204     p_vol_end   = NULL;
205     p_end       = p_block->p_buffer + p_block->i_buffer;
206
207     for( ;; )
208     {
209         if( m4v_FindStartCode( &p_vol_begin, p_end ) )
210         {
211             break;
212         }
213
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] );
217
218         if( ( p_vol_begin[3] & ~VIDEO_OBJECT_MASK ) ==
219             ( VIDEO_OBJECT_START_CODE&0xff ) )
220         {
221             p_vol_end = p_vol_begin + 4;
222             if( m4v_FindStartCode( &p_vol_end, p_end ) )
223             {
224                 p_vol_begin++;
225                 continue;
226             }
227             if( ( p_vol_end[3] & ~VIDEO_OBJECT_LAYER_MASK ) ==
228                 ( VIDEO_OBJECT_LAYER_START_CODE&0xff ) )
229             {
230                 p_vol_end += 4;
231                 if( m4v_FindStartCode( &p_vol_end, p_end ) )
232                 {
233                     p_vol_end = p_end;
234                 }
235             }
236             else
237             {
238                 p_vol_begin++;
239                 continue;
240             }
241         }
242         else if( ( p_vol_begin[3] & ~VIDEO_OBJECT_LAYER_MASK ) ==
243                  ( VIDEO_OBJECT_LAYER_START_CODE&0xff) )
244         {
245             p_vol_end = p_vol_begin + 4;
246             if( m4v_FindStartCode( &p_vol_end, p_end ) )
247             {
248                 p_vol_end = p_end;
249             }
250         }
251
252         if( p_vol_end != NULL && p_vol_begin < p_vol_end )
253         {
254             p_dec->fmt_out.i_extra = p_vol_end - p_vol_begin;
255             msg_Dbg( p_dec, "Found VOL" );
256
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 );
260             return VLC_SUCCESS;
261         }
262         else
263         {
264             p_vol_begin++;
265         }
266     }
267
268     return VLC_SUCCESS;
269 }
270
271 /*****************************************************************************
272  * ClosePacketizer: clean up the packetizer
273  *****************************************************************************/
274 static void ClosePacketizer( vlc_object_t *p_this )
275 {
276     decoder_t *p_dec = (decoder_t*)p_this;
277
278     free( p_dec->p_sys );
279 }