Renamed playlist "playlist-current" to "item-current".
[vlc.git] / modules / packetizer / copy.c
1 /*****************************************************************************
2  * copy.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002, 2006 the VideoLAN team
5  * $Id$
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_block.h>
37
38 /*****************************************************************************
39  * Module descriptor
40  *****************************************************************************/
41 static int  Open ( vlc_object_t * );
42 static void Close( vlc_object_t * );
43
44 vlc_module_begin ()
45     set_category( CAT_SOUT )
46     set_subcategory( SUBCAT_SOUT_PACKETIZER )
47     set_description( N_("Copy packetizer") )
48     set_capability( "packetizer", 1 )
49     set_callbacks( Open, Close )
50 vlc_module_end ()
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 struct decoder_sys_t
56 {
57     block_t *p_block;
58 };
59
60 static block_t *Packetize   ( decoder_t *, block_t ** );
61 static block_t *PacketizeSub( decoder_t *, block_t ** );
62
63 /*****************************************************************************
64  * Open: probe the packetizer and return score
65  *****************************************************************************
66  * Tries to launch a decoder and return score so that the interface is able
67  * to choose.
68  *****************************************************************************/
69 static int Open( vlc_object_t *p_this )
70 {
71     decoder_t     *p_dec = (decoder_t*)p_this;
72     decoder_sys_t *p_sys;
73
74     if( p_dec->fmt_in.i_cat != AUDIO_ES &&
75         p_dec->fmt_in.i_cat != VIDEO_ES &&
76         p_dec->fmt_in.i_cat != SPU_ES )
77     {
78         msg_Err( p_dec, "invalid ES type" );
79         return VLC_EGENERIC;
80     }
81
82     if( p_dec->fmt_in.i_cat == SPU_ES )
83         p_dec->pf_packetize = PacketizeSub;
84     else
85         p_dec->pf_packetize = Packetize;
86
87     /* Create the output format */
88     es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
89
90     /* Fix the value of the fourcc */
91     switch( p_dec->fmt_in.i_codec )
92     {
93         /* video */
94         case VLC_FOURCC( 'm', '4', 's', '2'):
95         case VLC_FOURCC( 'M', '4', 'S', '2'):
96         case VLC_FOURCC( 'm', 'p', '4', 's'):
97         case VLC_FOURCC( 'M', 'P', '4', 'S'):
98         case VLC_FOURCC( 'D', 'I', 'V', 'X'):
99         case VLC_FOURCC( 'd', 'i', 'v', 'x'):
100         case VLC_FOURCC( 'X', 'V', 'I', 'D'):
101         case VLC_FOURCC( 'X', 'v', 'i', 'D'):
102         case VLC_FOURCC( 'x', 'v', 'i', 'd'):
103         case VLC_FOURCC( 'D', 'X', '5', '0'):
104         case VLC_FOURCC( 0x04, 0,   0,   0):
105         case VLC_FOURCC( '3', 'I', 'V', '2'):
106             p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v');
107             break;
108
109         case VLC_FOURCC( 'm', 'p', 'g', '1' ):
110         case VLC_FOURCC( 'm', 'p', 'g', '2' ):
111         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
112         case VLC_FOURCC( 'm', 'p', '2', 'v' ):
113             p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
114             break;
115
116         case VLC_FOURCC( 'd', 'i', 'v', '1' ):
117         case VLC_FOURCC( 'M', 'P', 'G', '4' ):
118         case VLC_FOURCC( 'm', 'p', 'g', '4' ):
119             p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '1' );
120             break;
121
122         case VLC_FOURCC( 'd', 'i', 'v', '2' ):
123         case VLC_FOURCC( 'M', 'P', '4', '2' ):
124         case VLC_FOURCC( 'm', 'p', '4', '2' ):
125             p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '2' );
126             break;
127
128         case VLC_FOURCC( 'd', 'i', 'v', '3' ):
129         case VLC_FOURCC( 'd', 'i', 'v', '4' ):
130         case VLC_FOURCC( 'D', 'I', 'V', '4' ):
131         case VLC_FOURCC( 'd', 'i', 'v', '5' ):
132         case VLC_FOURCC( 'D', 'I', 'V', '5' ):
133         case VLC_FOURCC( 'd', 'i', 'v', '6' ):
134         case VLC_FOURCC( 'D', 'I', 'V', '6' ):
135         case VLC_FOURCC( 'M', 'P', '4', '3' ):
136         case VLC_FOURCC( 'm', 'p', '4', '3' ):
137         case VLC_FOURCC( 'm', 'p', 'g', '3' ):
138         case VLC_FOURCC( 'M', 'P', 'G', '3' ):
139         case VLC_FOURCC( 'A', 'P', '4', '1' ):
140             p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
141             break;
142
143         case VLC_FOURCC( 'h', '2', '6', '3' ):
144         case VLC_FOURCC( 'U', '2', '6', '3' ):
145         case VLC_FOURCC( 'u', '2', '6', '3' ):
146             p_dec->fmt_out.i_codec = VLC_FOURCC( 'H', '2', '6', '3' );
147             break;
148
149         case VLC_FOURCC( 'i', '2', '6', '3' ):
150             p_dec->fmt_out.i_codec = VLC_FOURCC( 'I', '2', '6', '3' );
151             break;
152
153         case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
154         case VLC_FOURCC( 'm', 'j', 'p', 'a' ):
155         case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
156         case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
157         case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
158             p_dec->fmt_out.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' );
159             break;
160
161         case VLC_FOURCC( 'd', 'v', 's', 'd' ):
162         case VLC_FOURCC( 'D', 'V', 'S', 'D' ):
163         case VLC_FOURCC( 'd', 'v', 'h', 'd' ):
164             p_dec->fmt_out.i_codec = VLC_FOURCC( 'd', 'v', 's', 'l' );
165             break;
166
167         /* audio */
168         case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
169             switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
170             {
171                 case 1:
172                     p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
173                     break;
174                 case 2:
175                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
176                     break;
177                 case 3:
178                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
179                     break;
180                 case 4:
181                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
182                     break;
183                 default:
184                     msg_Err( p_dec, "unknown raw audio sample size" );
185                     return VLC_EGENERIC;
186             }
187             break;
188
189         case VLC_FOURCC( 't', 'w', 'o', 's' ):
190             switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
191             {
192                 case 1:
193                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
194                     break;
195                 case 2:
196                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
197                     break;
198                 case 3:
199                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
200                     break;
201                 case 4:
202                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b');
203                     break;
204                 default:
205                     msg_Err( p_dec, "unknown raw audio sample size" );
206                     return VLC_EGENERIC;
207             }
208             break;
209
210         case VLC_FOURCC( 's', 'o', 'w', 't' ):
211             switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
212             {
213                 case 1:
214                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
215                     break;
216                 case 2:
217                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
218                     break;
219                 case 3:
220                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
221                     break;
222                 case 4:
223                     p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
224                     break;
225                 default:
226                     msg_Err( p_dec, "unknown raw audio sample size" );
227                     return VLC_EGENERIC;
228             }
229             break;
230     }
231
232     p_dec->p_sys = p_sys = malloc( sizeof( block_t ) );
233     p_sys->p_block    = NULL;
234
235     return VLC_SUCCESS;
236 }
237
238 /*****************************************************************************
239  * Close:
240  *****************************************************************************/
241 static void Close( vlc_object_t *p_this )
242 {
243     decoder_t     *p_dec = (decoder_t*)p_this;
244
245     if( p_dec->p_sys->p_block )
246     {
247         block_ChainRelease( p_dec->p_sys->p_block );
248     }
249
250     es_format_Clean( &p_dec->fmt_out );
251     free( p_dec->p_sys );
252 }
253
254 /*****************************************************************************
255  * Packetize: packetize an unit (here copy a complete block )
256  *****************************************************************************/
257 static block_t *Packetize ( decoder_t *p_dec, block_t **pp_block )
258 {
259     block_t *p_block;
260     block_t *p_ret = p_dec->p_sys->p_block;
261
262     if( pp_block == NULL || *pp_block == NULL )
263         return NULL;
264     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
265     {
266         block_Release( *pp_block );
267         return NULL;
268     }
269
270     p_block = *pp_block;
271     *pp_block = NULL;
272
273     if( p_block->i_dts <= 0 )
274     {
275         p_block->i_dts = p_block->i_pts;
276     }
277
278     if( p_block->i_dts <= 0 )
279     {
280         msg_Dbg( p_dec, "need dts > 0" );
281         block_Release( p_block );
282         return NULL;
283     }
284
285     if( p_ret != NULL && p_block->i_pts > p_ret->i_pts )
286     {
287         p_ret->i_length = p_block->i_pts - p_ret->i_pts;
288     }
289     p_dec->p_sys->p_block = p_block;
290
291     return p_ret;
292 }
293
294 /*****************************************************************************
295  * PacketizeSub: packetize an unit (here copy a complete block )
296  *****************************************************************************/
297 static block_t *PacketizeSub( decoder_t *p_dec, block_t **pp_block )
298 {
299     block_t *p_block;
300
301     if( pp_block == NULL || *pp_block == NULL )
302         return NULL;
303     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
304     {
305         block_Release( *pp_block );
306         return NULL;
307     }
308
309     p_block = *pp_block;
310     *pp_block = NULL;
311
312     if( p_block->i_dts <= 0 )
313     {
314         p_block->i_dts = p_block->i_pts;
315     }
316
317     if( p_block->i_dts <= 0 )
318     {
319         msg_Dbg( p_dec, "need dts > 0" );
320         block_Release( p_block );
321         return NULL;
322     }
323
324     return p_block;
325 }