]> git.sesse.net Git - vlc/blob - modules/codec/tarkin.c
More alignments fixes in configure.ac
[vlc] / modules / codec / tarkin.c
1 /*****************************************************************************
2  * tarkin.c: tarkin decoder module making use of libtarkin.
3  *****************************************************************************
4  * Copyright (C) 2001-2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <ogg/ogg.h>
35
36 /* FIXME */
37 // use 16 bit signed integers as wavelet coefficients
38 #define TYPE int16_t
39 // we'll actually use TYPE_BITS bits of type (e.g. 9 magnitude + 1 sign)
40 #define TYPE_BITS 10
41 // use the rle entropy coder
42 #define RLECODER 1
43
44 #include <tarkin.h>
45
46 /*****************************************************************************
47  * decoder_sys_t : tarkin decoder descriptor
48  *****************************************************************************/
49 struct decoder_sys_t
50 {
51     /*
52      * Tarkin properties
53      */
54     TarkinStream *tarkin_stream;
55
56     TarkinInfo       ti;                        /* tarkin bitstream settings */
57     TarkinComment    tc;                   /* tarkin bitstream user comments */
58     TarkinTime       tarkdate;
59
60     int i_headers;
61     mtime_t i_pts;
62 };
63
64 /*****************************************************************************
65  * Local prototypes
66  *****************************************************************************/
67 static int  OpenDecoder  ( vlc_object_t * );
68 static void CloseDecoder ( vlc_object_t * );
69
70 static void *DecodeBlock ( decoder_t *, block_t ** );
71 static picture_t *DecodePacket ( decoder_t *, block_t **, ogg_packet * );
72
73 static void tarkin_CopyPicture( decoder_t *, picture_t *, uint8_t *, int );
74
75 /*****************************************************************************
76  * Module descriptor
77  *****************************************************************************/
78 vlc_module_begin ()
79     set_description( N_("Tarkin decoder") )
80     set_capability( "decoder", 100 )
81     set_category( CAT_INPUT )
82     set_subcategory( SUBCAT_INPUT_VCODEC )
83     set_callbacks( OpenDecoder, CloseDecoder )
84     add_shortcut( "tarkin" )
85 vlc_module_end ()
86
87 /*****************************************************************************
88  * OpenDecoder: probe the decoder and return score
89  *****************************************************************************/
90 static int OpenDecoder( 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_CODEC_TARKIN )
96     {
97         return VLC_EGENERIC;
98     }
99
100     /* Allocate the memory needed to store the decoder's structure */
101     if( ( p_dec->p_sys = p_sys =
102           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
103         return VLC_ENOMEM;
104
105     /* Set output properties */
106     p_dec->fmt_out.i_cat = VIDEO_ES;
107     p_sys->i_headers = 0;
108
109     /* Set callbacks */
110     p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
111         DecodeBlock;
112     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
113         DecodeBlock;
114
115     /* Init supporting Tarkin structures needed in header parsing */
116     p_sys->tarkin_stream = tarkin_stream_new();
117     tarkin_info_init( &p_sys->ti );
118     tarkin_comment_init( &p_sys->tc );
119
120     return VLC_SUCCESS;
121 }
122
123 /****************************************************************************
124  * DecodeBlock: the whole thing
125  ****************************************************************************
126  * This function must be fed with ogg packets.
127  ****************************************************************************/
128 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
129 {
130     decoder_sys_t *p_sys = p_dec->p_sys;
131     block_t *p_block;
132     ogg_packet oggpacket;
133
134     if( !pp_block ) return NULL;
135
136     if( *pp_block )
137     {
138         /* Block to Ogg packet */
139         oggpacket.packet = (*pp_block)->p_buffer;
140         oggpacket.bytes = (*pp_block)->i_buffer;
141     }
142     else
143     {
144         /* Block to Ogg packet */
145         oggpacket.packet = NULL;
146         oggpacket.bytes = 0;
147     }
148
149     p_block = *pp_block;
150
151     oggpacket.granulepos = -1;
152     oggpacket.b_o_s = 0;
153     oggpacket.e_o_s = 0;
154     oggpacket.packetno = 0;
155
156     if( p_sys->i_headers == 0 )
157     {
158         /* Take care of the initial Tarkin header */
159
160         oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
161         if( tarkin_synthesis_headerin( &p_sys->ti, &p_sys->tc, &oggpacket )
162             < 0 )
163         {
164             msg_Err( p_dec, "this bitstream does not contain Tarkin "
165                      "video data.");
166             block_Release( p_block );
167             return NULL;
168         }
169         p_sys->i_headers++;
170
171         block_Release( p_block );
172         return NULL;
173     }
174
175     if( p_sys->i_headers == 1 )
176     {
177         if( tarkin_synthesis_headerin( &p_sys->ti, &p_sys->tc, &oggpacket )
178             < 0 )
179         {
180             msg_Err( p_dec, "2nd Tarkin header is corrupted." );
181             block_Release( p_block );
182             return NULL;
183         }
184         p_sys->i_headers++;
185         block_Release( p_block );
186         return NULL;
187     }
188
189     if( p_sys->i_headers == 2 )
190     {
191         if( tarkin_synthesis_headerin( &p_sys->ti, &p_sys->tc, &oggpacket )
192             < 0 )
193         {
194             msg_Err( p_dec, "3rd Tarkin header is corrupted." );
195             block_Release( p_block );
196             return NULL;
197         }
198         p_sys->i_headers++;
199
200         /* Initialize the tarkin decoder */
201         tarkin_synthesis_init( p_sys->tarkin_stream, &p_sys->ti );
202
203         msg_Err( p_dec, "Tarkin codec initialized");
204
205         block_Release( p_block );
206         return NULL;
207     }
208
209     return DecodePacket( p_dec, pp_block, &oggpacket );
210 }
211
212 /*****************************************************************************
213  * DecodePacket: decodes a Tarkin packet.
214  *****************************************************************************/
215 static picture_t *DecodePacket( decoder_t *p_dec, block_t **pp_block,
216                                 ogg_packet *p_oggpacket )
217 {
218     decoder_sys_t *p_sys = p_dec->p_sys;
219     uint8_t *rgb;
220
221     if( p_oggpacket->bytes )
222     {
223         tarkin_synthesis_packetin( p_sys->tarkin_stream, p_oggpacket );
224         //block_Release( *pp_block ); /* FIXME duplicate packet */
225         *pp_block = NULL;
226     }
227
228     if( tarkin_synthesis_frameout( p_sys->tarkin_stream,
229                                    &rgb, 0, &p_sys->tarkdate ) == 0 )
230     {
231         int i_width, i_height, i_chroma, i_stride;
232         picture_t *p_pic;
233
234         msg_Err( p_dec, "Tarkin frame decoded" );
235
236         i_width = p_sys->tarkin_stream->layer->desc.width;
237         i_height = p_sys->tarkin_stream->layer->desc.height;
238
239         switch( p_sys->tarkin_stream->layer->desc.format )
240         {
241         case TARKIN_RGB24:
242             i_chroma = VLC_CODEC_RGB24;
243             i_stride = i_width * 3;
244             break;
245         case TARKIN_RGB32:
246             i_chroma = VLC_CODEC_RGB32;
247             i_stride = i_width * 4;
248             break;
249         case TARKIN_RGBA:
250             i_chroma = VLC_CODEC_RGBA;
251             i_stride = i_width * 4;
252             break;
253         default:
254             i_chroma = VLC_CODEC_I420;
255             i_stride = i_width;
256             break;
257         }
258
259         /* Set output properties */
260         p_dec->fmt_out.video.i_width = i_width;
261         p_dec->fmt_out.video.i_height = i_height;
262
263         p_dec->fmt_out.video.i_sar_num = 1;
264         p_dec->fmt_out.video.i_sar_den = 1;
265         p_dec->fmt_out.i_codec = i_chroma;
266
267         /* Get a new picture */
268         if( (p_pic = decoder_NewPicture( p_dec )) )
269         {
270             tarkin_CopyPicture( p_dec, p_pic, rgb, i_stride );
271
272             tarkin_synthesis_freeframe( p_sys->tarkin_stream, rgb );
273
274             p_pic->date = mdate() + DEFAULT_PTS_DELAY/*i_pts*/;
275
276             return p_pic;
277         }
278     }
279
280     return NULL;
281 }
282
283 /*****************************************************************************
284  * CloseDecoder: tarkin decoder destruction
285  *****************************************************************************/
286 static void CloseDecoder( vlc_object_t *p_this )
287 {
288     decoder_t *p_dec = (decoder_t *)p_this;
289     decoder_sys_t *p_sys = p_dec->p_sys;
290
291     tarkin_stream_destroy( p_sys->tarkin_stream );
292
293     free( p_sys );
294 }
295
296 /*****************************************************************************
297  * tarkin_CopyPicture: copy a picture from tarkin internal buffers to a
298  *                     picture_t structure.
299  *****************************************************************************/
300 static void tarkin_CopyPicture( decoder_t *p_dec, picture_t *p_pic,
301                                 uint8_t *p_src, int i_pitch )
302 {
303     int i_plane, i_line, i_src_stride, i_dst_stride;
304     uint8_t *p_dst;
305
306     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
307     {
308         p_dst = p_pic->p[i_plane].p_pixels;
309         i_dst_stride = p_pic->p[i_plane].i_pitch;
310         i_src_stride = i_pitch;
311
312         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
313         {
314             vlc_memcpy( p_dst, p_src, i_src_stride );
315
316             p_src += i_src_stride;
317             p_dst += i_dst_stride;
318         }
319     }
320 }