]> git.sesse.net Git - vlc/blob - modules/codec/ogt/cvd.c
ogt.c cvd.c, subtitle.h: move common debug string help into subtitle.h
[vlc] / modules / codec / ogt / cvd.c
1 /*****************************************************************************
2  * cvd.c : CVD Subtitle decoder thread
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: cvd.c,v 1.6 2004/01/03 12:54:56 rocky Exp $
6  *
7  * Authors: Rocky Bernstein
8  *   based on code from:
9  *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
10  *       Samuel Hocevar <sam@zoy.org>
11  *       Laurent Aimar <fenrir@via.ecp.fr>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <vlc/vlc.h>
32 #include <vlc/vout.h>
33 #include <vlc/decoder.h>
34
35 #include "subtitle.h"
36 #include "cvd.h"
37 #include "common.h"
38
39 /*****************************************************************************
40  * Module descriptor.
41  *****************************************************************************/
42 static int  DecoderOpen   ( vlc_object_t * );
43 static int  PacketizerOpen( vlc_object_t * );
44
45 vlc_module_begin();
46     set_description( _("CVD subtitle decoder") );
47     set_capability( "decoder", 50 );
48     set_callbacks( DecoderOpen, VCDSubClose );
49
50     add_integer ( MODULE_STRING "-debug", 0, NULL,
51                   N_("set debug mask for additional debugging."),
52                   N_(DEBUG_LONGTEXT), VLC_TRUE );
53
54     add_submodule();
55     set_description( _("Chaoji VCD subtitle packetizer") );
56     set_capability( "packetizer", 50 );
57     set_callbacks( PacketizerOpen, VCDSubClose );
58 vlc_module_end();
59
60 /*****************************************************************************
61  * Local prototypes
62  *****************************************************************************/
63
64 static block_t *Reassemble( decoder_t *, block_t ** );
65 static void     Decode   ( decoder_t *, block_t ** );
66 static block_t *Packetize( decoder_t *, block_t ** );
67
68
69 /*****************************************************************************
70  * DecoderOpen
71  *****************************************************************************
72  * Tries to launch a decoder and return score so that the interface is able
73  * to chose.
74  *****************************************************************************/
75 static int
76 DecoderOpen( vlc_object_t *p_this )
77 {
78     decoder_t     *p_dec = (decoder_t*)p_this;
79     decoder_sys_t *p_sys;
80
81     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'c','v','d',' ' ) )
82     {
83         return VLC_EGENERIC;
84     }
85
86
87     p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
88
89     p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
90     p_sys->b_packetizer  = VLC_FALSE;
91     p_sys->p_vout        = NULL;
92     p_sys->i_image       = -1;
93     p_sys->subtitle_data = NULL;
94
95     VCDSubInitSubtitleBlock( p_sys );
96
97     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'c','v','d',' ' ) );
98
99
100     p_dec->pf_decode_sub = Decode;
101     p_dec->pf_packetize  = Packetize;
102
103     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
104
105     return VLC_SUCCESS;
106 }
107
108 /*****************************************************************************
109  * PacketizerOpen
110  *****************************************************************************
111  * Tries to launch a decoder and return score so that the interface is able
112  * to chose.
113  *****************************************************************************/
114 static int PacketizerOpen( vlc_object_t *p_this )
115 {
116     decoder_t *p_dec = (decoder_t*)p_this;
117
118     if( DecoderOpen( p_this ) )
119     {
120         return VLC_EGENERIC;
121     }
122     p_dec->p_sys->b_packetizer = VLC_TRUE;
123
124     return VLC_SUCCESS;
125 }
126
127 /*****************************************************************************
128  * Decode:
129  *****************************************************************************/
130 static void
131 Decode ( decoder_t *p_dec, block_t **pp_block )
132 {
133     decoder_sys_t *p_sys = p_dec->p_sys;
134     block_t       *p_spu = Reassemble( p_dec, pp_block );
135
136     dbg_print( (DECODE_DBG_CALL) , "");
137
138     if( p_spu )
139     {
140         p_sys->i_spu = block_ChainExtract( p_spu, p_sys->buffer, 65536 );
141         p_sys->i_pts = p_spu->i_pts;
142         block_ChainRelease( p_spu );
143
144         if( ( p_sys->p_vout = VCDSubFindVout( p_dec ) ) )
145         {
146             /* Parse and decode */
147             E_(ParsePacket)( p_dec );
148
149             vlc_object_release( p_sys->p_vout );
150         }
151
152         VCDSubInitSubtitleBlock ( p_sys );
153     }
154
155 }
156
157 /*****************************************************************************
158  * Packetize:
159  *****************************************************************************/
160 static block_t *
161 Packetize( decoder_t *p_dec, block_t **pp_block )
162 {
163     decoder_sys_t *p_sys = p_dec->p_sys;
164     block_t       *p_spu = Reassemble( p_dec, pp_block );
165
166     if( p_spu )
167     {
168         p_spu->i_dts = p_spu->i_pts;
169         p_spu->i_length = 0;
170
171         VCDSubInitSubtitleBlock( p_sys );
172
173         return block_ChainGather( p_spu );
174     }
175     return NULL;
176 }
177
178 /* following functions are local */
179
180 #define SPU_HEADER_LEN 1
181
182 /*****************************************************************************
183  Reassemble:
184
185  The data for single screen subtitle may come in one of many
186  non-contiguous packets of a stream. This routine is called when the
187  next packet in the stream comes in. The job of this routine is to
188  parse the header, if this is the beginning, and combine the packets
189  into one complete subtitle unit.
190
191  If everything is complete, we will return a block. Otherwise return
192  NULL.
193
194  *****************************************************************************/
195 static block_t *
196 Reassemble( decoder_t *p_dec, block_t **pp_block )
197 {
198     decoder_sys_t *p_sys = p_dec->p_sys;
199     block_t *p_block;
200     uint8_t *p_buffer;
201
202     if( pp_block == NULL || *pp_block == NULL )
203     {
204         return NULL;
205     }
206     p_block = *pp_block;
207     *pp_block = NULL;
208
209     if( p_block->i_buffer < SPU_HEADER_LEN )
210     {
211       msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
212                p_block->i_buffer, SPU_HEADER_LEN );
213       block_Release( p_block );
214       return NULL;
215     }
216
217     p_buffer = p_block->p_buffer;
218
219     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET), 
220                "header: 0x%02x 0x%02x 0x%02x 0x%02x, 0x%02x, 0x%02x, size: %i",
221                p_buffer[1], p_buffer[2], p_buffer[3], p_buffer[4],
222                p_buffer[5], p_buffer[6],
223                p_block->i_buffer);
224
225     if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[0] )
226       return NULL;
227
228     /* There is little data on the format, but it does not seem to have a
229        good way to detect the first packet in the subtitle.  It seems,
230        however, that it has a valid pts while later packets for the same
231        image don't */
232
233     if ( p_sys->state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == 0 ) {
234       msg_Warn( p_dec, 
235                 "first packet expected but no PTS present -- skipped\n");
236       return NULL;
237     }
238
239     if ( p_sys->subtitle_data_pos == 0 ) {
240       /* First packet in the subtitle block */
241       E_(ParseHeader)( p_dec, p_buffer, p_block );
242       VCDSubInitSubtitleData(p_sys);
243     }
244
245     /* FIXME - remove append_data and use chainappend */
246     VCDSubAppendData( p_dec, p_buffer, p_block->i_buffer - SPU_HEADER_LEN );
247
248     block_ChainAppend( &p_sys->p_block, p_block );
249
250     p_sys->i_spu += p_block->i_buffer - SPU_HEADER_LEN;
251
252     if ( p_sys->subtitle_data_pos == p_sys->i_spu_size ) {
253       /* last packet in subtitle block. */
254
255       uint8_t *p     = p_sys->subtitle_data + p_sys->metadata_offset+1;
256       uint8_t *p_end = p + p_sys->metadata_length;
257
258       dbg_print( (DECODE_DBG_PACKET),
259                  "subtitle packet complete, size=%d", p_sys->i_spu );
260
261       p_sys->state = SUBTITLE_BLOCK_COMPLETE;
262       p_sys->i_image++;
263
264
265       for ( ; p < p_end; p += 4 ) {
266
267         switch ( p[0] ) {
268           
269         case 0x04:      /* Display duration in 1/90000ths of a second */
270
271           p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
272           
273           dbg_print( DECODE_DBG_PACKET, 
274                      "subtitle display duration %u", p_sys->i_duration);
275           break;
276           
277         case 0x0c:      /* Unknown */
278           dbg_print( DECODE_DBG_PACKET, 
279                      "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x\n",
280                     p[0], p[1], p[2], p[3]);
281           break;
282           
283         case 0x17:      /* Position */
284           p_sys->i_x_start = ((p[1]&0x0f)<<6) + (p[2]>>2);
285           p_sys->i_y_start = ((p[2]&0x03)<<8) + p[3];
286           dbg_print( DECODE_DBG_PACKET, 
287                      "start position (%d,%d): %.2x %.2x %.2x", 
288                      p_sys->i_x_start, p_sys->i_y_start,
289                      p[1], p[2], p[3] );
290           break;
291           
292         case 0x1f:      /* Coordinates of the image bottom right */
293           {
294             int lastx = ((p[1]&0x0f)<<6) + (p[2]>>2);
295             int lasty = ((p[2]&0x03)<<8) + p[3];
296             p_sys->i_width  = lastx - p_sys->i_x_start + 1;
297             p_sys->i_height = lasty - p_sys->i_y_start + 1;
298             dbg_print( DECODE_DBG_PACKET, 
299                        "end position: (%d,%d): %.2x %.2x %.2x, w x h: %dx%d",
300                        lastx, lasty, p[1], p[2], p[3], 
301                        p_sys->i_width, p_sys->i_height );
302             break;
303           }
304           
305           
306         case 0x24:
307         case 0x25:
308         case 0x26:
309         case 0x27: 
310           {
311             uint8_t v = p[0]-0x24;
312             
313             /* Primary Palette */
314             dbg_print( DECODE_DBG_PACKET,
315                        "primary palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
316                        v, p[1], p[2], p[3]);
317             
318             p_sys->p_palette[v].s.y = p[1];
319             p_sys->p_palette[v].s.u = p[2];
320             p_sys->p_palette[v].s.v = p[3];
321             break;
322           }
323           
324           
325         case 0x2c:
326         case 0x2d:
327         case 0x2e:
328         case 0x2f:
329           {
330             uint8_t v = p[0]-0x2c;
331             
332             dbg_print( DECODE_DBG_PACKET,
333                        "highlight palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
334                        v, p[1], p[2], p[3]);
335             
336             /* Highlight Palette */
337             p_sys->p_palette_highlight[v].s.y = p[1];
338             p_sys->p_palette_highlight[v].s.u = p[2];
339             p_sys->p_palette_highlight[v].s.v = p[3];
340             break;
341           }
342
343         case 0x37:
344           /* transparency for primary palette */
345           p_sys->p_palette[0].s.t = p[3] & 0x0f;
346           p_sys->p_palette[1].s.t = p[3] >> 4;
347           p_sys->p_palette[2].s.t = p[2] & 0x0f;
348           p_sys->p_palette[3].s.t = p[2] >> 4;
349
350           dbg_print( DECODE_DBG_PACKET,
351                      "transparancy for primary palette 0..3: "
352                      "0x%0x 0x%0x 0x%0x 0x%0x",
353                      p_sys->p_palette[0].s.t,
354                      p_sys->p_palette[1].s.t,
355                      p_sys->p_palette[2].s.t,
356                      p_sys->p_palette[3].s.t );
357
358           break;
359
360         case 0x3f:
361           /* transparency for highlight palette */
362           p_sys->p_palette_highlight[0].s.t = p[2] & 0x0f;
363           p_sys->p_palette_highlight[1].s.t = p[2] >> 4;
364           p_sys->p_palette_highlight[2].s.t = p[1] & 0x0f;
365           p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
366
367           dbg_print( DECODE_DBG_PACKET,
368                      "transparancy for primary palette 0..3: "
369                      "0x%0x 0x%0x 0x%0x 0x%0x",
370                      p_sys->p_palette_highlight[0].s.t,
371                      p_sys->p_palette_highlight[1].s.t,
372                      p_sys->p_palette_highlight[2].s.t,
373                      p_sys->p_palette_highlight[3].s.t );
374
375           break;
376           
377         case 0x47:
378           /* offset to first field data, we correct to make it relative
379              to comp_image_offset (usually 4) */
380           p_sys->first_field_offset =
381             (p[2] << 8) + p[3] - p_sys->comp_image_offset;
382           dbg_print( DECODE_DBG_PACKET, 
383                      "first_field_offset %d", p_sys->first_field_offset);
384           break;
385           
386         case 0x4f:
387           /* offset to second field data, we correct to make it relative to
388              comp_image_offset (usually 4) */
389           p_sys->second_field_offset =
390             (p[2] << 8) + p[3] - p_sys->comp_image_offset;
391           dbg_print( DECODE_DBG_PACKET, 
392                      "second_field_offset %d", p_sys->second_field_offset);
393           break;
394           
395         default:
396           msg_Warn( p_dec, 
397                     "unknown sequence in control header " 
398                     "0x%0x 0x%0x 0x%0x 0x%0x",
399                     p[0], p[1], p[2], p[3]);
400           
401           p_sys->subtitle_data_pos = 0;
402         }
403       }
404       return p_sys->p_block;
405     } else {
406       /* Not last block in subtitle, so wait for another. */
407       p_sys->state = SUBTITLE_BLOCK_PARTIAL;
408     }
409
410     
411     return NULL;
412 }