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