1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: copy.c,v 1.3 2003/01/19 08:27:28 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 *****************************************************************************/
30 #include <vlc/decoder.h>
31 #include <vlc/input.h>
34 #include <stdlib.h> /* malloc(), free() */
35 #include <string.h> /* strdup() */
38 /*****************************************************************************
40 *****************************************************************************/
41 typedef struct packetizer_thread_s
43 /* Input properties */
44 decoder_fifo_t *p_fifo;
46 /* Output properties */
47 sout_input_t *p_sout_input;
48 sout_packet_format_t output_format;
52 } packetizer_thread_t;
54 static int Open ( vlc_object_t * );
55 static int Run ( decoder_fifo_t * );
57 static int InitThread ( packetizer_thread_t * );
58 static void PacketizeThread ( packetizer_thread_t * );
59 static void EndThread ( packetizer_thread_t * );
62 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes );
64 /*****************************************************************************
66 *****************************************************************************/
69 set_description( _("Copy packetizer") );
70 set_capability( "packetizer", 1 );
71 set_callbacks( Open, NULL );
75 /*****************************************************************************
76 * OpenDecoder: probe the packetizer and return score
77 *****************************************************************************
78 * Tries to launch a decoder and return score so that the interface is able
80 *****************************************************************************/
81 static int Open( vlc_object_t *p_this )
83 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
90 /*****************************************************************************
91 * RunDecoder: this function is called just after the thread is created
92 *****************************************************************************/
93 static int Run( decoder_fifo_t *p_fifo )
95 packetizer_thread_t *p_pack;
98 msg_Info( p_fifo, "Running copy packetizer" );
99 if( !( p_pack = malloc( sizeof( packetizer_thread_t ) ) ) )
101 msg_Err( p_fifo, "out of memory" );
102 DecoderError( p_fifo );
105 memset( p_pack, 0, sizeof( packetizer_thread_t ) );
107 p_pack->p_fifo = p_fifo;
109 if( InitThread( p_pack ) != 0 )
111 DecoderError( p_fifo );
115 while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
117 PacketizeThread( p_pack );
121 if( ( b_error = p_pack->p_fifo->b_error ) )
123 DecoderError( p_pack->p_fifo );
136 #define FREE( p ) if( p ) free( p ); p = NULL
138 /*****************************************************************************
139 * InitThread: initialize data before entering main loop
140 *****************************************************************************/
142 static int InitThread( packetizer_thread_t *p_pack )
145 switch( p_pack->p_fifo->i_fourcc )
147 case VLC_FOURCC( 'm', '4', 's', '2'):
148 case VLC_FOURCC( 'M', '4', 'S', '2'):
149 case VLC_FOURCC( 'm', 'p', '4', 's'):
150 case VLC_FOURCC( 'M', 'P', '4', 'S'):
151 case VLC_FOURCC( 'm', 'p', '4', 'v'):
152 case VLC_FOURCC( 'D', 'I', 'V', 'X'):
153 case VLC_FOURCC( 'd', 'i', 'v', 'x'):
154 case VLC_FOURCC( 'X', 'V', 'I', 'D'):
155 case VLC_FOURCC( 'X', 'v', 'i', 'D'):
156 case VLC_FOURCC( 'x', 'v', 'i', 'd'):
157 case VLC_FOURCC( 'D', 'X', '5', '0'):
158 case VLC_FOURCC( 0x04, 0, 0, 0):
159 case VLC_FOURCC( '3', 'I', 'V', '2'):
160 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v');
161 p_pack->output_format.i_cat = VIDEO_ES;
163 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
164 case VLC_FOURCC( 'm', 'p', 'g', '1' ):
165 case VLC_FOURCC( 'm', 'p', 'g', '2' ):
166 case VLC_FOURCC( 'm', 'p', '1', 'v' ):
167 case VLC_FOURCC( 'm', 'p', '2', 'v' ):
168 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v' );
169 p_pack->output_format.i_cat = VIDEO_ES;
171 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
172 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
173 p_pack->output_format.i_cat = AUDIO_ES;
176 case VLC_FOURCC( 'd', 'i', 'v', '1' ):
177 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
178 case VLC_FOURCC( 'M', 'P', 'G', '4' ):
179 case VLC_FOURCC( 'm', 'p', 'g', '4' ):
180 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '1' );
181 p_pack->output_format.i_cat = VIDEO_ES;
183 case VLC_FOURCC( 'd', 'i', 'v', '2' ):
184 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
185 case VLC_FOURCC( 'M', 'P', '4', '2' ):
186 case VLC_FOURCC( 'm', 'p', '4', '2' ):
187 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '2' );
188 p_pack->output_format.i_cat = VIDEO_ES;
190 case VLC_FOURCC( 'd', 'i', 'v', '3' ):
191 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
192 case VLC_FOURCC( 'd', 'i', 'v', '4' ):
193 case VLC_FOURCC( 'D', 'I', 'V', '4' ):
194 case VLC_FOURCC( 'd', 'i', 'v', '5' ):
195 case VLC_FOURCC( 'D', 'I', 'V', '5' ):
196 case VLC_FOURCC( 'd', 'i', 'v', '6' ):
197 case VLC_FOURCC( 'D', 'I', 'V', '6' ):
198 case VLC_FOURCC( 'M', 'P', '4', '3' ):
199 case VLC_FOURCC( 'm', 'p', '4', '3' ):
200 case VLC_FOURCC( 'm', 'p', 'g', '3' ):
201 case VLC_FOURCC( 'M', 'P', 'G', '3' ):
202 case VLC_FOURCC( 'A', 'P', '4', '1' ):
203 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '3' );
204 p_pack->output_format.i_cat = VIDEO_ES;
206 case VLC_FOURCC( 'H', '2', '6', '3' ):
207 case VLC_FOURCC( 'h', '2', '6', '3' ):
208 case VLC_FOURCC( 'U', '2', '6', '3' ):
209 case VLC_FOURCC( 'u', '2', '6', '3' ):
210 p_pack->output_format.i_fourcc = VLC_FOURCC( 'H', '2', '6', '3' );
211 p_pack->output_format.i_cat = VIDEO_ES;
213 case VLC_FOURCC( 'I', '2', '6', '3' ):
214 case VLC_FOURCC( 'i', '2', '6', '3' ):
215 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '2', '6', '3' );
216 p_pack->output_format.i_cat = VIDEO_ES;
218 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
219 p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '1' );
220 p_pack->output_format.i_cat = VIDEO_ES;
222 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
223 p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '2' );
224 p_pack->output_format.i_cat = VIDEO_ES;
226 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
227 case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
228 case VLC_FOURCC( 'm', 'j', 'p', 'a' ):
229 case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
230 case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
231 case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
232 p_pack->output_format.i_fourcc = VLC_FOURCC( 'M', 'J', 'P', 'G' );
233 p_pack->output_format.i_cat = VIDEO_ES;
235 case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
236 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'j', 'p', 'b' );
237 p_pack->output_format.i_cat = VIDEO_ES;
239 case VLC_FOURCC( 'd', 'v', 's', 'l' ):
240 case VLC_FOURCC( 'd', 'v', 's', 'd' ):
241 case VLC_FOURCC( 'D', 'V', 'S', 'D' ):
242 case VLC_FOURCC( 'd', 'v', 'h', 'd' ):
243 p_pack->output_format.i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' );
244 p_pack->output_format.i_cat = VIDEO_ES;
248 p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
249 p_pack->output_format.i_cat = UNKNOWN_ES;
253 switch( p_pack->output_format.i_cat )
257 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
260 p_pack->output_format.p_format = malloc( sizeof( WAVEFORMATEX ) + p_wf->cbSize );
261 memcpy( p_pack->output_format.p_format, p_wf, sizeof( WAVEFORMATEX ) + p_wf->cbSize );
265 p_pack->output_format.p_format = NULL;
272 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
275 p_pack->output_format.p_format = malloc( p_bih->biSize );
276 memcpy( p_pack->output_format.p_format, p_bih, p_bih->biSize );
277 if( p_pack->output_format.i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'v' ) )
279 p_bih->biCompression = VLC_FOURCC( 'd', 'i', 'v', 'x' );
283 p_bih->biCompression = p_pack->output_format.i_fourcc;
289 p_pack->output_format.p_format = NULL;
294 p_pack->output_format.p_format = NULL;
298 p_pack->p_sout_input =
299 sout_InputNew( p_pack->p_fifo,
300 &p_pack->output_format );
302 if( !p_pack->p_sout_input )
304 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
307 p_pack->i_pts_start = -1;
311 /*****************************************************************************
312 * PacketizeThread: packetize an unit (here copy a complete pes)
313 *****************************************************************************/
314 static void PacketizeThread( packetizer_thread_t *p_pack )
316 sout_buffer_t *p_sout_buffer;
320 /* **** get samples count **** */
321 input_ExtractPES( p_pack->p_fifo, &p_pes );
324 p_pack->p_fifo->b_error = 1;
327 if( p_pack->i_pts_start < 0 && p_pes->i_pts > 0 )
329 p_pack->i_pts_start = p_pes->i_pts;
331 i_size = p_pes->i_pes_size;
332 // msg_Dbg( p_pack->p_fifo, "pes size:%d", i_size );
335 pes_packet_t *p_pes_next;
336 data_packet_t *p_data;
340 sout_BufferNew( p_pack->p_sout_input->p_sout, i_size );
343 p_pack->p_fifo->b_error = 1;
346 /* TODO: memcpy of the pes packet */
347 for( i_buffer = 0, p_data = p_pes->p_first;
348 p_data != NULL && i_buffer < i_size;
349 p_data = p_data->p_next)
353 i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
357 p_pack->p_fifo->p_vlc->pf_memcpy( p_sout_buffer->p_buffer + i_buffer,
358 p_data->p_payload_start,
363 p_sout_buffer->i_length = 0;
364 p_sout_buffer->i_dts = p_pes->i_pts - p_pack->i_pts_start;
365 p_sout_buffer->i_pts = p_pes->i_pts - p_pack->i_pts_start;
366 p_sout_buffer->i_bitrate = 0;
368 input_ShowPES( p_pack->p_fifo, &p_pes_next );
371 p_sout_buffer->i_length = p_pes_next->i_pts - p_pes->i_pts;
373 sout_InputSendBuffer( p_pack->p_sout_input,
377 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
381 /*****************************************************************************
382 * EndThread : packetizer thread destruction
383 *****************************************************************************/
384 static void EndThread ( packetizer_thread_t *p_pack)
386 if( p_pack->p_sout_input )
388 sout_InputDelete( p_pack->p_sout_input );
392 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
396 vlc_mutex_lock( &p_fifo->data_lock );
398 if( p_fifo->p_first == NULL )
402 vlc_mutex_unlock( &p_fifo->data_lock );
403 if( pp_pes ) *pp_pes = NULL;
407 /* Signal the input thread we're waiting. This is only
408 * needed in case of slave clock (ES plug-in) but it won't
410 vlc_cond_signal( &p_fifo->data_wait );
412 /* Wait for the input to tell us when we received a packet. */
413 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
415 p_pes = p_fifo->p_first;
416 vlc_mutex_unlock( &p_fifo->data_lock );