]> git.sesse.net Git - vlc/blob - modules/packetizer/copy.c
* copy: ported to new API.
[vlc] / modules / packetizer / copy.c
1 /*****************************************************************************
2  * copy.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: copy.c,v 1.19 2003/11/20 18:27:44 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
33
34 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open ( vlc_object_t * );
38 static void Close( vlc_object_t * );
39
40 vlc_module_begin();
41     set_description( _("Copy packetizer") );
42     set_capability( "packetizer", 1 );
43     set_callbacks( Open, Close );
44 vlc_module_end();
45
46 /*****************************************************************************
47  * Local prototypes
48  *****************************************************************************/
49 struct decoder_sys_t
50 {
51     int i_spu_size;
52     int i_spu;
53
54     block_t *p_block;
55 };
56
57 static block_t *PacketizeAV ( decoder_t *, block_t ** );
58 static block_t *PacketizeSPU( decoder_t *, block_t ** );
59
60 /*****************************************************************************
61  * Open: probe the packetizer and return score
62  *****************************************************************************
63  * Tries to launch a decoder and return score so that the interface is able
64  * to choose.
65  *****************************************************************************/
66 static int Open( vlc_object_t *p_this )
67 {
68     decoder_t     *p_dec = (decoder_t*)p_this;
69     decoder_sys_t *p_sys;
70
71     if( p_dec->fmt_in.i_cat == AUDIO_ES || p_dec->fmt_in.i_cat == VIDEO_ES )
72     {
73         p_dec->pf_packetize = PacketizeAV;
74     }
75     else if( p_dec->fmt_in.i_cat == SPU_ES )
76     {
77         if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'p', 'u', ' ' ) ||
78             p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) )
79         {
80             p_dec->pf_packetize = PacketizeSPU;
81         }
82         else
83         {
84             p_dec->pf_packetize = PacketizeAV;
85         }
86     }
87     else
88     {
89         msg_Err( p_dec, "invalid ES type" );
90         return VLC_EGENERIC;
91     }
92
93     /* Create the output format */
94     memcpy( &p_dec->fmt_out, &p_dec->fmt_in, sizeof( es_format_t ) );
95     if( p_dec->fmt_in.i_extra > 0 )
96     {
97         p_dec->fmt_out.p_extra = malloc( p_dec->fmt_in.i_extra );
98         memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra,
99                 p_dec->fmt_in.i_extra );
100     }
101
102     /* Fix the value of the fourcc */
103     switch( p_dec->fmt_in.i_codec )
104     {
105         /* video */
106         case VLC_FOURCC( 'm', '4', 's', '2'):
107         case VLC_FOURCC( 'M', '4', 'S', '2'):
108         case VLC_FOURCC( 'm', 'p', '4', 's'):
109         case VLC_FOURCC( 'M', 'P', '4', 'S'):
110         case VLC_FOURCC( 'D', 'I', 'V', 'X'):
111         case VLC_FOURCC( 'd', 'i', 'v', 'x'):
112         case VLC_FOURCC( 'X', 'V', 'I', 'D'):
113         case VLC_FOURCC( 'X', 'v', 'i', 'D'):
114         case VLC_FOURCC( 'x', 'v', 'i', 'd'):
115         case VLC_FOURCC( 'D', 'X', '5', '0'):
116         case VLC_FOURCC( 0x04, 0,   0,   0):
117         case VLC_FOURCC( '3', 'I', 'V', '2'):
118             p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v');
119             break;
120
121         case VLC_FOURCC( 'm', 'p', 'g', '1' ):
122         case VLC_FOURCC( 'm', 'p', 'g', '2' ):
123         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
124         case VLC_FOURCC( 'm', 'p', '2', 'v' ):
125             p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
126             break;
127
128         case VLC_FOURCC( 'd', 'i', 'v', '1' ):
129         case VLC_FOURCC( 'M', 'P', 'G', '4' ):
130         case VLC_FOURCC( 'm', 'p', 'g', '4' ):
131             p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '1' );
132             break;
133
134         case VLC_FOURCC( 'd', 'i', 'v', '2' ):
135         case VLC_FOURCC( 'M', 'P', '4', '2' ):
136         case VLC_FOURCC( 'm', 'p', '4', '2' ):
137             p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '2' );
138             break;
139
140         case VLC_FOURCC( 'd', 'i', 'v', '3' ):
141         case VLC_FOURCC( 'd', 'i', 'v', '4' ):
142         case VLC_FOURCC( 'D', 'I', 'V', '4' ):
143         case VLC_FOURCC( 'd', 'i', 'v', '5' ):
144         case VLC_FOURCC( 'D', 'I', 'V', '5' ):
145         case VLC_FOURCC( 'd', 'i', 'v', '6' ):
146         case VLC_FOURCC( 'D', 'I', 'V', '6' ):
147         case VLC_FOURCC( 'M', 'P', '4', '3' ):
148         case VLC_FOURCC( 'm', 'p', '4', '3' ):
149         case VLC_FOURCC( 'm', 'p', 'g', '3' ):
150         case VLC_FOURCC( 'M', 'P', 'G', '3' ):
151         case VLC_FOURCC( 'A', 'P', '4', '1' ):
152             p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
153             break;
154
155         case VLC_FOURCC( 'h', '2', '6', '3' ):
156         case VLC_FOURCC( 'U', '2', '6', '3' ):
157         case VLC_FOURCC( 'u', '2', '6', '3' ):
158             p_dec->fmt_out.i_codec = VLC_FOURCC( 'H', '2', '6', '3' );
159             break;
160
161         case VLC_FOURCC( 'i', '2', '6', '3' ):
162             p_dec->fmt_out.i_codec = VLC_FOURCC( 'I', '2', '6', '3' );
163             break;
164
165         case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
166         case VLC_FOURCC( 'm', 'j', 'p', 'a' ):
167         case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
168         case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
169         case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
170             p_dec->fmt_out.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' );
171             break;
172
173         case VLC_FOURCC( 'd', 'v', 's', 'd' ):
174         case VLC_FOURCC( 'D', 'V', 'S', 'D' ):
175         case VLC_FOURCC( 'd', 'v', 'h', 'd' ):
176             p_dec->fmt_out.i_codec = VLC_FOURCC( 'd', 'v', 's', 'l' );
177             break;
178
179         /* audio */
180         case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
181             switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
182             {
183                 case 1:
184                     p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
185                     break;
186                 case 2:
187                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
188                     break;
189                 case 3:
190                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
191                     break;
192                 case 4:
193                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
194                     break;
195                 default:
196                     msg_Err( p_dec, "unknown raw audio sample size !!" );
197                     return VLC_EGENERIC;
198             }
199             break;
200
201         case VLC_FOURCC( 't', 'w', 'o', 's' ):
202             switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
203             {
204                 case 1:
205                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
206                     break;
207                 case 2:
208                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
209                     break;
210                 case 3:
211                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
212                     break;
213                 case 4:
214                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b');
215                     break;
216                 default:
217                     msg_Err( p_dec, "unknown raw audio sample size !!" );
218                     return VLC_EGENERIC;
219             }
220             break;
221
222         case VLC_FOURCC( 's', 'o', 'w', 't' ):
223             switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
224             {
225                 case 1:
226                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
227                     break;
228                 case 2:
229                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
230                     break;
231                 case 3:
232                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
233                     break;
234                 case 4:
235                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
236                     break;
237                 default:
238                     msg_Err( p_dec, "unknown raw audio sample size !!" );
239                     return VLC_EGENERIC;
240             }
241             break;
242
243         /* subtitles */
244         case VLC_FOURCC( 's', 'p', 'u', 'b' ):
245             p_dec->fmt_out.i_codec = VLC_FOURCC( 's', 'p', 'u', ' ' );
246             break;
247     }
248
249     p_dec->p_sys = p_sys = malloc( sizeof( block_t ) );
250     p_sys->i_spu_size = 0;
251     p_sys->i_spu      = 0;
252     p_sys->p_block    = NULL;
253
254     return VLC_SUCCESS;
255 }
256
257 /*****************************************************************************
258  * Close:
259  *****************************************************************************/
260 static void Close( vlc_object_t *p_this )
261 {
262     decoder_t     *p_dec = (decoder_t*)p_this;
263
264     if( p_dec->p_sys->p_block )
265     {
266         block_ChainRelease( p_dec->p_sys->p_block );
267     }
268
269     free( p_dec->p_sys );
270 }
271
272 /*****************************************************************************
273  * PacketizeStd: packetize an unit (here copy a complete block )
274  *****************************************************************************/
275 static block_t *PacketizeAV ( decoder_t *p_dec, block_t **pp_block )
276 {
277     block_t *p_block;
278     block_t *p_ret = p_dec->p_sys->p_block;
279
280     if( pp_block == NULL || *pp_block == NULL )
281     {
282         return NULL;
283     }
284     p_block = *pp_block;
285     *pp_block = NULL;
286
287     if( p_block->i_pts <= 0 )
288     {
289         msg_Dbg( p_dec, "need pts > 0" );
290         block_Release( p_block );
291         return NULL;
292     }
293
294     if( p_ret != NULL && p_block->i_pts > p_ret->i_pts )
295     {
296         p_ret->i_length = p_block->i_pts - p_ret->i_pts;
297     }
298     p_dec->p_sys->p_block = p_block;
299
300     return p_ret;
301 }
302
303 /*****************************************************************************
304  * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle)
305  *****************************************************************************/
306 static block_t *PacketizeSPU( decoder_t *p_dec, block_t **pp_block )
307 {
308     decoder_sys_t *p_sys = p_dec->p_sys;
309     block_t *p_block;
310
311     if( pp_block == NULL || *pp_block == NULL )
312     {
313         return NULL;
314     }
315     p_block = *pp_block;
316     *pp_block = NULL;
317
318     if( p_sys->i_spu_size <= 0 &&
319         ( p_block->i_pts <= 0 || p_block->i_buffer < 4 ) )
320     {
321         msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" );
322         block_Release( p_block );
323         return NULL;
324     }
325
326     block_ChainAppend( &p_sys->p_block, p_block );
327     p_sys->i_spu += p_block->i_buffer;
328
329     if( p_sys->i_spu_size <= 0 )
330     {
331         int i_rle = ( ( p_block->p_buffer[2] << 8 )| p_block->p_buffer[3] ) - 4;
332
333         p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )| p_block->p_buffer[1];
334
335         msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d", p_sys->i_spu_size, i_rle );
336
337         if( p_sys->i_spu_size <= 0 || i_rle >= p_sys->i_spu_size )
338         {
339             p_sys->i_spu_size = 0;
340             p_sys->i_spu      = 0;
341             p_sys->p_block    = NULL;
342
343             block_Release( p_block );
344             return NULL;
345         }
346     }
347
348     if( p_sys->i_spu >= p_sys->i_spu_size )
349     {
350         /* We have a complete sub */
351         block_t *p_ret = p_sys->p_block;
352
353         msg_Dbg( p_dec, "SPU packets size=%d should be %d",
354                  p_sys->i_spu, p_sys->i_spu_size );
355
356         p_sys->i_spu_size = 0;
357         p_sys->i_spu      = 0;
358         p_sys->p_block    = NULL;
359         return p_ret;
360     }
361     return NULL;
362 }
363