]> git.sesse.net Git - vlc/blob - modules/packetizer/copy.c
* copy: removed annoying debug message.
[vlc] / modules / packetizer / copy.c
1 /*****************************************************************************
2  * copy.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: copy.c,v 1.15 2003/08/11 20:19:45 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     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         default:
390             msg_Err( p_pack->p_fifo, "unknown es type !!" );
391             return VLC_EGENERIC;
392     }
393
394     switch( p_pack->output_format.i_cat )
395     {
396         case AUDIO_ES:
397             {
398                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
399                 if( p_wf )
400                 {
401                     p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
402                     p_pack->output_format.i_channels    = p_wf->nChannels;
403                     p_pack->output_format.i_block_align = p_wf->nBlockAlign;
404                     p_pack->output_format.i_bitrate     = p_wf->nAvgBytesPerSec * 8;
405                     p_pack->output_format.i_extra_data  = p_wf->cbSize;
406                     if( p_wf->cbSize  > 0 )
407                     {
408                         p_pack->output_format.p_extra_data =
409                             malloc( p_pack->output_format.i_extra_data );
410                         memcpy( p_pack->output_format.p_extra_data,
411                                 &p_wf[1],
412                                 p_pack->output_format.i_extra_data );
413                     }
414                     else
415                     {
416                         p_pack->output_format.p_extra_data = NULL;
417                     }
418                 }
419                 else
420                 {
421                     p_pack->output_format.i_sample_rate = 0;
422                     p_pack->output_format.i_channels    = 0;
423                     p_pack->output_format.i_block_align = 0;
424                     p_pack->output_format.i_bitrate     = 0;
425                     p_pack->output_format.i_extra_data  = 0;
426                     p_pack->output_format.p_extra_data  = NULL;
427                 }
428             }
429             break;
430
431         case VIDEO_ES:
432             {
433                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
434
435                 p_pack->output_format.i_bitrate = 0;
436                 if( p_bih )
437                 {
438                     p_pack->output_format.i_width  = p_bih->biWidth;
439                     p_pack->output_format.i_height = p_bih->biHeight;
440                     p_pack->output_format.i_extra_data  = p_bih->biSize - sizeof( BITMAPINFOHEADER );
441                     if( p_pack->output_format.i_extra_data > 0 )
442                     {
443                         p_pack->output_format.p_extra_data =
444                             malloc( p_pack->output_format.i_extra_data );
445                         memcpy( p_pack->output_format.p_extra_data,
446                                 &p_bih[1],
447                                 p_pack->output_format.i_extra_data );
448                     }
449                 }
450                 else
451                 {
452                     p_pack->output_format.i_width  = 0;
453                     p_pack->output_format.i_height = 0;
454                     p_pack->output_format.i_extra_data  = 0;
455                     p_pack->output_format.p_extra_data  = NULL;
456                 }
457             }
458             break;
459
460         case SPU_ES:
461             p_pack->output_format.i_extra_data  = 0;
462             p_pack->output_format.p_extra_data  = NULL;
463             break;
464
465         default:
466             return VLC_EGENERIC;
467     }
468
469     p_pack->p_sout_input =
470         sout_InputNew( p_pack->p_fifo,
471                        &p_pack->output_format );
472
473     if( !p_pack->p_sout_input )
474     {
475         msg_Err( p_pack->p_fifo, "cannot add a new stream" );
476         return VLC_EGENERIC;
477     }
478
479     return( VLC_SUCCESS );
480 }
481
482 /*****************************************************************************
483  * PacketizeStd: packetize an unit (here copy a complete pes)
484  *****************************************************************************/
485 static void PacketizeStd( packetizer_thread_t *p_pack )
486 {
487     sout_buffer_t   *p_out = NULL;
488     pes_packet_t    *p_pes;
489
490     input_ExtractPES( p_pack->p_fifo, &p_pes );
491     if( !p_pes )
492     {
493         p_pack->p_fifo->b_error = 1;
494         return;
495     }
496 #if 0
497     msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd,
498              p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
499 #endif
500
501     if( p_pes->i_pts <= 0 )
502     {
503         msg_Dbg( p_pack->p_fifo, "need pts != 0" );
504         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
505         return;
506     }
507
508     if( p_pes->i_pes_size > 0 )
509     {
510         pes_packet_t    *p_next;
511
512         AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
513
514         input_ShowPES( p_pack->p_fifo, &p_next );
515         if( p_next && p_next->i_pts > 0 )
516         {
517             p_out->i_length = p_next->i_pts - p_pes->i_pts;
518         }
519
520         sout_InputSendBuffer( p_pack->p_sout_input,
521                                p_out );
522     }
523
524     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
525 }
526
527 /*****************************************************************************
528  * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle)
529  *****************************************************************************/
530 static void PacketizeSPU( packetizer_thread_t *p_pack )
531 {
532     sout_buffer_t   *p_out = NULL;
533     pes_packet_t    *p_pes;
534
535     int     i_spu_size = 0;
536
537     for( ;; )
538     {
539         input_ExtractPES( p_pack->p_fifo, &p_pes );
540         if( !p_pes )
541         {
542             p_pack->p_fifo->b_error = 1;
543             return;
544         }
545 #if 0
546         msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd,
547                  p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts );
548 #endif
549
550         if( p_out == NULL &&
551             ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) )
552         {
553             msg_Dbg( p_pack->p_fifo, "invalid starting packet (size < 4 or pts <=0)" );
554             input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
555             return;
556         }
557
558         if( p_pes->i_pes_size > 0 )
559         {
560             AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes );
561
562             if( i_spu_size <= 0 )
563             {
564                 int i_rle;
565                 i_spu_size = ( p_out->p_buffer[0] << 8 )| p_out->p_buffer[1];
566                 i_rle      = ( ( p_out->p_buffer[2] << 8 )| p_out->p_buffer[3] ) - 4;
567
568                 msg_Dbg( p_pack->p_fifo, "i_spu_size=%d i_rle=%d", i_spu_size, i_rle );
569                 if( i_spu_size == 0 || i_rle >= i_spu_size )
570                 {
571                     sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out );
572                     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
573                     return;
574                 }
575             }
576         }
577
578         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
579
580         if( (int)p_out->i_size >= i_spu_size )
581         {
582             break;
583         }
584     }
585     msg_Dbg( p_pack->p_fifo,
586              "SPU packets size=%d should be %d",
587              p_out->i_size, i_spu_size );
588
589     sout_InputSendBuffer( p_pack->p_sout_input, p_out );
590 }
591
592
593 /*****************************************************************************
594  * End : packetizer thread destruction
595  *****************************************************************************/
596 static void End ( packetizer_thread_t *p_pack)
597 {
598     if( p_pack->p_sout_input )
599     {
600         sout_InputDelete( p_pack->p_sout_input );
601     }
602     free( p_pack );
603 }
604
605 /*****************************************************************************
606  * AppendPEStoSoutBuffer: copy/cat one pes into a sout_buffer_t.
607  *****************************************************************************/
608 static void AppendPEStoSoutBuffer( sout_instance_t *p_sout,
609                                    sout_buffer_t **pp_out,
610                                    pes_packet_t *p_pes )
611 {
612     sout_buffer_t *p_out = *pp_out;
613     unsigned int  i_out;
614
615     data_packet_t   *p_data;
616
617     if( p_out == NULL )
618     {
619         i_out = 0;
620         p_out = *pp_out = sout_BufferNew( p_sout, p_pes->i_pes_size );
621         p_out->i_dts = p_pes->i_pts;
622         p_out->i_pts = p_pes->i_pts;
623     }
624     else
625     {
626         i_out = p_out->i_size;
627         sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size );
628     }
629     p_out->i_size = i_out + p_pes->i_pes_size;
630
631     for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next)
632     {
633         int i_copy;
634
635         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
636                         p_out->i_size - i_out );
637         if( i_copy > 0 )
638         {
639             memcpy( &p_out->p_buffer[i_out],
640                     p_data->p_payload_start,
641                     i_copy );
642         }
643         i_out += i_copy;
644     }
645     p_out->i_size = i_out;
646 }
647
648 /*****************************************************************************
649  * input_ShowPES: Show the next PES in the fifo
650  *****************************************************************************/
651 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
652 {
653     vlc_mutex_lock( &p_fifo->data_lock );
654
655     if( p_fifo->p_first == NULL )
656     {
657         if( p_fifo->b_die )
658         {
659             vlc_mutex_unlock( &p_fifo->data_lock );
660             *pp_pes = NULL;
661             return;
662         }
663
664         /* Signal the input thread we're waiting. This is only
665          * needed in case of slave clock (ES plug-in) but it won't
666          * harm. */
667         vlc_cond_signal( &p_fifo->data_wait );
668
669         /* Wait for the input to tell us when we received a packet. */
670         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
671     }
672     *pp_pes = p_fifo->p_first;
673     vlc_mutex_unlock( &p_fifo->data_lock );
674 }
675