]> git.sesse.net Git - vlc/blob - modules/packetizer/copy.c
* modules/mux/ogg.c: always backup the vorbis/theora headers so we can resend them...
[vlc] / modules / packetizer / copy.c
1 /*****************************************************************************
2  * copy.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: copy.c,v 1.17 2003/09/29 22:37:36 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         case VLC_FOURCC( 'I', '4', '2', '0' ):
244             p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '0' );
245             p_pack->output_format.i_cat = VIDEO_ES;
246             break;
247         case VLC_FOURCC( 'I', '4', '2', '2' ):
248             p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '4', '2', '2' );
249             p_pack->output_format.i_cat = VIDEO_ES;
250             break;
251         case VLC_FOURCC( 'R', 'V', '1', '5' ):
252             p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '5' );
253             p_pack->output_format.i_cat = VIDEO_ES;
254             break;
255         case VLC_FOURCC( 'R', 'V', '1', '6' ):
256             p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '1', '6' );
257             p_pack->output_format.i_cat = VIDEO_ES;
258             break;
259         case VLC_FOURCC( 'R', 'V', '2', '4' ):
260             p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '2', '4' );
261             p_pack->output_format.i_cat = VIDEO_ES;
262             break;
263         case VLC_FOURCC( 'R', 'V', '3', '2' ):
264             p_pack->output_format.i_fourcc = VLC_FOURCC( 'R', 'V', '3', '2' );
265             p_pack->output_format.i_cat = VIDEO_ES;
266             break;
267         case VLC_FOURCC( 'G', 'R', 'E', 'Y' ):
268             p_pack->output_format.i_fourcc = VLC_FOURCC( 'G', 'R', 'E', 'Y' );
269             p_pack->output_format.i_cat = VIDEO_ES;
270             break;
271
272         /* audio */
273         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
274             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
275             p_pack->output_format.i_cat = AUDIO_ES;
276             break;
277         case VLC_FOURCC( 'w', 'm', 'a', '1' ):
278             p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' );
279             p_pack->output_format.i_cat = AUDIO_ES;
280             break;
281         case VLC_FOURCC( 'w', 'm', 'a', '2' ):
282             p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' );
283             p_pack->output_format.i_cat = AUDIO_ES;
284             break;
285         case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
286         {
287             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
288             if( p_wf )
289             {
290                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
291                 {
292                     case 1:
293                         p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' ');
294                         break;
295                     case 2:
296                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
297                         break;
298                     case 3:
299                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
300                         break;
301                     case 4:
302                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
303                         break;
304                     default:
305                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
306                         return VLC_EGENERIC;
307                 }
308             }
309             else
310             {
311                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
312                 return VLC_EGENERIC;
313             }
314             p_pack->output_format.i_cat = AUDIO_ES;
315             break;
316         }
317         case VLC_FOURCC( 't', 'w', 'o', 's' ):
318         {
319             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
320             if( p_wf )
321             {
322                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
323                 {
324                     case 1:
325                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
326                         break;
327                     case 2:
328                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b');
329                         break;
330                     case 3:
331                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b');
332                         break;
333                     case 4:
334                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b');
335                         break;
336                     default:
337                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
338                         return VLC_EGENERIC;
339                 }
340             }
341             else
342             {
343                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
344                 return VLC_EGENERIC;
345             }
346             p_pack->output_format.i_cat = AUDIO_ES;
347             break;
348         }
349         case VLC_FOURCC( 's', 'o', 'w', 't' ):
350         {
351             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
352             if( p_wf )
353             {
354                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
355                 {
356                     case 1:
357                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' ');
358                         break;
359                     case 2:
360                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l');
361                         break;
362                     case 3:
363                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l');
364                         break;
365                     case 4:
366                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l');
367                         break;
368                     default:
369                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
370                         return VLC_EGENERIC;
371                 }
372             }
373             else
374             {
375                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" );
376                 return VLC_EGENERIC;
377             }
378             p_pack->output_format.i_cat = AUDIO_ES;
379             break;
380         }
381
382         /* subtitles */
383         case VLC_FOURCC( 's', 'p', 'u', ' ' ):  /* DVD */
384         case VLC_FOURCC( 's', 'p', 'u', 'b' ):
385             p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'p', 'u', ' ' );
386             p_pack->output_format.i_cat = SPU_ES;
387             p_pack->pf_packetize = PacketizeSPU;
388             break;
389
390         case VLC_FOURCC( 's', 'u', 'b', 't' ):
391             p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'u', 'b', 't' );
392             p_pack->output_format.i_cat = SPU_ES;
393             break;
394
395         default:
396             msg_Err( p_pack->p_fifo, "unknown es type !!" );
397             return VLC_EGENERIC;
398     }
399
400     switch( p_pack->output_format.i_cat )
401     {
402         case AUDIO_ES:
403             {
404                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
405                 if( p_wf )
406                 {
407                     p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
408                     p_pack->output_format.i_channels    = p_wf->nChannels;
409                     p_pack->output_format.i_block_align = p_wf->nBlockAlign;
410                     p_pack->output_format.i_bitrate     = p_wf->nAvgBytesPerSec * 8;
411                     p_pack->output_format.i_extra_data  = p_wf->cbSize;
412                     if( p_wf->cbSize  > 0 )
413                     {
414                         p_pack->output_format.p_extra_data =
415                             malloc( p_pack->output_format.i_extra_data );
416                         memcpy( p_pack->output_format.p_extra_data,
417                                 &p_wf[1],
418                                 p_pack->output_format.i_extra_data );
419                     }
420                     else
421                     {
422                         p_pack->output_format.p_extra_data = NULL;
423                     }
424                 }
425                 else
426                 {
427                     p_pack->output_format.i_sample_rate = 0;
428                     p_pack->output_format.i_channels    = 0;
429                     p_pack->output_format.i_block_align = 0;
430                     p_pack->output_format.i_bitrate     = 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 VIDEO_ES:
438             {
439                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
440
441                 p_pack->output_format.i_bitrate = 0;
442                 if( p_bih )
443                 {
444                     p_pack->output_format.i_width  = p_bih->biWidth;
445                     p_pack->output_format.i_height = p_bih->biHeight;
446                     p_pack->output_format.i_extra_data  = p_bih->biSize - sizeof( BITMAPINFOHEADER );
447                     if( p_pack->output_format.i_extra_data > 0 )
448                     {
449                         p_pack->output_format.p_extra_data =
450                             malloc( p_pack->output_format.i_extra_data );
451                         memcpy( p_pack->output_format.p_extra_data,
452                                 &p_bih[1],
453                                 p_pack->output_format.i_extra_data );
454                     }
455                 }
456                 else
457                 {
458                     p_pack->output_format.i_width  = 0;
459                     p_pack->output_format.i_height = 0;
460                     p_pack->output_format.i_extra_data  = 0;
461                     p_pack->output_format.p_extra_data  = NULL;
462                 }
463             }
464             break;
465
466         case SPU_ES:
467             p_pack->output_format.i_extra_data  = 0;
468             p_pack->output_format.p_extra_data  = NULL;
469             break;
470
471         default:
472             return VLC_EGENERIC;
473     }
474
475     p_pack->p_sout_input =
476         sout_InputNew( p_pack->p_fifo,
477                        &p_pack->output_format );
478
479     if( !p_pack->p_sout_input )
480     {
481         msg_Err( p_pack->p_fifo, "cannot add a new stream" );
482         return VLC_EGENERIC;
483     }
484
485     return( VLC_SUCCESS );
486 }
487
488 /*****************************************************************************
489  * PacketizeStd: packetize an unit (here copy a complete pes)
490  *****************************************************************************/
491 static void PacketizeStd( packetizer_thread_t *p_pack )
492 {
493     sout_buffer_t   *p_out = NULL;
494     pes_packet_t    *p_pes;
495
496     input_ExtractPES( p_pack->p_fifo, &p_pes );
497     if( !p_pes )
498     {
499         p_pack->p_fifo->b_error = 1;
500         return;
501     }
502 #if 0
503     msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd,
504              p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
505 #endif
506
507     if( p_pes->i_pts <= 0 )
508     {
509         msg_Dbg( p_pack->p_fifo, "need pts != 0" );
510         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
511         return;
512     }
513
514     if( p_pes->i_pes_size > 0 )
515     {
516         pes_packet_t    *p_next;
517
518         AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
519
520         input_ShowPES( p_pack->p_fifo, &p_next );
521         if( p_next && p_next->i_pts > 0 )
522         {
523             p_out->i_length = p_next->i_pts - p_pes->i_pts;
524         }
525
526         sout_InputSendBuffer( p_pack->p_sout_input,
527                                p_out );
528     }
529
530     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
531 }
532
533 /*****************************************************************************
534  * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle)
535  *****************************************************************************/
536 static void PacketizeSPU( packetizer_thread_t *p_pack )
537 {
538     sout_buffer_t   *p_out = NULL;
539     pes_packet_t    *p_pes;
540
541     int     i_spu_size = 0;
542
543     for( ;; )
544     {
545         input_ExtractPES( p_pack->p_fifo, &p_pes );
546         if( !p_pes )
547         {
548             p_pack->p_fifo->b_error = 1;
549             return;
550         }
551 #if 0
552         msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd,
553                  p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
554 #endif
555
556         if( p_out == NULL &&
557             ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) )
558         {
559             msg_Dbg( p_pack->p_fifo, "invalid starting packet (size < 4 or pts <=0)" );
560             input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
561             return;
562         }
563
564         if( p_pes->i_pes_size > 0 )
565         {
566             AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
567
568             if( i_spu_size <= 0 )
569             {
570                 int i_rle;
571                 i_spu_size = ( p_out->p_buffer[0] << 8 )| p_out->p_buffer[1];
572                 i_rle      = ( ( p_out->p_buffer[2] << 8 )| p_out->p_buffer[3] ) - 4;
573
574                 msg_Dbg( p_pack->p_fifo, "i_spu_size=%d i_rle=%d", i_spu_size, i_rle );
575                 if( i_spu_size == 0 || i_rle >= i_spu_size )
576                 {
577                     sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out );
578                     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
579                     return;
580                 }
581             }
582         }
583
584         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
585
586         if( (int)p_out->i_size >= i_spu_size )
587         {
588             break;
589         }
590     }
591     msg_Dbg( p_pack->p_fifo,
592              "SPU packets size=%d should be %d",
593              p_out->i_size, i_spu_size );
594
595     sout_InputSendBuffer( p_pack->p_sout_input, p_out );
596 }
597
598
599 /*****************************************************************************
600  * End : packetizer thread destruction
601  *****************************************************************************/
602 static void End ( packetizer_thread_t *p_pack)
603 {
604     if( p_pack->p_sout_input )
605     {
606         sout_InputDelete( p_pack->p_sout_input );
607     }
608     free( p_pack );
609 }
610
611 /*****************************************************************************
612  * AppendPEStoSoutBuffer: copy/cat one pes into a sout_buffer_t.
613  *****************************************************************************/
614 static void AppendPEStoSoutBuffer( sout_instance_t *p_sout,
615                                    sout_buffer_t **pp_out,
616                                    pes_packet_t *p_pes )
617 {
618     sout_buffer_t *p_out = *pp_out;
619     unsigned int  i_out;
620
621     data_packet_t   *p_data;
622
623     if( p_out == NULL )
624     {
625         i_out = 0;
626         p_out = *pp_out = sout_BufferNew( p_sout, p_pes->i_pes_size );
627         p_out->i_dts = p_pes->i_pts;
628         p_out->i_pts = p_pes->i_pts;
629     }
630     else
631     {
632         i_out = p_out->i_size;
633         sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size );
634     }
635     p_out->i_size = i_out + p_pes->i_pes_size;
636
637     for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next)
638     {
639         int i_copy;
640
641         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
642                         p_out->i_size - i_out );
643         if( i_copy > 0 )
644         {
645             memcpy( &p_out->p_buffer[i_out],
646                     p_data->p_payload_start,
647                     i_copy );
648         }
649         i_out += i_copy;
650     }
651     p_out->i_size = i_out;
652 }
653
654 /*****************************************************************************
655  * input_ShowPES: Show the next PES in the fifo
656  *****************************************************************************/
657 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
658 {
659     vlc_mutex_lock( &p_fifo->data_lock );
660
661     if( p_fifo->p_first == NULL )
662     {
663         if( p_fifo->b_die )
664         {
665             vlc_mutex_unlock( &p_fifo->data_lock );
666             *pp_pes = NULL;
667             return;
668         }
669
670         /* Signal the input thread we're waiting. This is only
671          * needed in case of slave clock (ES plug-in) but it won't
672          * harm. */
673         vlc_cond_signal( &p_fifo->data_wait );
674
675         /* Wait for the input to tell us when we received a packet. */
676         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
677     }
678     *pp_pes = p_fifo->p_first;
679     vlc_mutex_unlock( &p_fifo->data_lock );
680 }