ogt.c cvd.c, subtitle.h: move common debug string help into subtitle.h
[vlc.git] / modules / codec / ogt / ogt.c
1 /*****************************************************************************
2  * ogt.c : Overlay Graphics Text (SVCD subtitles) decoder thread
3  *****************************************************************************
4  * Copyright (C) 2003, 2004 VideoLAN
5  * $Id: ogt.c,v 1.8 2004/01/03 12:54:56 rocky Exp $
6  *
7  * Author: 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 "ogt.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( _("Philips OGT (SVCD 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( _("Philips OGT (SVCD 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( 'o','g','t',' ' ) )
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( 'o','g','t',' ' ) );
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 #define SPU_HEADER_LEN 5
179
180 /*****************************************************************************
181  Reassemble:
182
183  The data for single screen subtitle may come in one of many
184  non-contiguous packets of a stream. This routine is called when the
185  next packet in the stream comes in. The job of this routine is to
186  parse the header, if this is the beginning, and combine the packets
187  into one complete subtitle unit.
188
189  If everything is complete, we will return a block. Otherwise return
190  NULL.
191
192
193  The format of the beginning of the subtitle packet that is used here.
194
195    size    description
196    -------------------------------------------
197    byte    subtitle channel (0..7) in bits 0-3
198    byte    subtitle packet number of this subtitle image 0-N,
199            if the subtitle packet is complete, the top bit of the byte is 1.
200    uint16  subtitle image number
201
202  *****************************************************************************/
203 static block_t *
204 Reassemble( decoder_t *p_dec, block_t **pp_block )
205 {
206     decoder_sys_t *p_sys = p_dec->p_sys;
207     block_t *p_block;
208     uint8_t *p_buffer;
209     uint16_t i_expected_image;
210     uint8_t  i_packet, i_expected_packet;
211
212     if( pp_block == NULL || *pp_block == NULL )
213     {
214         return NULL;
215     }
216     p_block = *pp_block;
217     *pp_block = NULL;
218
219     if( p_block->i_buffer < SPU_HEADER_LEN )
220     {
221       msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
222                p_block->i_buffer, SPU_HEADER_LEN );
223       block_Release( p_block );
224       return NULL;
225     }
226
227     p_buffer = p_block->p_buffer;
228
229     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET), 
230                "header: 0x%02x 0x%02x 0x%02x 0x%02x, size: %i",
231                p_buffer[1], p_buffer[2], p_buffer[3], p_buffer[4],
232                p_block->i_buffer);
233
234     if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[1] )
235       return NULL;
236
237     if ( p_sys->state == SUBTITLE_BLOCK_EMPTY ) {
238       i_expected_image  = p_sys->i_image+1;
239       i_expected_packet = 0;
240     } else {
241       i_expected_image  = p_sys->i_image;
242       i_expected_packet = p_sys->i_packet+1;
243     }
244
245     p_buffer += 2;
246
247     if ( *p_buffer & 0x80 ) {
248       p_sys->state = SUBTITLE_BLOCK_COMPLETE;
249       i_packet     = ( *p_buffer++ & 0x7F );
250     } else {
251       p_sys->state = SUBTITLE_BLOCK_PARTIAL;
252       i_packet     = *p_buffer++;
253     }
254
255     p_sys->i_image = GETINT16(p_buffer);
256
257     if ( p_sys->i_image != i_expected_image ) {
258       msg_Warn( p_dec, "expecting subtitle image %u but found %u",
259                 i_expected_image, p_sys->i_image );
260     }
261
262     if ( i_packet != i_expected_packet ) {
263       msg_Warn( p_dec, "expecting subtitle image packet %u but found %u",
264                 i_expected_packet, i_packet);
265     }
266
267     p_sys->i_packet = i_packet;
268
269     if ( p_sys->i_packet == 0 ) {
270       /* First packet in the subtitle block */
271       E_(ParseHeader)( p_dec, p_buffer, p_block );
272       VCDSubInitSubtitleData(p_sys);
273     }
274
275     /* FIXME - remove append_data and use chainappend */
276     VCDSubAppendData( p_dec, p_buffer, p_block->i_buffer - SPU_HEADER_LEN );
277
278     block_ChainAppend( &p_sys->p_block, p_block );
279
280     p_sys->i_spu += p_block->i_buffer - SPU_HEADER_LEN;
281
282     if (p_sys->state == SUBTITLE_BLOCK_COMPLETE)
283     {
284       if( p_sys->i_spu != p_sys->i_spu_size )
285         {
286           msg_Warn( p_dec, "SPU packets size=%d should be %d",
287                    p_sys->i_spu, p_sys->i_spu_size );
288         }
289
290       dbg_print( (DECODE_DBG_PACKET),
291                  "subtitle packet complete, size=%d", p_sys->i_spu );
292
293       return p_sys->p_block;
294     }
295     return NULL;
296 }