1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: copy.c,v 1.9 2003/05/03 01:12:13 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_packetizer_input_t *p_sout_input;
48 sout_format_t output_format;
50 // mtime_t i_last_pts;
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 )
148 case VLC_FOURCC( 'm', '4', 's', '2'):
149 case VLC_FOURCC( 'M', '4', 'S', '2'):
150 case VLC_FOURCC( 'm', 'p', '4', 's'):
151 case VLC_FOURCC( 'M', 'P', '4', 'S'):
152 case VLC_FOURCC( 'm', 'p', '4', 'v'):
153 case VLC_FOURCC( 'D', 'I', 'V', 'X'):
154 case VLC_FOURCC( 'd', 'i', 'v', 'x'):
155 case VLC_FOURCC( 'X', 'V', 'I', 'D'):
156 case VLC_FOURCC( 'X', 'v', 'i', 'D'):
157 case VLC_FOURCC( 'x', 'v', 'i', 'd'):
158 case VLC_FOURCC( 'D', 'X', '5', '0'):
159 case VLC_FOURCC( 0x04, 0, 0, 0):
160 case VLC_FOURCC( '3', 'I', 'V', '2'):
161 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v');
162 p_pack->output_format.i_cat = VIDEO_ES;
164 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
165 case VLC_FOURCC( 'm', 'p', 'g', '1' ):
166 case VLC_FOURCC( 'm', 'p', 'g', '2' ):
167 case VLC_FOURCC( 'm', 'p', '1', 'v' ):
168 case VLC_FOURCC( 'm', 'p', '2', 'v' ):
169 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v' );
170 p_pack->output_format.i_cat = VIDEO_ES;
173 case VLC_FOURCC( 'd', 'i', 'v', '1' ):
174 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
175 case VLC_FOURCC( 'M', 'P', 'G', '4' ):
176 case VLC_FOURCC( 'm', 'p', 'g', '4' ):
177 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '1' );
178 p_pack->output_format.i_cat = VIDEO_ES;
180 case VLC_FOURCC( 'd', 'i', 'v', '2' ):
181 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
182 case VLC_FOURCC( 'M', 'P', '4', '2' ):
183 case VLC_FOURCC( 'm', 'p', '4', '2' ):
184 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '2' );
185 p_pack->output_format.i_cat = VIDEO_ES;
187 case VLC_FOURCC( 'd', 'i', 'v', '3' ):
188 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
189 case VLC_FOURCC( 'd', 'i', 'v', '4' ):
190 case VLC_FOURCC( 'D', 'I', 'V', '4' ):
191 case VLC_FOURCC( 'd', 'i', 'v', '5' ):
192 case VLC_FOURCC( 'D', 'I', 'V', '5' ):
193 case VLC_FOURCC( 'd', 'i', 'v', '6' ):
194 case VLC_FOURCC( 'D', 'I', 'V', '6' ):
195 case VLC_FOURCC( 'M', 'P', '4', '3' ):
196 case VLC_FOURCC( 'm', 'p', '4', '3' ):
197 case VLC_FOURCC( 'm', 'p', 'g', '3' ):
198 case VLC_FOURCC( 'M', 'P', 'G', '3' ):
199 case VLC_FOURCC( 'A', 'P', '4', '1' ):
200 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '3' );
201 p_pack->output_format.i_cat = VIDEO_ES;
203 case VLC_FOURCC( 'H', '2', '6', '3' ):
204 case VLC_FOURCC( 'h', '2', '6', '3' ):
205 case VLC_FOURCC( 'U', '2', '6', '3' ):
206 case VLC_FOURCC( 'u', '2', '6', '3' ):
207 p_pack->output_format.i_fourcc = VLC_FOURCC( 'H', '2', '6', '3' );
208 p_pack->output_format.i_cat = VIDEO_ES;
210 case VLC_FOURCC( 'I', '2', '6', '3' ):
211 case VLC_FOURCC( 'i', '2', '6', '3' ):
212 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '2', '6', '3' );
213 p_pack->output_format.i_cat = VIDEO_ES;
215 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
216 p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '1' );
217 p_pack->output_format.i_cat = VIDEO_ES;
219 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
220 p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '2' );
221 p_pack->output_format.i_cat = VIDEO_ES;
223 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
224 case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
225 case VLC_FOURCC( 'm', 'j', 'p', 'a' ):
226 case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
227 case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
228 case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
229 p_pack->output_format.i_fourcc = VLC_FOURCC( 'M', 'J', 'P', 'G' );
230 p_pack->output_format.i_cat = VIDEO_ES;
232 case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
233 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'j', 'p', 'b' );
234 p_pack->output_format.i_cat = VIDEO_ES;
236 case VLC_FOURCC( 'd', 'v', 's', 'l' ):
237 case VLC_FOURCC( 'd', 'v', 's', 'd' ):
238 case VLC_FOURCC( 'D', 'V', 'S', 'D' ):
239 case VLC_FOURCC( 'd', 'v', 'h', 'd' ):
240 p_pack->output_format.i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' );
241 p_pack->output_format.i_cat = VIDEO_ES;
243 case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
244 p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '1' );
245 p_pack->output_format.i_cat = VIDEO_ES;
248 case VLC_FOURCC( 'I', '4', '2', '0' ):
249 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '0' );
250 p_pack->output_format.i_cat = VIDEO_ES;
252 case VLC_FOURCC( 'I', '4', '2', '2' ):
253 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '2' );
254 p_pack->output_format.i_cat = VIDEO_ES;
258 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
259 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
260 p_pack->output_format.i_cat = AUDIO_ES;
262 case VLC_FOURCC( 'w', 'm', 'a', '1' ):
263 p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' );
264 p_pack->output_format.i_cat = AUDIO_ES;
266 case VLC_FOURCC( 'w', 'm', 'a', '2' ):
267 p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' );
268 p_pack->output_format.i_cat = AUDIO_ES;
270 case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
272 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
275 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
278 p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' ');
281 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
284 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
287 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
290 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
296 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
299 p_pack->output_format.i_cat = AUDIO_ES;
302 case VLC_FOURCC( 't', 'w', 'o', 's' ):
304 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
307 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
310 p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
313 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b');
316 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b');
319 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b');
322 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
328 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
331 p_pack->output_format.i_cat = AUDIO_ES;
334 case VLC_FOURCC( 's', 'o', 'w', 't' ):
336 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
339 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
342 p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
345 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
348 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
351 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
354 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
360 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
363 p_pack->output_format.i_cat = AUDIO_ES;
368 msg_Err( p_pack->p_fifo, "unknown es type !!" );
370 //p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
371 //p_pack->output_format.i_cat = UNKNOWN_ES;
375 switch( p_pack->output_format.i_cat )
379 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
382 p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
383 p_pack->output_format.i_channels = p_wf->nChannels;
384 p_pack->output_format.i_block_align = p_wf->nBlockAlign;
385 p_pack->output_format.i_bitrate = p_wf->nAvgBytesPerSec * 8;
386 p_pack->output_format.i_extra_data = p_wf->cbSize;
387 if( p_wf->cbSize > 0 )
389 p_pack->output_format.p_extra_data =
390 malloc( p_pack->output_format.i_extra_data );
391 memcpy( p_pack->output_format.p_extra_data,
393 p_pack->output_format.i_extra_data );
397 p_pack->output_format.p_extra_data = NULL;
402 p_pack->output_format.i_sample_rate = 0;
403 p_pack->output_format.i_channels = 0;
404 p_pack->output_format.i_block_align = 0;
405 p_pack->output_format.i_bitrate = 0;
406 p_pack->output_format.i_extra_data = 0;
407 p_pack->output_format.p_extra_data = NULL;
414 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
416 p_pack->output_format.i_bitrate = 0;
419 p_pack->output_format.i_width = p_bih->biWidth;
420 p_pack->output_format.i_height = p_bih->biHeight;
421 p_pack->output_format.i_extra_data = p_bih->biSize - sizeof( BITMAPINFOHEADER );
422 if( p_pack->output_format.i_extra_data > 0 )
424 p_pack->output_format.p_extra_data =
425 malloc( p_pack->output_format.i_extra_data );
426 memcpy( p_pack->output_format.p_extra_data,
428 p_pack->output_format.i_extra_data );
433 p_pack->output_format.i_width = 0;
434 p_pack->output_format.i_height = 0;
435 p_pack->output_format.i_extra_data = 0;
436 p_pack->output_format.p_extra_data = NULL;
445 p_pack->p_sout_input =
446 sout_InputNew( p_pack->p_fifo,
447 &p_pack->output_format );
449 if( !p_pack->p_sout_input )
451 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
454 // p_pack->i_last_pts = 0;
455 return( VLC_SUCCESS );
458 /*****************************************************************************
459 * PacketizeThread: packetize an unit (here copy a complete pes)
460 *****************************************************************************/
461 static void PacketizeThread( packetizer_thread_t *p_pack )
463 sout_buffer_t *p_sout_buffer;
468 /* **** get samples count **** */
469 input_ExtractPES( p_pack->p_fifo, &p_pes );
472 p_pack->p_fifo->b_error = 1;
475 i_pts = p_pes->i_pts;
477 if( i_pts <= 0 ) //&& p_pack->i_last_pts <= 0 )
479 msg_Dbg( p_pack->p_fifo, "need pts != 0" );
480 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
484 i_size = p_pes->i_pes_size;
486 // msg_Dbg( p_pack->p_fifo, "pes size:%d", i_size );
489 pes_packet_t *p_pes_next;
490 data_packet_t *p_data;
494 sout_BufferNew( p_pack->p_sout_input->p_sout, i_size );
497 p_pack->p_fifo->b_error = 1;
498 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
501 /* TODO: memcpy of the pes packet */
502 for( i_buffer = 0, p_data = p_pes->p_first;
503 p_data != NULL && i_buffer < i_size;
504 p_data = p_data->p_next)
508 i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
512 p_pack->p_fifo->p_vlc->pf_memcpy( p_sout_buffer->p_buffer + i_buffer,
513 p_data->p_payload_start,
518 p_sout_buffer->i_length = 0;
519 p_sout_buffer->i_dts = i_pts; //p_pes->i_pts - p_pack->i_pts_start;
520 p_sout_buffer->i_pts = i_pts; //p_pes->i_pts - p_pack->i_pts_start;
521 p_sout_buffer->i_bitrate = 0;
523 input_ShowPES( p_pack->p_fifo, &p_pes_next );
526 p_sout_buffer->i_length = p_pes_next->i_pts - i_pts;
528 sout_InputSendBuffer( p_pack->p_sout_input,
532 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
536 /*****************************************************************************
537 * EndThread : packetizer thread destruction
538 *****************************************************************************/
539 static void EndThread ( packetizer_thread_t *p_pack)
541 if( p_pack->p_sout_input )
543 sout_InputDelete( p_pack->p_sout_input );
548 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
552 vlc_mutex_lock( &p_fifo->data_lock );
554 if( p_fifo->p_first == NULL )
558 vlc_mutex_unlock( &p_fifo->data_lock );
559 if( pp_pes ) *pp_pes = NULL;
563 /* Signal the input thread we're waiting. This is only
564 * needed in case of slave clock (ES plug-in) but it won't
566 vlc_cond_signal( &p_fifo->data_wait );
568 /* Wait for the input to tell us when we received a packet. */
569 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
571 p_pes = p_fifo->p_first;
572 vlc_mutex_unlock( &p_fifo->data_lock );