1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: copy.c,v 1.19 2003/11/20 18:27:44 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
34 /*****************************************************************************
36 *****************************************************************************/
37 static int Open ( vlc_object_t * );
38 static void Close( vlc_object_t * );
41 set_description( _("Copy packetizer") );
42 set_capability( "packetizer", 1 );
43 set_callbacks( Open, Close );
46 /*****************************************************************************
48 *****************************************************************************/
57 static block_t *PacketizeAV ( decoder_t *, block_t ** );
58 static block_t *PacketizeSPU( decoder_t *, block_t ** );
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
65 *****************************************************************************/
66 static int Open( vlc_object_t *p_this )
68 decoder_t *p_dec = (decoder_t*)p_this;
71 if( p_dec->fmt_in.i_cat == AUDIO_ES || p_dec->fmt_in.i_cat == VIDEO_ES )
73 p_dec->pf_packetize = PacketizeAV;
75 else if( p_dec->fmt_in.i_cat == SPU_ES )
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' ) )
80 p_dec->pf_packetize = PacketizeSPU;
84 p_dec->pf_packetize = PacketizeAV;
89 msg_Err( p_dec, "invalid ES type" );
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 )
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 );
102 /* Fix the value of the fourcc */
103 switch( p_dec->fmt_in.i_codec )
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');
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' );
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' );
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' );
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' );
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' );
161 case VLC_FOURCC( 'i', '2', '6', '3' ):
162 p_dec->fmt_out.i_codec = VLC_FOURCC( 'I', '2', '6', '3' );
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' );
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' );
180 case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
181 switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
184 p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
187 p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
190 p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
193 p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
196 msg_Err( p_dec, "unknown raw audio sample size !!" );
201 case VLC_FOURCC( 't', 'w', 'o', 's' ):
202 switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
205 p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
208 p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
211 p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
214 p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b');
217 msg_Err( p_dec, "unknown raw audio sample size !!" );
222 case VLC_FOURCC( 's', 'o', 'w', 't' ):
223 switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
226 p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
229 p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
232 p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
235 p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
238 msg_Err( p_dec, "unknown raw audio sample size !!" );
244 case VLC_FOURCC( 's', 'p', 'u', 'b' ):
245 p_dec->fmt_out.i_codec = VLC_FOURCC( 's', 'p', 'u', ' ' );
249 p_dec->p_sys = p_sys = malloc( sizeof( block_t ) );
250 p_sys->i_spu_size = 0;
252 p_sys->p_block = NULL;
257 /*****************************************************************************
259 *****************************************************************************/
260 static void Close( vlc_object_t *p_this )
262 decoder_t *p_dec = (decoder_t*)p_this;
264 if( p_dec->p_sys->p_block )
266 block_ChainRelease( p_dec->p_sys->p_block );
269 free( p_dec->p_sys );
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 )
278 block_t *p_ret = p_dec->p_sys->p_block;
280 if( pp_block == NULL || *pp_block == NULL )
287 if( p_block->i_pts <= 0 )
289 msg_Dbg( p_dec, "need pts > 0" );
290 block_Release( p_block );
294 if( p_ret != NULL && p_block->i_pts > p_ret->i_pts )
296 p_ret->i_length = p_block->i_pts - p_ret->i_pts;
298 p_dec->p_sys->p_block = p_block;
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 )
308 decoder_sys_t *p_sys = p_dec->p_sys;
311 if( pp_block == NULL || *pp_block == NULL )
318 if( p_sys->i_spu_size <= 0 &&
319 ( p_block->i_pts <= 0 || p_block->i_buffer < 4 ) )
321 msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" );
322 block_Release( p_block );
326 block_ChainAppend( &p_sys->p_block, p_block );
327 p_sys->i_spu += p_block->i_buffer;
329 if( p_sys->i_spu_size <= 0 )
331 int i_rle = ( ( p_block->p_buffer[2] << 8 )| p_block->p_buffer[3] ) - 4;
333 p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )| p_block->p_buffer[1];
335 msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d", p_sys->i_spu_size, i_rle );
337 if( p_sys->i_spu_size <= 0 || i_rle >= p_sys->i_spu_size )
339 p_sys->i_spu_size = 0;
341 p_sys->p_block = NULL;
343 block_Release( p_block );
348 if( p_sys->i_spu >= p_sys->i_spu_size )
350 /* We have a complete sub */
351 block_t *p_ret = p_sys->p_block;
353 msg_Dbg( p_dec, "SPU packets size=%d should be %d",
354 p_sys->i_spu, p_sys->i_spu_size );
356 p_sys->i_spu_size = 0;
358 p_sys->p_block = NULL;