1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: copy.c,v 1.11 2003/07/20 23:30:07 gbazin 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;
247 case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
248 p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '3' );
249 p_pack->output_format.i_cat = VIDEO_ES;
252 case VLC_FOURCC( 'I', '4', '2', '0' ):
253 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '0' );
254 p_pack->output_format.i_cat = VIDEO_ES;
256 case VLC_FOURCC( 'I', '4', '2', '2' ):
257 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '2' );
258 p_pack->output_format.i_cat = VIDEO_ES;
260 case VLC_FOURCC( 'R', 'V', '1', '5' ):
261 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '5' );
262 p_pack->output_format.i_cat = VIDEO_ES;
264 case VLC_FOURCC( 'R', 'V', '1', '6' ):
265 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '6' );
266 p_pack->output_format.i_cat = VIDEO_ES;
268 case VLC_FOURCC( 'R', 'V', '2', '4' ):
269 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '2', '4' );
270 p_pack->output_format.i_cat = VIDEO_ES;
272 case VLC_FOURCC( 'R', 'V', '3', '2' ):
273 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '3', '2' );
274 p_pack->output_format.i_cat = VIDEO_ES;
276 case VLC_FOURCC( 'G', 'R', 'E', 'Y' ):
277 p_pack->output_format.i_fourcc = VLC_FOURCC( 'G', 'R', 'E', 'Y' );
278 p_pack->output_format.i_cat = VIDEO_ES;
282 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
283 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
284 p_pack->output_format.i_cat = AUDIO_ES;
286 case VLC_FOURCC( 'w', 'm', 'a', '1' ):
287 p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' );
288 p_pack->output_format.i_cat = AUDIO_ES;
290 case VLC_FOURCC( 'w', 'm', 'a', '2' ):
291 p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' );
292 p_pack->output_format.i_cat = AUDIO_ES;
294 case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
296 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
299 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
302 p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' ');
305 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
308 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
311 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
314 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
320 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
323 p_pack->output_format.i_cat = AUDIO_ES;
326 case VLC_FOURCC( 't', 'w', 'o', 's' ):
328 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
331 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
334 p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
337 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b');
340 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b');
343 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b');
346 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
352 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
355 p_pack->output_format.i_cat = AUDIO_ES;
358 case VLC_FOURCC( 's', 'o', 'w', 't' ):
360 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
363 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
366 p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
369 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
372 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
375 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
378 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
384 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
387 p_pack->output_format.i_cat = AUDIO_ES;
392 msg_Err( p_pack->p_fifo, "unknown es type !!" );
394 //p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
395 //p_pack->output_format.i_cat = UNKNOWN_ES;
399 switch( p_pack->output_format.i_cat )
403 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
406 p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
407 p_pack->output_format.i_channels = p_wf->nChannels;
408 p_pack->output_format.i_block_align = p_wf->nBlockAlign;
409 p_pack->output_format.i_bitrate = p_wf->nAvgBytesPerSec * 8;
410 p_pack->output_format.i_extra_data = p_wf->cbSize;
411 if( p_wf->cbSize > 0 )
413 p_pack->output_format.p_extra_data =
414 malloc( p_pack->output_format.i_extra_data );
415 memcpy( p_pack->output_format.p_extra_data,
417 p_pack->output_format.i_extra_data );
421 p_pack->output_format.p_extra_data = NULL;
426 p_pack->output_format.i_sample_rate = 0;
427 p_pack->output_format.i_channels = 0;
428 p_pack->output_format.i_block_align = 0;
429 p_pack->output_format.i_bitrate = 0;
430 p_pack->output_format.i_extra_data = 0;
431 p_pack->output_format.p_extra_data = NULL;
438 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
440 p_pack->output_format.i_bitrate = 0;
443 p_pack->output_format.i_width = p_bih->biWidth;
444 p_pack->output_format.i_height = p_bih->biHeight;
445 p_pack->output_format.i_extra_data = p_bih->biSize - sizeof( BITMAPINFOHEADER );
446 if( p_pack->output_format.i_extra_data > 0 )
448 p_pack->output_format.p_extra_data =
449 malloc( p_pack->output_format.i_extra_data );
450 memcpy( p_pack->output_format.p_extra_data,
452 p_pack->output_format.i_extra_data );
457 p_pack->output_format.i_width = 0;
458 p_pack->output_format.i_height = 0;
459 p_pack->output_format.i_extra_data = 0;
460 p_pack->output_format.p_extra_data = NULL;
469 p_pack->p_sout_input =
470 sout_InputNew( p_pack->p_fifo,
471 &p_pack->output_format );
473 if( !p_pack->p_sout_input )
475 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
478 // p_pack->i_last_pts = 0;
479 return( VLC_SUCCESS );
482 /*****************************************************************************
483 * PacketizeThread: packetize an unit (here copy a complete pes)
484 *****************************************************************************/
485 static void PacketizeThread( packetizer_thread_t *p_pack )
487 sout_buffer_t *p_sout_buffer;
492 /* **** get samples count **** */
493 input_ExtractPES( p_pack->p_fifo, &p_pes );
496 p_pack->p_fifo->b_error = 1;
499 i_pts = p_pes->i_pts;
501 if( i_pts <= 0 ) //&& p_pack->i_last_pts <= 0 )
503 msg_Dbg( p_pack->p_fifo, "need pts != 0" );
504 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
508 i_size = p_pes->i_pes_size;
510 // msg_Dbg( p_pack->p_fifo, "pes size:%d", i_size );
513 pes_packet_t *p_pes_next;
514 data_packet_t *p_data;
518 sout_BufferNew( p_pack->p_sout_input->p_sout, i_size );
521 p_pack->p_fifo->b_error = 1;
522 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
525 /* TODO: memcpy of the pes packet */
526 for( i_buffer = 0, p_data = p_pes->p_first;
527 p_data != NULL && i_buffer < i_size;
528 p_data = p_data->p_next)
532 i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
536 p_pack->p_fifo->p_vlc->pf_memcpy( p_sout_buffer->p_buffer + i_buffer,
537 p_data->p_payload_start,
542 p_sout_buffer->i_length = 0;
543 p_sout_buffer->i_dts = i_pts; //p_pes->i_pts - p_pack->i_pts_start;
544 p_sout_buffer->i_pts = i_pts; //p_pes->i_pts - p_pack->i_pts_start;
545 p_sout_buffer->i_bitrate = 0;
547 input_ShowPES( p_pack->p_fifo, &p_pes_next );
550 p_sout_buffer->i_length = p_pes_next->i_pts - i_pts;
552 sout_InputSendBuffer( p_pack->p_sout_input,
556 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
560 /*****************************************************************************
561 * EndThread : packetizer thread destruction
562 *****************************************************************************/
563 static void EndThread ( packetizer_thread_t *p_pack)
565 if( p_pack->p_sout_input )
567 sout_InputDelete( p_pack->p_sout_input );
572 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
576 vlc_mutex_lock( &p_fifo->data_lock );
578 if( p_fifo->p_first == NULL )
582 vlc_mutex_unlock( &p_fifo->data_lock );
583 if( pp_pes ) *pp_pes = NULL;
587 /* Signal the input thread we're waiting. This is only
588 * needed in case of slave clock (ES plug-in) but it won't
590 vlc_cond_signal( &p_fifo->data_wait );
592 /* Wait for the input to tell us when we received a packet. */
593 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
595 p_pes = p_fifo->p_first;
596 vlc_mutex_unlock( &p_fifo->data_lock );