]> git.sesse.net Git - vlc/blob - modules/packetizer/copy.c
* ALL: final improvements to the decoders/packetizers api.
[vlc] / modules / packetizer / copy.c
1 /*****************************************************************************
2  * copy.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: copy.c,v 1.18 2003/11/16 21:07:31 gbazin Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
33 #include <vlc/sout.h>
34
35 #include "codecs.h"
36
37 /*****************************************************************************
38  * Module descriptor
39  *****************************************************************************/
40 static int  Open    ( vlc_object_t * );
41
42 vlc_module_begin();
43     set_description( _("Copy packetizer") );
44     set_capability( "packetizer", 1 );
45     set_callbacks( Open, NULL );
46 vlc_module_end();
47
48 /*****************************************************************************
49  * Local prototypes
50  *****************************************************************************/
51 static int  Run         ( decoder_fifo_t * );
52
53 typedef struct packetizer_thread_s
54 {
55     /* Input properties */
56     decoder_fifo_t          *p_fifo;
57
58     /* Output properties */
59     sout_packetizer_input_t *p_sout_input;
60     sout_format_t           output_format;
61
62     void                    (*pf_packetize)( struct packetizer_thread_s * );
63
64 } packetizer_thread_t;
65
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 * );
70
71
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 );
74
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
79  * to choose.
80  *****************************************************************************/
81 static int Open( vlc_object_t *p_this )
82 {
83     decoder_t *p_dec = (decoder_t*)p_this;
84
85     p_dec->pf_run = Run;
86
87     return VLC_SUCCESS;
88 }
89
90 /*****************************************************************************
91  * Run: this function is called just after the thread is created
92  *****************************************************************************/
93 static int Run( decoder_fifo_t *p_fifo )
94 {
95     packetizer_thread_t *p_pack;
96     int i_ret;
97
98     msg_Dbg( p_fifo, "Running copy packetizer (fcc=%4.4s)",
99              (char*)&p_fifo->i_fourcc );
100
101     p_pack = malloc( sizeof( packetizer_thread_t ) );
102     memset( p_pack, 0, sizeof( packetizer_thread_t ) );
103
104     p_pack->p_fifo = p_fifo;
105
106     if( Init( p_pack ) )
107     {
108         DecoderError( p_fifo );
109         return VLC_EGENERIC;
110     }
111
112     while( !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
113     {
114         p_pack->pf_packetize( p_pack );
115     }
116
117     if( p_pack->p_fifo->b_error )
118     {
119         DecoderError( p_pack->p_fifo );
120     }
121
122     i_ret = p_pack->p_fifo->b_error ? VLC_EGENERIC : VLC_SUCCESS;
123     End( p_pack );
124
125     return( i_ret );
126 }
127
128 /*****************************************************************************
129  * Init: initialize data before entering main loop
130  *****************************************************************************/
131 static int Init( packetizer_thread_t *p_pack )
132 {
133
134     p_pack->pf_packetize = PacketizeStd;
135
136     switch( p_pack->p_fifo->i_fourcc )
137     {
138         /* video */
139         case VLC_FOURCC( 'm', '4', 's', '2'):
140         case VLC_FOURCC( 'M', '4', 'S', '2'):
141         case VLC_FOURCC( 'm', 'p', '4', 's'):
142         case VLC_FOURCC( 'M', 'P', '4', 'S'):
143         case VLC_FOURCC( 'm', 'p', '4', 'v'):
144         case VLC_FOURCC( 'D', 'I', 'V', 'X'):
145         case VLC_FOURCC( 'd', 'i', 'v', 'x'):
146         case VLC_FOURCC( 'X', 'V', 'I', 'D'):
147         case VLC_FOURCC( 'X', 'v', 'i', 'D'):
148         case VLC_FOURCC( 'x', 'v', 'i', 'd'):
149         case VLC_FOURCC( 'D', 'X', '5', '0'):
150         case VLC_FOURCC( 0x04, 0,   0,   0):
151         case VLC_FOURCC( '3', 'I', 'V', '2'):
152             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v');
153             p_pack->output_format.i_cat = VIDEO_ES;
154             break;
155         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
156         case VLC_FOURCC( 'm', 'p', 'g', '1' ):
157         case VLC_FOURCC( 'm', 'p', 'g', '2' ):
158         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
159         case VLC_FOURCC( 'm', 'p', '2', 'v' ):
160             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v' );
161             p_pack->output_format.i_cat = VIDEO_ES;
162             break;
163
164         case VLC_FOURCC( 'd', 'i', 'v', '1' ):
165         case VLC_FOURCC( 'D', 'I', 'V', '1' ):
166         case VLC_FOURCC( 'M', 'P', 'G', '4' ):
167         case VLC_FOURCC( 'm', 'p', 'g', '4' ):
168             p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '1' );
169             p_pack->output_format.i_cat = VIDEO_ES;
170             break;
171         case VLC_FOURCC( 'd', 'i', 'v', '2' ):
172         case VLC_FOURCC( 'D', 'I', 'V', '2' ):
173         case VLC_FOURCC( 'M', 'P', '4', '2' ):
174         case VLC_FOURCC( 'm', 'p', '4', '2' ):
175             p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '2' );
176             p_pack->output_format.i_cat = VIDEO_ES;
177             break;
178         case VLC_FOURCC( 'd', 'i', 'v', '3' ):
179         case VLC_FOURCC( 'D', 'I', 'V', '3' ):
180         case VLC_FOURCC( 'd', 'i', 'v', '4' ):
181         case VLC_FOURCC( 'D', 'I', 'V', '4' ):
182         case VLC_FOURCC( 'd', 'i', 'v', '5' ):
183         case VLC_FOURCC( 'D', 'I', 'V', '5' ):
184         case VLC_FOURCC( 'd', 'i', 'v', '6' ):
185         case VLC_FOURCC( 'D', 'I', 'V', '6' ):
186         case VLC_FOURCC( 'M', 'P', '4', '3' ):
187         case VLC_FOURCC( 'm', 'p', '4', '3' ):
188         case VLC_FOURCC( 'm', 'p', 'g', '3' ):
189         case VLC_FOURCC( 'M', 'P', 'G', '3' ):
190         case VLC_FOURCC( 'A', 'P', '4', '1' ):
191             p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '3' );
192             p_pack->output_format.i_cat = VIDEO_ES;
193             break;
194         case VLC_FOURCC( 'H', '2', '6', '3' ):
195         case VLC_FOURCC( 'h', '2', '6', '3' ):
196         case VLC_FOURCC( 'U', '2', '6', '3' ):
197         case VLC_FOURCC( 'u', '2', '6', '3' ):
198             p_pack->output_format.i_fourcc = VLC_FOURCC( 'H', '2', '6', '3' );
199             p_pack->output_format.i_cat = VIDEO_ES;
200             break;
201         case VLC_FOURCC( 'I', '2', '6', '3' ):
202         case VLC_FOURCC( 'i', '2', '6', '3' ):
203             p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '2', '6', '3' );
204             p_pack->output_format.i_cat = VIDEO_ES;
205             break;
206         case VLC_FOURCC( 'W', 'M', 'V', '1' ):
207             p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '1' );
208             p_pack->output_format.i_cat = VIDEO_ES;
209             break;
210         case VLC_FOURCC( 'W', 'M', 'V', '2' ):
211             p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '2' );
212             p_pack->output_format.i_cat = VIDEO_ES;
213             break;
214         case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
215         case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
216         case VLC_FOURCC( 'm', 'j', 'p', 'a' ):
217         case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
218         case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
219         case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
220             p_pack->output_format.i_fourcc = VLC_FOURCC( 'M', 'J', 'P', 'G' );
221             p_pack->output_format.i_cat = VIDEO_ES;
222             break;
223         case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
224             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'j', 'p', 'b' );
225             p_pack->output_format.i_cat = VIDEO_ES;
226             break;
227         case VLC_FOURCC( 'd', 'v', 's', 'l' ):
228         case VLC_FOURCC( 'd', 'v', 's', 'd' ):
229         case VLC_FOURCC( 'D', 'V', 'S', 'D' ):
230         case VLC_FOURCC( 'd', 'v', 'h', 'd' ):
231             p_pack->output_format.i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' );
232             p_pack->output_format.i_cat = VIDEO_ES;
233             break;
234         case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
235             p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '1' );
236             p_pack->output_format.i_cat = VIDEO_ES;
237             break;
238         case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
239             p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '3' );
240             p_pack->output_format.i_cat = VIDEO_ES;
241             break;
242
243         /* audio */
244         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
245             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
246             p_pack->output_format.i_cat = AUDIO_ES;
247             break;
248         case VLC_FOURCC( 'w', 'm', 'a', '1' ):
249             p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' );
250             p_pack->output_format.i_cat = AUDIO_ES;
251             break;
252         case VLC_FOURCC( 'w', 'm', 'a', '2' ):
253             p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' );
254             p_pack->output_format.i_cat = AUDIO_ES;
255             break;
256         case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
257         {
258             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
259             if( p_wf )
260             {
261                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
262                 {
263                     case 1:
264                         p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' ');
265                         break;
266                     case 2:
267                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
268                         break;
269                     case 3:
270                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
271                         break;
272                     case 4:
273                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
274                         break;
275                     default:
276                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
277                         return VLC_EGENERIC;
278                 }
279             }
280             else
281             {
282                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
283                 return VLC_EGENERIC;
284             }
285             p_pack->output_format.i_cat = AUDIO_ES;
286             break;
287         }
288         case VLC_FOURCC( 't', 'w', 'o', 's' ):
289         {
290             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
291             if( p_wf )
292             {
293                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
294                 {
295                     case 1:
296                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
297                         break;
298                     case 2:
299                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b');
300                         break;
301                     case 3:
302                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b');
303                         break;
304                     case 4:
305                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b');
306                         break;
307                     default:
308                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
309                         return VLC_EGENERIC;
310                 }
311             }
312             else
313             {
314                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
315                 return VLC_EGENERIC;
316             }
317             p_pack->output_format.i_cat = AUDIO_ES;
318             break;
319         }
320         case VLC_FOURCC( 's', 'o', 'w', 't' ):
321         {
322             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
323             if( p_wf )
324             {
325                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
326                 {
327                     case 1:
328                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
329                         break;
330                     case 2:
331                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
332                         break;
333                     case 3:
334                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
335                         break;
336                     case 4:
337                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
338                         break;
339                     default:
340                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
341                         return VLC_EGENERIC;
342                 }
343             }
344             else
345             {
346                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
347                 return VLC_EGENERIC;
348             }
349             p_pack->output_format.i_cat = AUDIO_ES;
350             break;
351         }
352
353         /* subtitles */
354         case VLC_FOURCC( 's', 'p', 'u', ' ' ):  /* DVD */
355         case VLC_FOURCC( 's', 'p', 'u', 'b' ):
356             p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'p', 'u', ' ' );
357             p_pack->output_format.i_cat = SPU_ES;
358             p_pack->pf_packetize = PacketizeSPU;
359             break;
360
361         case VLC_FOURCC( 's', 'u', 'b', 't' ):
362             p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'u', 'b', 't' );
363             p_pack->output_format.i_cat = SPU_ES;
364             break;
365
366         default:
367             msg_Err( p_pack->p_fifo, "unknown es type !!" );
368             return VLC_EGENERIC;
369     }
370
371     switch( p_pack->output_format.i_cat )
372     {
373         case AUDIO_ES:
374             {
375                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
376                 if( p_wf )
377                 {
378                     p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
379                     p_pack->output_format.i_channels    = p_wf->nChannels;
380                     p_pack->output_format.i_block_align = p_wf->nBlockAlign;
381                     p_pack->output_format.i_bitrate     = p_wf->nAvgBytesPerSec * 8;
382                     p_pack->output_format.i_extra_data  = p_wf->cbSize;
383                     if( p_wf->cbSize  > 0 )
384                     {
385                         p_pack->output_format.p_extra_data =
386                             malloc( p_pack->output_format.i_extra_data );
387                         memcpy( p_pack->output_format.p_extra_data,
388                                 &p_wf[1],
389                                 p_pack->output_format.i_extra_data );
390                     }
391                     else
392                     {
393                         p_pack->output_format.p_extra_data = NULL;
394                     }
395                 }
396                 else
397                 {
398                     p_pack->output_format.i_sample_rate = 0;
399                     p_pack->output_format.i_channels    = 0;
400                     p_pack->output_format.i_block_align = 0;
401                     p_pack->output_format.i_bitrate     = 0;
402                     p_pack->output_format.i_extra_data  = 0;
403                     p_pack->output_format.p_extra_data  = NULL;
404                 }
405             }
406             break;
407
408         case VIDEO_ES:
409             {
410                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
411
412                 p_pack->output_format.i_bitrate = 0;
413                 if( p_bih )
414                 {
415                     p_pack->output_format.i_width  = p_bih->biWidth;
416                     p_pack->output_format.i_height = p_bih->biHeight;
417                     p_pack->output_format.i_extra_data  = p_bih->biSize - sizeof( BITMAPINFOHEADER );
418                     if( p_pack->output_format.i_extra_data > 0 )
419                     {
420                         p_pack->output_format.p_extra_data =
421                             malloc( p_pack->output_format.i_extra_data );
422                         memcpy( p_pack->output_format.p_extra_data,
423                                 &p_bih[1],
424                                 p_pack->output_format.i_extra_data );
425                     }
426                 }
427                 else
428                 {
429                     p_pack->output_format.i_width  = 0;
430                     p_pack->output_format.i_height = 0;
431                     p_pack->output_format.i_extra_data  = 0;
432                     p_pack->output_format.p_extra_data  = NULL;
433                 }
434             }
435             break;
436
437         case SPU_ES:
438             p_pack->output_format.i_extra_data  = 0;
439             p_pack->output_format.p_extra_data  = NULL;
440             break;
441
442         default:
443             return VLC_EGENERIC;
444     }
445
446     p_pack->p_sout_input =
447         sout_InputNew( p_pack->p_fifo,
448                        &p_pack->output_format );
449
450     if( !p_pack->p_sout_input )
451     {
452         msg_Err( p_pack->p_fifo, "cannot add a new stream" );
453         return VLC_EGENERIC;
454     }
455
456     return( VLC_SUCCESS );
457 }
458
459 /*****************************************************************************
460  * PacketizeStd: packetize an unit (here copy a complete pes)
461  *****************************************************************************/
462 static void PacketizeStd( packetizer_thread_t *p_pack )
463 {
464     sout_buffer_t   *p_out = NULL;
465     pes_packet_t    *p_pes;
466
467     input_ExtractPES( p_pack->p_fifo, &p_pes );
468     if( !p_pes )
469     {
470         p_pack->p_fifo->b_error = 1;
471         return;
472     }
473 #if 0
474     msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd,
475              p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
476 #endif
477
478     if( p_pes->i_pts <= 0 )
479     {
480         msg_Dbg( p_pack->p_fifo, "need pts != 0" );
481         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
482         return;
483     }
484
485     if( p_pes->i_pes_size > 0 )
486     {
487         pes_packet_t    *p_next;
488
489         AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
490
491         input_ShowPES( p_pack->p_fifo, &p_next );
492         if( p_next && p_next->i_pts > 0 )
493         {
494             p_out->i_length = p_next->i_pts - p_pes->i_pts;
495         }
496
497         sout_InputSendBuffer( p_pack->p_sout_input,
498                                p_out );
499     }
500
501     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
502 }
503
504 /*****************************************************************************
505  * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle)
506  *****************************************************************************/
507 static void PacketizeSPU( packetizer_thread_t *p_pack )
508 {
509     sout_buffer_t   *p_out = NULL;
510     pes_packet_t    *p_pes;
511
512     int     i_spu_size = 0;
513
514     for( ;; )
515     {
516         input_ExtractPES( p_pack->p_fifo, &p_pes );
517         if( !p_pes )
518         {
519             p_pack->p_fifo->b_error = 1;
520             return;
521         }
522 #if 0
523         msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd,
524                  p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
525 #endif
526
527         if( p_out == NULL &&
528             ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) )
529         {
530             msg_Dbg( p_pack->p_fifo, "invalid starting packet (size < 4 or pts <=0)" );
531             input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
532             return;
533         }
534
535         if( p_pes->i_pes_size > 0 )
536         {
537             AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
538
539             if( i_spu_size <= 0 )
540             {
541                 int i_rle;
542                 i_spu_size = ( p_out->p_buffer[0] << 8 )| p_out->p_buffer[1];
543                 i_rle      = ( ( p_out->p_buffer[2] << 8 )| p_out->p_buffer[3] ) - 4;
544
545                 msg_Dbg( p_pack->p_fifo, "i_spu_size=%d i_rle=%d", i_spu_size, i_rle );
546                 if( i_spu_size == 0 || i_rle >= i_spu_size )
547                 {
548                     sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out );
549                     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
550                     return;
551                 }
552             }
553         }
554
555         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
556
557         if( (int)p_out->i_size >= i_spu_size )
558         {
559             break;
560         }
561     }
562     msg_Dbg( p_pack->p_fifo,
563              "SPU packets size=%d should be %d",
564              p_out->i_size, i_spu_size );
565
566     sout_InputSendBuffer( p_pack->p_sout_input, p_out );
567 }
568
569
570 /*****************************************************************************
571  * End : packetizer thread destruction
572  *****************************************************************************/
573 static void End ( packetizer_thread_t *p_pack)
574 {
575     if( p_pack->p_sout_input )
576     {
577         sout_InputDelete( p_pack->p_sout_input );
578     }
579     free( p_pack );
580 }
581
582 /*****************************************************************************
583  * AppendPEStoSoutBuffer: copy/cat one pes into a sout_buffer_t.
584  *****************************************************************************/
585 static void AppendPEStoSoutBuffer( sout_instance_t *p_sout,
586                                    sout_buffer_t **pp_out,
587                                    pes_packet_t *p_pes )
588 {
589     sout_buffer_t *p_out = *pp_out;
590     unsigned int  i_out;
591
592     data_packet_t   *p_data;
593
594     if( p_out == NULL )
595     {
596         i_out = 0;
597         p_out = *pp_out = sout_BufferNew( p_sout, p_pes->i_pes_size );
598         p_out->i_dts = p_pes->i_pts;
599         p_out->i_pts = p_pes->i_pts;
600     }
601     else
602     {
603         i_out = p_out->i_size;
604         sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size );
605     }
606     p_out->i_size = i_out + p_pes->i_pes_size;
607
608     for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next)
609     {
610         int i_copy;
611
612         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
613                         p_out->i_size - i_out );
614         if( i_copy > 0 )
615         {
616             memcpy( &p_out->p_buffer[i_out],
617                     p_data->p_payload_start,
618                     i_copy );
619         }
620         i_out += i_copy;
621     }
622     p_out->i_size = i_out;
623 }
624
625 /*****************************************************************************
626  * input_ShowPES: Show the next PES in the fifo
627  *****************************************************************************/
628 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
629 {
630     vlc_mutex_lock( &p_fifo->data_lock );
631
632     if( p_fifo->p_first == NULL )
633     {
634         if( p_fifo->b_die )
635         {
636             vlc_mutex_unlock( &p_fifo->data_lock );
637             *pp_pes = NULL;
638             return;
639         }
640
641         /* Signal the input thread we're waiting. This is only
642          * needed in case of slave clock (ES plug-in) but it won't
643          * harm. */
644         vlc_cond_signal( &p_fifo->data_wait );
645
646         /* Wait for the input to tell us when we received a packet. */
647         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
648     }
649     *pp_pes = p_fifo->p_first;
650     vlc_mutex_unlock( &p_fifo->data_lock );
651 }