]> git.sesse.net Git - vlc/blob - modules/codec/ogt/ogt.c
* ffmpeg.c: disabled mpeg4 audio, too buggy. (This way users can see that
[vlc] / 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.11 2004/01/16 13:32:37 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                   DEBUG_LONGTEXT, VLC_TRUE );
53
54     add_integer ( MODULE_STRING "-horizontal-correct", 0, NULL,
55                   HORIZONTAL_CORRECT, HORIZONTAL_CORRECT_LONGTEXT, VLC_FALSE );
56
57     add_integer ( MODULE_STRING "-vertical-correct", 0, NULL,
58                   VERTICAL_CORRECT, VERTICAL_CORRECT_LONGTEXT, VLC_FALSE );
59
60     add_string( MODULE_STRING "-aspect-ratio", "", NULL,
61                 SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT, 
62                 VLC_TRUE );
63
64     add_integer( MODULE_STRING "-duration-scaling", 9, NULL,
65                  DURATION_SCALE_TEXT, DURATION_SCALE_LONGTEXT,
66                  VLC_TRUE );
67
68     add_submodule();
69     set_description( _("Philips OGT (SVCD subtitle) packetizer") );
70     set_capability( "packetizer", 50 );
71     set_callbacks( PacketizerOpen, VCDSubClose );
72 vlc_module_end();
73
74 /*****************************************************************************
75  * Local prototypes
76  *****************************************************************************/
77
78 static block_t *Reassemble( decoder_t *, block_t ** );
79 static void     Decode   ( decoder_t *, block_t ** );
80 static block_t *Packetize( decoder_t *, block_t ** );
81
82
83 /*****************************************************************************
84  * DecoderOpen
85  *****************************************************************************
86  * Tries to launch a decoder and return score so that the interface is able
87  * to chose.
88  *****************************************************************************/
89 static int
90 DecoderOpen( vlc_object_t *p_this )
91 {
92     decoder_t     *p_dec = (decoder_t*)p_this;
93     decoder_sys_t *p_sys;
94
95     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
96     {
97         return VLC_EGENERIC;
98     }
99
100
101     p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
102
103     p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
104     p_sys->b_packetizer  = VLC_FALSE;
105     p_sys->p_vout        = NULL;
106     p_sys->i_image       = -1;
107     p_sys->subtitle_data = NULL;
108
109     VCDSubInitSubtitleBlock( p_sys );
110
111     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
112
113
114     p_dec->pf_decode_sub = Decode;
115     p_dec->pf_packetize  = Packetize;
116
117     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
118
119     return VLC_SUCCESS;
120 }
121
122 /*****************************************************************************
123  * PacketizerOpen
124  *****************************************************************************
125  * Tries to launch a decoder and return score so that the interface is able
126  * to chose.
127  *****************************************************************************/
128 static int PacketizerOpen( vlc_object_t *p_this )
129 {
130     decoder_t *p_dec = (decoder_t*)p_this;
131
132     if( DecoderOpen( p_this ) )
133     {
134         return VLC_EGENERIC;
135     }
136     p_dec->p_sys->b_packetizer = VLC_TRUE;
137
138     return VLC_SUCCESS;
139 }
140
141 /*****************************************************************************
142  * Decode:
143  *****************************************************************************/
144 static void
145 Decode ( decoder_t *p_dec, block_t **pp_block )
146 {
147     decoder_sys_t *p_sys = p_dec->p_sys;
148     block_t       *p_spu = Reassemble( p_dec, pp_block );
149
150     dbg_print( (DECODE_DBG_CALL) , "");
151
152     if( p_spu )
153     {
154         p_sys->i_spu = block_ChainExtract( p_spu, p_sys->buffer, 65536 );
155         p_sys->i_pts = p_spu->i_pts;
156         block_ChainRelease( p_spu );
157
158         if( ( p_sys->p_vout = VCDSubFindVout( p_dec ) ) )
159         {
160             /* Parse and decode */
161             E_(ParsePacket)( p_dec );
162
163             vlc_object_release( p_sys->p_vout );
164         }
165
166         VCDSubInitSubtitleBlock ( p_sys );
167     }
168
169 }
170
171 /*****************************************************************************
172  * Packetize:
173  *****************************************************************************/
174 static block_t *
175 Packetize( decoder_t *p_dec, block_t **pp_block )
176 {
177     decoder_sys_t *p_sys = p_dec->p_sys;
178     block_t       *p_spu = Reassemble( p_dec, pp_block );
179
180     if( p_spu )
181     {
182         p_spu->i_dts = p_spu->i_pts;
183         p_spu->i_length = 0;
184
185         VCDSubInitSubtitleBlock( p_sys );
186
187         return block_ChainGather( p_spu );
188     }
189     return NULL;
190 }
191
192 #define SPU_HEADER_LEN 5
193
194 /*****************************************************************************
195  Reassemble:
196
197  The data for single screen subtitle may come in one of many
198  non-contiguous packets of a stream. This routine is called when the
199  next packet in the stream comes in. The job of this routine is to
200  parse the header, if this is the beginning, and combine the packets
201  into one complete subtitle unit.
202
203  If everything is complete, we will return a block. Otherwise return
204  NULL.
205
206
207  The format of the beginning of the subtitle packet that is used here.
208
209    size    description
210    -------------------------------------------
211    byte    subtitle channel (0..7) in bits 0-3
212    byte    subtitle packet number of this subtitle image 0-N,
213            if the subtitle packet is complete, the top bit of the byte is 1.
214    uint16  subtitle image number
215
216  *****************************************************************************/
217 static block_t *
218 Reassemble( decoder_t *p_dec, block_t **pp_block )
219 {
220     decoder_sys_t *p_sys = p_dec->p_sys;
221     block_t *p_block;
222     uint8_t *p_buffer;
223     uint16_t i_expected_image;
224     uint8_t  i_packet, i_expected_packet;
225
226     if( pp_block == NULL || *pp_block == NULL )
227     {
228         return NULL;
229     }
230     p_block = *pp_block;
231     *pp_block = NULL;
232
233     if( p_block->i_buffer < SPU_HEADER_LEN )
234     {
235       msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
236                p_block->i_buffer, SPU_HEADER_LEN );
237       block_Release( p_block );
238       return NULL;
239     }
240
241     p_buffer = p_block->p_buffer;
242
243     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET), 
244                "header: 0x%02x 0x%02x 0x%02x 0x%02x, size: %i",
245                p_buffer[1], p_buffer[2], p_buffer[3], p_buffer[4],
246                p_block->i_buffer);
247
248     if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[1] )
249       return NULL;
250
251     if ( p_sys->state == SUBTITLE_BLOCK_EMPTY ) {
252       i_expected_image  = p_sys->i_image+1;
253       i_expected_packet = 0;
254     } else {
255       i_expected_image  = p_sys->i_image;
256       i_expected_packet = p_sys->i_packet+1;
257     }
258
259     p_buffer += 2;
260
261     if ( *p_buffer & 0x80 ) {
262       p_sys->state = SUBTITLE_BLOCK_COMPLETE;
263       i_packet     = ( *p_buffer++ & 0x7F );
264     } else {
265       p_sys->state = SUBTITLE_BLOCK_PARTIAL;
266       i_packet     = *p_buffer++;
267     }
268
269     p_sys->i_image = GETINT16(p_buffer);
270
271     if ( p_sys->i_image != i_expected_image ) {
272       msg_Warn( p_dec, "expecting subtitle image %u but found %u",
273                 i_expected_image, p_sys->i_image );
274     }
275
276     if ( i_packet != i_expected_packet ) {
277       msg_Warn( p_dec, "expecting subtitle image packet %u but found %u",
278                 i_expected_packet, i_packet);
279     }
280
281     p_sys->i_packet = i_packet;
282
283     if ( p_sys->i_packet == 0 ) {
284       /* First packet in the subtitle block */
285       E_(ParseHeader)( p_dec, p_buffer, p_block );
286       VCDSubInitSubtitleData(p_sys);
287     }
288
289     /* FIXME - remove append_data and use chainappend */
290     VCDSubAppendData( p_dec, p_buffer, p_block->i_buffer - SPU_HEADER_LEN );
291
292     block_ChainAppend( &p_sys->p_block, p_block );
293
294     p_sys->i_spu += p_block->i_buffer - SPU_HEADER_LEN;
295
296     if (p_sys->state == SUBTITLE_BLOCK_COMPLETE)
297     {
298       if( p_sys->i_spu != p_sys->i_spu_size )
299         {
300           msg_Warn( p_dec, "SPU packets size=%d should be %d",
301                    p_sys->i_spu, p_sys->i_spu_size );
302         }
303
304       dbg_print( (DECODE_DBG_PACKET),
305                  "subtitle packet complete, size=%d", p_sys->i_spu );
306
307       return p_sys->p_block;
308     }
309     return NULL;
310 }
311
312 \f
313 /* 
314  * Local variables:
315  *  c-file-style: "gnu"
316  *  tab-width: 8
317  *  indent-tabs-mode: nil
318  * End:
319  */