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