]> git.sesse.net Git - vlc/blob - src/spu_decoder/spu_decoder.c
* Coding style fixes here and there.
[vlc] / src / spu_decoder / spu_decoder.c
1 /*****************************************************************************
2  * spu_decoder.c : spu decoder thread
3  *****************************************************************************
4  * Copyright (C) 2000 VideoLAN
5  * $Id: spu_decoder.c,v 1.38 2001/04/28 03:36:25 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <unistd.h>                                              /* getpid() */
30 #ifdef WIN32                   /* getpid() for win32 is located in process.h */
31 #include <process.h>
32 #endif
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                    /* memcpy(), memset() */
36
37 #include "config.h"
38 #include "common.h"
39 #include "threads.h"
40 #include "mtime.h"
41
42 #include "intf_msg.h"
43
44 #include "stream_control.h"
45 #include "input_ext-dec.h"
46
47 #include "video.h"
48 #include "video_output.h"
49
50 #include "spu_decoder.h"
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 static int  InitThread  ( spudec_thread_t * );
56 static void RunThread   ( spudec_thread_t * );
57 static void ErrorThread ( spudec_thread_t * );
58 static void EndThread   ( spudec_thread_t * );
59
60 static int  SyncPacket           ( spudec_thread_t * );
61 static void ParsePacket          ( spudec_thread_t * );
62 static int  ParseControlSequences( spudec_thread_t *, subpicture_t * );
63 static int  ParseRLE             ( u8 *,              subpicture_t * );
64
65 /*****************************************************************************
66  * spudec_CreateThread: create a spu decoder thread
67  *****************************************************************************/
68 vlc_thread_t spudec_CreateThread( vdec_config_t * p_config )
69 {
70     spudec_thread_t *     p_spudec;
71
72     /* Allocate the memory needed to store the thread's structure */
73     p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
74
75     if ( p_spudec == NULL )
76     {
77         intf_ErrMsg( "spudec error: not enough memory "
78                      "for spudec_CreateThread() to create the new thread" );
79         return( 0 );
80     }
81
82     /*
83      * Initialize the thread properties
84      */
85     p_spudec->p_config = p_config;
86     p_spudec->p_fifo = p_config->decoder_config.p_decoder_fifo;
87
88     /* Get the video output informations */
89     p_spudec->p_vout = p_config->p_vout;
90
91     /* Spawn the spu decoder thread */
92     if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
93          (vlc_thread_func_t)RunThread, (void *)p_spudec) )
94     {
95         intf_ErrMsg( "spudec error: can't spawn spu decoder thread" );
96         free( p_spudec );
97         return( 0 );
98     }
99
100     return( p_spudec->thread_id );
101 }
102
103 /* following functions are local */
104
105 /*****************************************************************************
106  * InitThread: initialize spu decoder thread
107  *****************************************************************************
108  * This function is called from RunThread and performs the second step of the
109  * initialization. It returns 0 on success. Note that the thread's flag are not
110  * modified inside this function.
111  *****************************************************************************/
112 static int InitThread( spudec_thread_t *p_spudec )
113 {
114     p_spudec->p_config->decoder_config.pf_init_bit_stream(
115             &p_spudec->bit_stream,
116             p_spudec->p_config->decoder_config.p_decoder_fifo, NULL, NULL );
117
118     /* Mark thread as running and return */
119     return( 0 );
120 }
121
122 /*****************************************************************************
123  * RunThread: spu decoder thread
124  *****************************************************************************
125  * spu decoder thread. This function only returns when the thread is
126  * terminated.
127  *****************************************************************************/
128 static void RunThread( spudec_thread_t *p_spudec )
129 {
130     intf_WarnMsg( 1, "spudec: spu decoder thread %i spawned", getpid() );
131
132     /*
133      * Initialize thread and free configuration
134      */
135     p_spudec->p_fifo->b_error = InitThread( p_spudec );
136
137     /*
138      * Main loop - it is not executed if an error occured during
139      * initialization
140      */
141     while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
142     {
143         if( !SyncPacket( p_spudec ) )
144         {
145             ParsePacket( p_spudec );
146         }
147     }
148
149     /*
150      * Error loop
151      */
152     if( p_spudec->p_fifo->b_error )
153     {
154         ErrorThread( p_spudec );
155     }
156
157     /* End of thread */
158     intf_WarnMsg( 1, "spudec: destroying spu decoder thread %i", getpid() );
159     EndThread( p_spudec );
160 }
161
162 /*****************************************************************************
163  * ErrorThread: RunThread() error loop
164  *****************************************************************************
165  * This function is called when an error occured during thread main's loop. The
166  * thread can still receive feed, but must be ready to terminate as soon as
167  * possible.
168  *****************************************************************************/
169 static void ErrorThread( spudec_thread_t *p_spudec )
170 {
171     /* We take the lock, because we are going to read/write the start/end
172      * indexes of the decoder fifo */
173     vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
174
175     /* Wait until a `die' order is sent */
176     while( !p_spudec->p_fifo->b_die )
177     {
178         /* Trash all received PES packets */
179         while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
180         {
181             p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
182                     DECODER_FIFO_START(*p_spudec->p_fifo) );
183             DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
184         }
185
186         /* Waiting for the input thread to put new PES packets in the fifo */
187         vlc_cond_wait( &p_spudec->p_fifo->data_wait,
188                        &p_spudec->p_fifo->data_lock );
189     }
190
191     /* We can release the lock before leaving */
192     vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
193 }
194
195 /*****************************************************************************
196  * EndThread: thread destruction
197  *****************************************************************************
198  * This function is called when the thread ends after a sucessful
199  * initialization.
200  *****************************************************************************/
201 static void EndThread( spudec_thread_t *p_spudec )
202 {
203     free( p_spudec->p_config );
204     free( p_spudec );
205 }
206
207 /*****************************************************************************
208  * SyncPacket: get in sync with the stream
209  *****************************************************************************
210  * This function makes a few sanity checks and returns 0 if it looks like we
211  * are at the beginning of a subpicture packet.
212  *****************************************************************************/
213 static int SyncPacket( spudec_thread_t *p_spudec )
214 {
215     /* Re-align the buffer on an 8-bit boundary */
216     RealignBits( &p_spudec->bit_stream );
217
218     /* The total SPU packet size, often bigger than a PS packet */
219     p_spudec->i_spu_size = GetBits( &p_spudec->bit_stream, 16 );
220
221     /* The RLE stuff size (remove 4 because we just read 32 bits) */
222     p_spudec->i_rle_size = ShowBits( &p_spudec->bit_stream, 16 ) - 4;
223
224     /* If the values we got are a bit strange, skip packet */
225     if( p_spudec->i_rle_size >= p_spudec->i_spu_size )
226     {
227         return( 1 );
228     }
229
230     RemoveBits( &p_spudec->bit_stream, 16 );
231
232     return( 0 );
233 }
234
235 /*****************************************************************************
236  * ParsePacket: parse an SPU packet and send it to the video output
237  *****************************************************************************
238  * This function parses the SPU packet and, if valid, sends it to the
239  * video output.
240  *****************************************************************************/
241 static void ParsePacket( spudec_thread_t *p_spudec )
242 {
243     subpicture_t * p_spu;
244     u8           * p_src;
245
246     /* We cannot display a subpicture with no date */
247     if( DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts == 0 )
248     {
249         return;
250     }
251
252     /* Allocate the subpicture internal data. */
253     p_spu = vout_CreateSubPicture( p_spudec->p_vout, DVD_SUBPICTURE,
254                                    p_spudec->i_rle_size * 4 );
255     /* Rationale for the "p_spudec->i_rle_size * 4": we are going to
256      * expand the RLE stuff so that we won't need to read nibbles later
257      * on. This will speed things up a lot. Plus, we'll only need to do
258      * this stupid interlacing stuff once. */
259
260     if( p_spu == NULL )
261     {
262         return;
263     }
264
265     /* Get display time now. If we do it later, we may miss a PTS. */
266     p_spu->begin_date = p_spu->end_date
267                     = DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts;
268
269     /* Allocate the temporary buffer we will parse */
270     p_src = malloc( p_spudec->i_rle_size );
271
272     if( p_src == NULL )
273     {
274         intf_ErrMsg( "spudec error: could not allocate p_src" );
275         vout_DestroySubPicture( p_spudec->p_vout, p_spu );
276         return;
277     }
278
279     /* Get RLE data */
280     GetChunk( &p_spudec->bit_stream, p_src, p_spudec->i_rle_size );
281
282 #if 0
283     /* Dump the subtitle info */
284     intf_WarnHexDump( 0, p_spu->p_data, p_spudec->i_rle_size );
285 #endif
286
287     /* Getting the control part */
288     if( ParseControlSequences( p_spudec, p_spu ) )
289     {
290         /* There was a parse error, delete the subpicture */
291         free( p_src );
292         vout_DestroySubPicture( p_spudec->p_vout, p_spu );
293         return;
294     }
295
296     if( ParseRLE( p_src, p_spu ) )
297     {
298         /* There was a parse error, delete the subpicture */
299         free( p_src );
300         vout_DestroySubPicture( p_spudec->p_vout, p_spu );
301         return;
302     }
303
304     intf_WarnMsg( 1, "spudec: got a valid %ix%i subtitle at (%i,%i), "
305                      "RLE offsets: 0x%x 0x%x",
306                   p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y,
307                   p_spu->type.spu.i_offset[0], p_spu->type.spu.i_offset[1] );
308
309     /* SPU is finished - we can ask the video output to display it */
310     vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
311
312     /* Clean up */
313     free( p_src );
314 }
315
316 /*****************************************************************************
317  * ParseControlSequences: parse all SPU control sequences
318  *****************************************************************************
319  * This is the most important part in SPU decoding. We get dates, palette
320  * information, coordinates, and so on. For more information on the
321  * subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
322  *****************************************************************************/
323 static int ParseControlSequences( spudec_thread_t *p_spudec,
324                                   subpicture_t * p_spu )
325 {
326     /* Our current index in the SPU packet */
327     int i_index = p_spudec->i_rle_size + 4;
328
329     /* The next start-of-control-sequence index and the previous one */
330     int i_next_index = 0, i_prev_index;
331
332     /* Command time and date */
333     u8  i_command;
334     int i_date;
335
336     do
337     {
338         /* Get the control sequence date */
339         i_date = GetBits( &p_spudec->bit_stream, 16 );
340  
341         /* Next offset */
342         i_prev_index = i_next_index;
343         i_next_index = GetBits( &p_spudec->bit_stream, 16 );
344  
345         /* Skip what we just read */
346         i_index += 4;
347  
348         do
349         {
350             i_command = GetBits( &p_spudec->bit_stream, 8 );
351             i_index++;
352  
353             switch( i_command )
354             {
355                 case SPU_CMD_FORCE_DISPLAY:
356  
357                     /* 00 (force displaying) */
358                     break;
359  
360                 /* Convert the dates in seconds to PTS values */
361                 case SPU_CMD_START_DISPLAY:
362  
363                     /* 01 (start displaying) */
364                     p_spu->begin_date += ( i_date * 11000 );
365  
366                     break;
367  
368                 case SPU_CMD_STOP_DISPLAY:
369  
370                     /* 02 (stop displaying) */
371                     p_spu->end_date += ( i_date * 11000 );
372  
373                     break;
374  
375                 case SPU_CMD_SET_PALETTE:
376  
377                     /* 03xxxx (palette) - trashed */
378                     RemoveBits( &p_spudec->bit_stream, 16 );
379                     i_index += 2;
380  
381                     break;
382  
383                 case SPU_CMD_SET_ALPHACHANNEL:
384  
385                     /* 04xxxx (alpha channel) - trashed */
386                     RemoveBits( &p_spudec->bit_stream, 16 );
387                     i_index += 2;
388  
389                     break;
390  
391                 case SPU_CMD_SET_COORDINATES:
392  
393                     /* 05xxxyyyxxxyyy (coordinates) */
394                     p_spu->i_x = GetBits( &p_spudec->bit_stream, 12 );
395                     p_spu->i_width = GetBits( &p_spudec->bit_stream, 12 )
396                                       - p_spu->i_x + 1;
397  
398                     p_spu->i_y = GetBits( &p_spudec->bit_stream, 12 );
399                     p_spu->i_height = GetBits( &p_spudec->bit_stream, 12 )
400                                        - p_spu->i_y + 1;
401  
402                     i_index += 6;
403  
404                     break;
405  
406                 case SPU_CMD_SET_OFFSETS:
407  
408                     /* 06xxxxyyyy (byte offsets) */
409                     p_spu->type.spu.i_offset[0] =
410                         GetBits( &p_spudec->bit_stream, 16 ) - 4;
411  
412                     p_spu->type.spu.i_offset[1] =
413                         GetBits( &p_spudec->bit_stream, 16 ) - 4;
414  
415                     i_index += 4;
416  
417                     break;
418  
419                 case SPU_CMD_END:
420  
421                     /* ff (end) */
422                     break;
423  
424                 default:
425  
426                     /* xx (unknown command) */
427                     intf_ErrMsg( "spudec error: unknown command 0x%.2x",
428                                  i_command );
429                     return( 1 );
430             }
431
432         } while( i_command != SPU_CMD_END );
433
434     } while( i_index == i_next_index );
435
436     /* Check that the last index matches the previous one */
437     if( i_next_index != i_prev_index )
438     {
439         intf_ErrMsg( "spudec error: index mismatch (0x%.4x != 0x%.4x)",
440                      i_next_index, i_prev_index );
441         return( 1 );
442     }
443
444     if( i_index > p_spudec->i_spu_size )
445     {
446         intf_ErrMsg( "spudec error: uh-oh, we went too far (0x%.4x > 0x%.4x)",
447                      i_index, p_spudec->i_spu_size );
448         return( 1 );
449     }
450
451     /* Get rid of padding bytes */
452     switch( p_spudec->i_spu_size - i_index )
453     {
454         case 1:
455
456             RemoveBits( &p_spudec->bit_stream, 8 );
457             i_index++;
458
459         case 0:
460
461             /* Zero or one padding byte, quite usual */
462
463             break;
464
465         default:
466
467             /* More than one padding byte - this is very strange, but
468              * we can deal with it */
469             intf_WarnMsg( 2, "spudec warning: %i padding bytes, we usually "
470                              "get 1 or none",
471                           p_spudec->i_spu_size - i_index );
472
473             while( i_index < p_spudec->i_spu_size )
474             {
475                 RemoveBits( &p_spudec->bit_stream, 8 );
476                 i_index++;
477             }
478
479             break;
480     }
481
482     /* Successfully parsed ! */
483     return( 0 );
484 }
485
486 /*****************************************************************************
487  * ParseRLE: parse the RLE part of the subtitle
488  *****************************************************************************
489  * This part parses the subtitle graphical data and stores it in a more
490  * convenient structure for later decoding. For more information on the
491  * subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
492  *****************************************************************************/
493 static int ParseRLE( u8 *p_src, subpicture_t * p_spu )
494 {
495     unsigned int i_code;
496     unsigned int i_id = 0;
497
498     unsigned int i_width = p_spu->i_width;
499     unsigned int i_height = p_spu->i_height;
500     unsigned int i_x, i_y;
501
502     u16 *p_dest = (u16 *)p_spu->p_data;
503
504     /* The subtitles are interlaced, we need two offsets */
505     unsigned int  pi_table[ 2 ];
506     unsigned int *pi_offset;
507
508     pi_table[ 0 ] = p_spu->type.spu.i_offset[ 0 ] << 1;
509     pi_table[ 1 ] = p_spu->type.spu.i_offset[ 1 ] << 1;
510
511     for( i_y = 0 ; i_y < i_height ; i_y++ )
512     {
513         pi_offset = pi_table + i_id;
514
515         for( i_x = 0 ; i_x < i_width ; i_x += i_code >> 2 )
516         {
517             i_code = AddNibble( 0, p_src, pi_offset );
518
519             if( i_code < 0x04 )
520             {
521                 i_code = AddNibble( i_code, p_src, pi_offset );
522
523                 if( i_code < 0x10 )
524                 {
525                     i_code = AddNibble( i_code, p_src, pi_offset );
526
527                     if( i_code < 0x040 )
528                     {
529                         i_code = AddNibble( i_code, p_src, pi_offset );
530
531                         if( i_code < 0x0100 )
532                         {
533                             /* If the 14 first bits are set to 0, then it's a
534                              * new line. We emulate it. */
535                             if( i_code < 0x0004 )
536                             {
537                                 i_code |= ( i_width - i_x ) << 2;
538                             }
539                             else
540                             {
541                                 /* We have a boo boo ! */
542                                 intf_ErrMsg( "spudec error: unknown RLE code "
543                                              "0x%.4x", i_code );
544                                 return( 1 );
545                             }
546                         }
547                     }
548                 }
549             }
550
551             if( ( (i_code >> 2) + i_x + i_y * i_width ) > i_height * i_width )
552             {
553                 intf_ErrMsg( "spudec error: out of bounds, %i at (%i,%i) is "
554                              "out of %ix%i",
555                              i_code >> 2, i_x, i_y, i_width, i_height);
556                 return( 1 );
557             }
558
559             /* We got a valid code, store it */
560             *p_dest++ = i_code;
561         }
562
563         /* Check that we didn't go too far */
564         if( i_x > i_width )
565         {
566             intf_ErrMsg( "spudec error: i_x overflowed, %i > %i",
567                          i_x, i_width );
568             return( 1 );
569         }
570
571         /* Byte-align the stream */
572         if( *pi_offset & 0x1 )
573         {
574             (*pi_offset)++;
575         }
576
577         /* Swap fields */
578         i_id = ~i_id & 0x1;
579     }
580
581     /* FIXME: we shouldn't need these padding bytes */
582     while( i_y < i_height )
583     {
584         *p_dest++ = i_width << 2;
585         i_y++;
586     }
587
588     return( 0 );
589 }
590