1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: copy.c,v 1.12 2003/07/31 19:02:23 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>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int Open ( vlc_object_t * );
43 set_description( _("Copy packetizer") );
44 set_capability( "packetizer", 1 );
45 set_callbacks( Open, NULL );
48 /*****************************************************************************
50 *****************************************************************************/
51 static int Run ( decoder_fifo_t * );
53 typedef struct packetizer_thread_s
55 /* Input properties */
56 decoder_fifo_t *p_fifo;
58 /* Output properties */
59 sout_packetizer_input_t *p_sout_input;
60 sout_format_t output_format;
62 void (*pf_packetize)( struct packetizer_thread_s * );
64 } packetizer_thread_t;
66 static int Init ( packetizer_thread_t * );
67 static void PacketizeStd( packetizer_thread_t * );
68 static void PacketizeSPU( packetizer_thread_t * );
69 static void End ( packetizer_thread_t * );
72 static void AppendPEStoSoutBuffer( sout_instance_t *,sout_buffer_t **,pes_packet_t *);
73 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes );
75 /*****************************************************************************
76 * Open: 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 * Run: 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;
97 msg_Dbg( p_fifo, "Running copy packetizer (fcc=%4.4s)", (char*)&p_fifo->i_fourcc );
99 p_pack = malloc( sizeof( packetizer_thread_t ) );
100 memset( p_pack, 0, sizeof( packetizer_thread_t ) );
102 p_pack->p_fifo = p_fifo;
106 DecoderError( p_fifo );
110 while( !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
112 p_pack->pf_packetize( p_pack );
115 if( p_pack->p_fifo->b_error )
117 DecoderError( p_pack->p_fifo );
122 return( p_pack->p_fifo->b_error ? VLC_EGENERIC : VLC_SUCCESS );
125 /*****************************************************************************
126 * Init: initialize data before entering main loop
127 *****************************************************************************/
128 static int Init( packetizer_thread_t *p_pack )
131 p_pack->pf_packetize = PacketizeStd;
133 switch( p_pack->p_fifo->i_fourcc )
136 case VLC_FOURCC( 'm', '4', 's', '2'):
137 case VLC_FOURCC( 'M', '4', 'S', '2'):
138 case VLC_FOURCC( 'm', 'p', '4', 's'):
139 case VLC_FOURCC( 'M', 'P', '4', 'S'):
140 case VLC_FOURCC( 'm', 'p', '4', 'v'):
141 case VLC_FOURCC( 'D', 'I', 'V', 'X'):
142 case VLC_FOURCC( 'd', 'i', 'v', 'x'):
143 case VLC_FOURCC( 'X', 'V', 'I', 'D'):
144 case VLC_FOURCC( 'X', 'v', 'i', 'D'):
145 case VLC_FOURCC( 'x', 'v', 'i', 'd'):
146 case VLC_FOURCC( 'D', 'X', '5', '0'):
147 case VLC_FOURCC( 0x04, 0, 0, 0):
148 case VLC_FOURCC( '3', 'I', 'V', '2'):
149 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v');
150 p_pack->output_format.i_cat = VIDEO_ES;
152 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
153 case VLC_FOURCC( 'm', 'p', 'g', '1' ):
154 case VLC_FOURCC( 'm', 'p', 'g', '2' ):
155 case VLC_FOURCC( 'm', 'p', '1', 'v' ):
156 case VLC_FOURCC( 'm', 'p', '2', 'v' ):
157 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v' );
158 p_pack->output_format.i_cat = VIDEO_ES;
161 case VLC_FOURCC( 'd', 'i', 'v', '1' ):
162 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
163 case VLC_FOURCC( 'M', 'P', 'G', '4' ):
164 case VLC_FOURCC( 'm', 'p', 'g', '4' ):
165 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '1' );
166 p_pack->output_format.i_cat = VIDEO_ES;
168 case VLC_FOURCC( 'd', 'i', 'v', '2' ):
169 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
170 case VLC_FOURCC( 'M', 'P', '4', '2' ):
171 case VLC_FOURCC( 'm', 'p', '4', '2' ):
172 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '2' );
173 p_pack->output_format.i_cat = VIDEO_ES;
175 case VLC_FOURCC( 'd', 'i', 'v', '3' ):
176 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
177 case VLC_FOURCC( 'd', 'i', 'v', '4' ):
178 case VLC_FOURCC( 'D', 'I', 'V', '4' ):
179 case VLC_FOURCC( 'd', 'i', 'v', '5' ):
180 case VLC_FOURCC( 'D', 'I', 'V', '5' ):
181 case VLC_FOURCC( 'd', 'i', 'v', '6' ):
182 case VLC_FOURCC( 'D', 'I', 'V', '6' ):
183 case VLC_FOURCC( 'M', 'P', '4', '3' ):
184 case VLC_FOURCC( 'm', 'p', '4', '3' ):
185 case VLC_FOURCC( 'm', 'p', 'g', '3' ):
186 case VLC_FOURCC( 'M', 'P', 'G', '3' ):
187 case VLC_FOURCC( 'A', 'P', '4', '1' ):
188 p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '3' );
189 p_pack->output_format.i_cat = VIDEO_ES;
191 case VLC_FOURCC( 'H', '2', '6', '3' ):
192 case VLC_FOURCC( 'h', '2', '6', '3' ):
193 case VLC_FOURCC( 'U', '2', '6', '3' ):
194 case VLC_FOURCC( 'u', '2', '6', '3' ):
195 p_pack->output_format.i_fourcc = VLC_FOURCC( 'H', '2', '6', '3' );
196 p_pack->output_format.i_cat = VIDEO_ES;
198 case VLC_FOURCC( 'I', '2', '6', '3' ):
199 case VLC_FOURCC( 'i', '2', '6', '3' ):
200 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '2', '6', '3' );
201 p_pack->output_format.i_cat = VIDEO_ES;
203 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
204 p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '1' );
205 p_pack->output_format.i_cat = VIDEO_ES;
207 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
208 p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '2' );
209 p_pack->output_format.i_cat = VIDEO_ES;
211 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
212 case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
213 case VLC_FOURCC( 'm', 'j', 'p', 'a' ):
214 case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
215 case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
216 case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
217 p_pack->output_format.i_fourcc = VLC_FOURCC( 'M', 'J', 'P', 'G' );
218 p_pack->output_format.i_cat = VIDEO_ES;
220 case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
221 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'j', 'p', 'b' );
222 p_pack->output_format.i_cat = VIDEO_ES;
224 case VLC_FOURCC( 'd', 'v', 's', 'l' ):
225 case VLC_FOURCC( 'd', 'v', 's', 'd' ):
226 case VLC_FOURCC( 'D', 'V', 'S', 'D' ):
227 case VLC_FOURCC( 'd', 'v', 'h', 'd' ):
228 p_pack->output_format.i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' );
229 p_pack->output_format.i_cat = VIDEO_ES;
231 case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
232 p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '1' );
233 p_pack->output_format.i_cat = VIDEO_ES;
235 case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
236 p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '3' );
237 p_pack->output_format.i_cat = VIDEO_ES;
240 case VLC_FOURCC( 'I', '4', '2', '0' ):
241 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '0' );
242 p_pack->output_format.i_cat = VIDEO_ES;
244 case VLC_FOURCC( 'I', '4', '2', '2' ):
245 p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '2' );
246 p_pack->output_format.i_cat = VIDEO_ES;
248 case VLC_FOURCC( 'R', 'V', '1', '5' ):
249 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '5' );
250 p_pack->output_format.i_cat = VIDEO_ES;
252 case VLC_FOURCC( 'R', 'V', '1', '6' ):
253 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '6' );
254 p_pack->output_format.i_cat = VIDEO_ES;
256 case VLC_FOURCC( 'R', 'V', '2', '4' ):
257 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '2', '4' );
258 p_pack->output_format.i_cat = VIDEO_ES;
260 case VLC_FOURCC( 'R', 'V', '3', '2' ):
261 p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '3', '2' );
262 p_pack->output_format.i_cat = VIDEO_ES;
264 case VLC_FOURCC( 'G', 'R', 'E', 'Y' ):
265 p_pack->output_format.i_fourcc = VLC_FOURCC( 'G', 'R', 'E', 'Y' );
266 p_pack->output_format.i_cat = VIDEO_ES;
270 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
271 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
272 p_pack->output_format.i_cat = AUDIO_ES;
274 case VLC_FOURCC( 'w', 'm', 'a', '1' ):
275 p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' );
276 p_pack->output_format.i_cat = AUDIO_ES;
278 case VLC_FOURCC( 'w', 'm', 'a', '2' ):
279 p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' );
280 p_pack->output_format.i_cat = AUDIO_ES;
282 case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
284 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
287 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
290 p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' ');
293 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
296 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
299 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
302 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
308 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
311 p_pack->output_format.i_cat = AUDIO_ES;
314 case VLC_FOURCC( 't', 'w', 'o', 's' ):
316 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
319 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
322 p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
325 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b');
328 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b');
331 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b');
334 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
340 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
343 p_pack->output_format.i_cat = AUDIO_ES;
346 case VLC_FOURCC( 's', 'o', 'w', 't' ):
348 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
351 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
354 p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
357 p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
360 p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
363 p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
366 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
372 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
375 p_pack->output_format.i_cat = AUDIO_ES;
380 case VLC_FOURCC( 's', 'p', 'u', ' ' ): /* DVD */
381 case VLC_FOURCC( 's', 'p', 'u', 'b' ):
382 p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'p', 'u', ' ' );
383 p_pack->output_format.i_cat = SPU_ES;
384 p_pack->pf_packetize = PacketizeSPU;
387 msg_Err( p_pack->p_fifo, "unknown es type !!" );
391 switch( p_pack->output_format.i_cat )
395 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
398 p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
399 p_pack->output_format.i_channels = p_wf->nChannels;
400 p_pack->output_format.i_block_align = p_wf->nBlockAlign;
401 p_pack->output_format.i_bitrate = p_wf->nAvgBytesPerSec * 8;
402 p_pack->output_format.i_extra_data = p_wf->cbSize;
403 if( p_wf->cbSize > 0 )
405 p_pack->output_format.p_extra_data =
406 malloc( p_pack->output_format.i_extra_data );
407 memcpy( p_pack->output_format.p_extra_data,
409 p_pack->output_format.i_extra_data );
413 p_pack->output_format.p_extra_data = NULL;
418 p_pack->output_format.i_sample_rate = 0;
419 p_pack->output_format.i_channels = 0;
420 p_pack->output_format.i_block_align = 0;
421 p_pack->output_format.i_bitrate = 0;
422 p_pack->output_format.i_extra_data = 0;
423 p_pack->output_format.p_extra_data = NULL;
430 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
432 p_pack->output_format.i_bitrate = 0;
435 p_pack->output_format.i_width = p_bih->biWidth;
436 p_pack->output_format.i_height = p_bih->biHeight;
437 p_pack->output_format.i_extra_data = p_bih->biSize - sizeof( BITMAPINFOHEADER );
438 if( p_pack->output_format.i_extra_data > 0 )
440 p_pack->output_format.p_extra_data =
441 malloc( p_pack->output_format.i_extra_data );
442 memcpy( p_pack->output_format.p_extra_data,
444 p_pack->output_format.i_extra_data );
449 p_pack->output_format.i_width = 0;
450 p_pack->output_format.i_height = 0;
451 p_pack->output_format.i_extra_data = 0;
452 p_pack->output_format.p_extra_data = NULL;
458 p_pack->output_format.i_extra_data = 0;
459 p_pack->output_format.p_extra_data = NULL;
466 p_pack->p_sout_input =
467 sout_InputNew( p_pack->p_fifo,
468 &p_pack->output_format );
470 if( !p_pack->p_sout_input )
472 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
476 return( VLC_SUCCESS );
479 /*****************************************************************************
480 * PacketizeStd: packetize an unit (here copy a complete pes)
481 *****************************************************************************/
482 static void PacketizeStd( packetizer_thread_t *p_pack )
484 sout_buffer_t *p_out = NULL;
487 input_ExtractPES( p_pack->p_fifo, &p_pes );
490 p_pack->p_fifo->b_error = 1;
494 msg_Dbg( p_pack->p_fifo,
495 "pes size:%d dts=%lld pts=%lld",
496 p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
499 if( p_pes->i_pts <= 0 )
501 msg_Dbg( p_pack->p_fifo, "need pts != 0" );
502 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
506 if( p_pes->i_pes_size > 0 )
508 pes_packet_t *p_next;
510 AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
512 input_ShowPES( p_pack->p_fifo, &p_next );
513 if( p_next && p_next->i_pts > 0 )
515 p_out->i_length = p_next->i_pts - p_pes->i_pts;
518 sout_InputSendBuffer( p_pack->p_sout_input,
522 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
525 /*****************************************************************************
526 * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle)
527 *****************************************************************************/
528 static void PacketizeSPU( packetizer_thread_t *p_pack )
530 sout_buffer_t *p_out = NULL;
537 input_ExtractPES( p_pack->p_fifo, &p_pes );
540 p_pack->p_fifo->b_error = 1;
544 msg_Dbg( p_pack->p_fifo,
545 "pes size:%d dts=%lld pts=%lld",
546 p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
549 ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) )
551 msg_Dbg( p_pack->p_fifo, "invalid starting packet (size < 4 or pts <=0)" );
552 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
556 if( p_pes->i_pes_size > 0 )
558 AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
560 if( i_spu_size <= 0 )
563 i_spu_size = ( p_out->p_buffer[0] << 8 )| p_out->p_buffer[1];
564 i_rle = ( ( p_out->p_buffer[2] << 8 )| p_out->p_buffer[3] ) - 4;
566 msg_Dbg( p_pack->p_fifo, "i_spu_size=%d i_rle=%d", i_spu_size, i_rle );
567 if( i_spu_size == 0 || i_rle >= i_spu_size )
569 sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out );
570 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
576 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
578 if( (int)p_out->i_size >= i_spu_size )
583 msg_Dbg( p_pack->p_fifo,
584 "SPU packets size=%d should be %d",
585 p_out->i_size, i_spu_size );
587 sout_InputSendBuffer( p_pack->p_sout_input, p_out );
591 /*****************************************************************************
592 * End : packetizer thread destruction
593 *****************************************************************************/
594 static void End ( packetizer_thread_t *p_pack)
596 if( p_pack->p_sout_input )
598 sout_InputDelete( p_pack->p_sout_input );
603 /*****************************************************************************
604 * AppendPEStoSoutBuffer: copy/cat one pes into a sout_buffer_t.
605 *****************************************************************************/
606 static void AppendPEStoSoutBuffer( sout_instance_t *p_sout,
607 sout_buffer_t **pp_out,
608 pes_packet_t *p_pes )
610 sout_buffer_t *p_out = *pp_out;
613 data_packet_t *p_data;
618 p_out = *pp_out = sout_BufferNew( p_sout, p_pes->i_pes_size );
619 p_out->i_dts = p_pes->i_pts;
620 p_out->i_pts = p_pes->i_pts;
624 i_out = p_out->i_size;
625 sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size );
627 p_out->i_size = i_out + p_pes->i_pes_size;
629 for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next)
633 i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
634 p_out->i_size - i_out );
637 memcpy( &p_out->p_buffer[i_out],
638 p_data->p_payload_start,
643 p_out->i_size = i_out;
646 /*****************************************************************************
647 * input_ShowPES: Show the next PES in the fifo
648 *****************************************************************************/
649 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
651 vlc_mutex_lock( &p_fifo->data_lock );
653 if( p_fifo->p_first == NULL )
657 vlc_mutex_unlock( &p_fifo->data_lock );
662 /* Signal the input thread we're waiting. This is only
663 * needed in case of slave clock (ES plug-in) but it won't
665 vlc_cond_signal( &p_fifo->data_wait );
667 /* Wait for the input to tell us when we received a packet. */
668 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
670 *pp_pes = p_fifo->p_first;
671 vlc_mutex_unlock( &p_fifo->data_lock );