]> git.sesse.net Git - vlc/blob - modules/packetizer/copy.c
* copy.c: Added DVD subtitle support. I still need to commit the TS
[vlc] / modules / packetizer / copy.c
1 /*****************************************************************************
2  * copy.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: copy.c,v 1.12 2003/07/31 19:02:23 fenrir 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_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
84
85     p_fifo->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
97     msg_Dbg( p_fifo, "Running copy packetizer (fcc=%4.4s)", (char*)&p_fifo->i_fourcc );
98
99     p_pack = malloc( sizeof( packetizer_thread_t ) );
100     memset( p_pack, 0, sizeof( packetizer_thread_t ) );
101
102     p_pack->p_fifo = p_fifo;
103
104     if( Init( p_pack ) )
105     {
106         DecoderError( p_fifo );
107         return VLC_EGENERIC;
108     }
109
110     while( !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
111     {
112         p_pack->pf_packetize( p_pack );
113     }
114
115     if( p_pack->p_fifo->b_error )
116     {
117         DecoderError( p_pack->p_fifo );
118     }
119
120     End( p_pack );
121
122     return( p_pack->p_fifo->b_error ? VLC_EGENERIC : VLC_SUCCESS );
123 }
124
125 /*****************************************************************************
126  * Init: initialize data before entering main loop
127  *****************************************************************************/
128 static int Init( packetizer_thread_t *p_pack )
129 {
130
131     p_pack->pf_packetize = PacketizeStd;
132
133     switch( p_pack->p_fifo->i_fourcc )
134     {
135         /* video */
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;
151             break;
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;
159             break;
160
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;
167             break;
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;
174             break;
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;
190             break;
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;
197             break;
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;
202             break;
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;
206             break;
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;
210             break;
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;
219             break;
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;
223             break;
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;
230             break;
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;
234             break;
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;
238             break;
239
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;
243             break;
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;
247             break;
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;
251             break;
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;
255             break;
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;
259             break;
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;
263             break;
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;
267             break;
268
269         /* audio */
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;
273             break;
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;
277             break;
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;
281             break;
282         case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
283         {
284             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
285             if( p_wf )
286             {
287                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
288                 {
289                     case 1:
290                         p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' ');
291                         break;
292                     case 2:
293                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
294                         break;
295                     case 3:
296                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
297                         break;
298                     case 4:
299                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
300                         break;
301                     default:
302                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
303                         return VLC_EGENERIC;
304                 }
305             }
306             else
307             {
308                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
309                 return VLC_EGENERIC;
310             }
311             p_pack->output_format.i_cat = AUDIO_ES;
312             break;
313         }
314         case VLC_FOURCC( 't', 'w', 'o', 's' ):
315         {
316             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
317             if( p_wf )
318             {
319                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
320                 {
321                     case 1:
322                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
323                         break;
324                     case 2:
325                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b');
326                         break;
327                     case 3:
328                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b');
329                         break;
330                     case 4:
331                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b');
332                         break;
333                     default:
334                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
335                         return VLC_EGENERIC;
336                 }
337             }
338             else
339             {
340                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
341                 return VLC_EGENERIC;
342             }
343             p_pack->output_format.i_cat = AUDIO_ES;
344             break;
345         }
346         case VLC_FOURCC( 's', 'o', 'w', 't' ):
347         {
348             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
349             if( p_wf )
350             {
351                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
352                 {
353                     case 1:
354                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
355                         break;
356                     case 2:
357                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
358                         break;
359                     case 3:
360                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
361                         break;
362                     case 4:
363                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
364                         break;
365                     default:
366                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
367                         return VLC_EGENERIC;
368                 }
369             }
370             else
371             {
372                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
373                 return VLC_EGENERIC;
374             }
375             p_pack->output_format.i_cat = AUDIO_ES;
376             break;
377         }
378
379         /* subtitles */
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;
385             break;
386         default:
387             msg_Err( p_pack->p_fifo, "unknown es type !!" );
388             return VLC_EGENERIC;
389     }
390
391     switch( p_pack->output_format.i_cat )
392     {
393         case AUDIO_ES:
394             {
395                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
396                 if( p_wf )
397                 {
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 )
404                     {
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,
408                                 &p_wf[1],
409                                 p_pack->output_format.i_extra_data );
410                     }
411                     else
412                     {
413                         p_pack->output_format.p_extra_data = NULL;
414                     }
415                 }
416                 else
417                 {
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;
424                 }
425             }
426             break;
427
428         case VIDEO_ES:
429             {
430                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
431
432                 p_pack->output_format.i_bitrate = 0;
433                 if( p_bih )
434                 {
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 )
439                     {
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,
443                                 &p_bih[1],
444                                 p_pack->output_format.i_extra_data );
445                     }
446                 }
447                 else
448                 {
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;
453                 }
454             }
455             break;
456
457         case SPU_ES:
458             p_pack->output_format.i_extra_data  = 0;
459             p_pack->output_format.p_extra_data  = NULL;
460             break;
461
462         default:
463             return VLC_EGENERIC;
464     }
465
466     p_pack->p_sout_input =
467         sout_InputNew( p_pack->p_fifo,
468                        &p_pack->output_format );
469
470     if( !p_pack->p_sout_input )
471     {
472         msg_Err( p_pack->p_fifo, "cannot add a new stream" );
473         return VLC_EGENERIC;
474     }
475
476     return( VLC_SUCCESS );
477 }
478
479 /*****************************************************************************
480  * PacketizeStd: packetize an unit (here copy a complete pes)
481  *****************************************************************************/
482 static void PacketizeStd( packetizer_thread_t *p_pack )
483 {
484     sout_buffer_t   *p_out = NULL;
485     pes_packet_t    *p_pes;
486
487     input_ExtractPES( p_pack->p_fifo, &p_pes );
488     if( !p_pes )
489     {
490         p_pack->p_fifo->b_error = 1;
491         return;
492     }
493
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 );
497
498
499     if( p_pes->i_pts <= 0 )
500     {
501         msg_Dbg( p_pack->p_fifo, "need pts != 0" );
502         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
503         return;
504     }
505
506     if( p_pes->i_pes_size > 0 )
507     {
508         pes_packet_t    *p_next;
509
510         AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
511
512         input_ShowPES( p_pack->p_fifo, &p_next );
513         if( p_next && p_next->i_pts > 0 )
514         {
515             p_out->i_length = p_next->i_pts - p_pes->i_pts;
516         }
517
518         sout_InputSendBuffer( p_pack->p_sout_input,
519                                p_out );
520     }
521
522     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
523 }
524
525 /*****************************************************************************
526  * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle)
527  *****************************************************************************/
528 static void PacketizeSPU( packetizer_thread_t *p_pack )
529 {
530     sout_buffer_t   *p_out = NULL;
531     pes_packet_t    *p_pes;
532
533     int     i_spu_size = 0;
534
535     for( ;; )
536     {
537         input_ExtractPES( p_pack->p_fifo, &p_pes );
538         if( !p_pes )
539         {
540             p_pack->p_fifo->b_error = 1;
541             return;
542         }
543
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 );
547
548         if( p_out == NULL &&
549             ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) )
550         {
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 );
553             return;
554         }
555
556         if( p_pes->i_pes_size > 0 )
557         {
558             AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
559
560             if( i_spu_size <= 0 )
561             {
562                 int i_rle;
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;
565
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 )
568                 {
569                     sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out );
570                     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
571                     return;
572                 }
573             }
574         }
575
576         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
577
578         if( (int)p_out->i_size >= i_spu_size )
579         {
580             break;
581         }
582     }
583     msg_Dbg( p_pack->p_fifo,
584              "SPU packets size=%d should be %d",
585              p_out->i_size, i_spu_size );
586
587     sout_InputSendBuffer( p_pack->p_sout_input, p_out );
588 }
589
590
591 /*****************************************************************************
592  * End : packetizer thread destruction
593  *****************************************************************************/
594 static void End ( packetizer_thread_t *p_pack)
595 {
596     if( p_pack->p_sout_input )
597     {
598         sout_InputDelete( p_pack->p_sout_input );
599     }
600     free( p_pack );
601 }
602
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 )
609 {
610     sout_buffer_t *p_out = *pp_out;
611     unsigned int  i_out;
612
613     data_packet_t   *p_data;
614
615     if( p_out == NULL )
616     {
617         i_out = 0;
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;
621     }
622     else
623     {
624         i_out = p_out->i_size;
625         sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size );
626     }
627     p_out->i_size = i_out + p_pes->i_pes_size;
628
629     for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next)
630     {
631         int i_copy;
632
633         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
634                         p_out->i_size - i_out );
635         if( i_copy > 0 )
636         {
637             memcpy( &p_out->p_buffer[i_out],
638                     p_data->p_payload_start,
639                     i_copy );
640         }
641         i_out += i_copy;
642     }
643     p_out->i_size = i_out;
644 }
645
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 )
650 {
651     vlc_mutex_lock( &p_fifo->data_lock );
652
653     if( p_fifo->p_first == NULL )
654     {
655         if( p_fifo->b_die )
656         {
657             vlc_mutex_unlock( &p_fifo->data_lock );
658             *pp_pes = NULL;
659             return;
660         }
661
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
664          * harm. */
665         vlc_cond_signal( &p_fifo->data_wait );
666
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 );
669     }
670     *pp_pes = p_fifo->p_first;
671     vlc_mutex_unlock( &p_fifo->data_lock );
672 }
673