Do not try to fix the font color attribute at the codec level.
[vlc/solaris.git] / modules / codec / schroedinger.c
blobc84d09bd235fb7f70dce847782180b875618d557
1 /*****************************************************************************
2 * schroedinger.c: Dirac decoder module making use of libschroedinger.
3 * (http://www.bbc.co.uk/rd/projects/dirac/index.shtml)
4 * (http://diracvideo.org)
5 *****************************************************************************
6 * Copyright (C) 2008-2010 the VideoLAN team
8 * Authors: Jonathan Rosser <jonathan.rosser@gmail.com>
9 * David Flynn <davidf at rd dot bbc.co.uk>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
27 * Preamble
28 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_sout.h>
38 #include <schroedinger/schro.h>
40 /*****************************************************************************
41 * Module descriptor
42 *****************************************************************************/
43 static int OpenDecoder ( vlc_object_t * );
44 static void CloseDecoder ( vlc_object_t * );
46 vlc_module_begin ()
47 set_category( CAT_INPUT )
48 set_subcategory( SUBCAT_INPUT_VCODEC )
49 set_shortname( "Schroedinger" )
50 set_description( N_("Dirac video decoder using libschroedinger") )
51 set_capability( "decoder", 200 )
52 set_callbacks( OpenDecoder, CloseDecoder )
53 add_shortcut( "schroedinger" )
54 vlc_module_end ()
56 /*****************************************************************************
57 * Local prototypes
58 *****************************************************************************/
59 static picture_t *DecodeBlock ( decoder_t *p_dec, block_t **pp_block );
61 struct picture_free_t
63 picture_t *p_pic;
64 decoder_t *p_dec;
67 /*****************************************************************************
68 * decoder_sys_t : Schroedinger decoder descriptor
69 *****************************************************************************/
70 struct decoder_sys_t
73 * Dirac properties
75 mtime_t i_lastpts;
76 mtime_t i_frame_pts_delta;
77 SchroDecoder *p_schro;
78 SchroVideoFormat *p_format;
81 /*****************************************************************************
82 * OpenDecoder: probe the decoder and return score
83 *****************************************************************************/
84 static int OpenDecoder( vlc_object_t *p_this )
86 decoder_t *p_dec = (decoder_t*)p_this;
87 decoder_sys_t *p_sys;
88 SchroDecoder *p_schro;
90 if( p_dec->fmt_in.i_codec != VLC_CODEC_DIRAC )
92 return VLC_EGENERIC;
95 /* Allocate the memory needed to store the decoder's structure */
96 p_sys = malloc(sizeof(decoder_sys_t));
97 if( p_sys == NULL )
98 return VLC_ENOMEM;
100 /* Initialise the schroedinger (and hence liboil libraries */
101 /* This does no allocation and is safe to call */
102 schro_init();
104 /* Initialise the schroedinger decoder */
105 if( !(p_schro = schro_decoder_new()) )
107 free( p_sys );
108 return VLC_EGENERIC;
111 p_dec->p_sys = p_sys;
112 p_sys->p_schro = p_schro;
113 p_sys->p_format = NULL;
114 p_sys->i_lastpts = VLC_TS_INVALID;
115 p_sys->i_frame_pts_delta = 0;
117 /* Set output properties */
118 p_dec->fmt_out.i_cat = VIDEO_ES;
119 p_dec->fmt_out.i_codec = VLC_CODEC_I420;
121 /* Set callbacks */
122 p_dec->pf_decode_video = DecodeBlock;
124 return VLC_SUCCESS;
127 /*****************************************************************************
128 * SetPictureFormat: Set the decoded picture params to the ones from the stream
129 *****************************************************************************/
130 static void SetVideoFormat( decoder_t *p_dec )
132 decoder_sys_t *p_sys = p_dec->p_sys;
134 p_sys->p_format = schro_decoder_get_video_format(p_sys->p_schro);
135 if( p_sys->p_format == NULL ) return;
137 p_sys->i_frame_pts_delta = INT64_C(1000000)
138 * p_sys->p_format->frame_rate_denominator
139 / p_sys->p_format->frame_rate_numerator;
141 switch( p_sys->p_format->chroma_format )
143 case SCHRO_CHROMA_420: p_dec->fmt_out.i_codec = VLC_CODEC_I420; break;
144 case SCHRO_CHROMA_422: p_dec->fmt_out.i_codec = VLC_CODEC_I422; break;
145 case SCHRO_CHROMA_444: p_dec->fmt_out.i_codec = VLC_CODEC_I444; break;
146 default:
147 p_dec->fmt_out.i_codec = 0;
148 break;
151 p_dec->fmt_out.video.i_visible_width = p_sys->p_format->clean_width;
152 p_dec->fmt_out.video.i_x_offset = p_sys->p_format->left_offset;
153 p_dec->fmt_out.video.i_width = p_sys->p_format->width;
155 p_dec->fmt_out.video.i_visible_height = p_sys->p_format->clean_height;
156 p_dec->fmt_out.video.i_y_offset = p_sys->p_format->top_offset;
157 p_dec->fmt_out.video.i_height = p_sys->p_format->height;
159 /* aspect_ratio_[numerator|denominator] describes the pixel aspect ratio */
160 p_dec->fmt_out.video.i_sar_num = p_sys->p_format->aspect_ratio_numerator;
161 p_dec->fmt_out.video.i_sar_den = p_sys->p_format->aspect_ratio_denominator;
163 p_dec->fmt_out.video.i_frame_rate =
164 p_sys->p_format->frame_rate_numerator;
165 p_dec->fmt_out.video.i_frame_rate_base =
166 p_sys->p_format->frame_rate_denominator;
169 /*****************************************************************************
170 * SchroFrameFree: schro_frame callback to release the associated picture_t
171 * When schro_decoder_reset() is called there will be pictures in the
172 * decoding pipeline that need to be released rather than displayed.
173 *****************************************************************************/
174 static void SchroFrameFree( SchroFrame *frame, void *priv)
176 struct picture_free_t *p_free = priv;
178 if( !p_free )
179 return;
181 decoder_DeletePicture( p_free->p_dec, p_free->p_pic );
182 free(p_free);
183 (void)frame;
186 /*****************************************************************************
187 * CreateSchroFrameFromPic: wrap a picture_t in a SchroFrame
188 *****************************************************************************/
189 static SchroFrame *CreateSchroFrameFromPic( decoder_t *p_dec )
191 decoder_sys_t *p_sys = p_dec->p_sys;
192 SchroFrame *p_schroframe = schro_frame_new();
193 picture_t *p_pic = NULL;
194 struct picture_free_t *p_free;
196 if( !p_schroframe )
197 return NULL;
199 p_pic = decoder_NewPicture( p_dec );
201 if( !p_pic )
202 return NULL;
204 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_420;
205 if( p_sys->p_format->chroma_format == SCHRO_CHROMA_422 )
207 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_422;
209 else if( p_sys->p_format->chroma_format == SCHRO_CHROMA_444 )
211 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_444;
214 p_schroframe->width = p_sys->p_format->width;
215 p_schroframe->height = p_sys->p_format->height;
217 p_free = malloc( sizeof( *p_free ) );
218 p_free->p_pic = p_pic;
219 p_free->p_dec = p_dec;
220 schro_frame_set_free_callback( p_schroframe, SchroFrameFree, p_free );
222 for( int i=0; i<3; i++ )
224 p_schroframe->components[i].width = p_pic->p[i].i_visible_pitch;
225 p_schroframe->components[i].stride = p_pic->p[i].i_pitch;
226 p_schroframe->components[i].height = p_pic->p[i].i_visible_lines;
227 p_schroframe->components[i].length =
228 p_pic->p[i].i_pitch * p_pic->p[i].i_lines;
229 p_schroframe->components[i].data = p_pic->p[i].p_pixels;
231 if(i!=0)
233 p_schroframe->components[i].v_shift =
234 SCHRO_FRAME_FORMAT_V_SHIFT( p_schroframe->format );
235 p_schroframe->components[i].h_shift =
236 SCHRO_FRAME_FORMAT_H_SHIFT( p_schroframe->format );
240 p_pic->b_progressive = !p_sys->p_format->interlaced;
241 p_pic->b_top_field_first = p_sys->p_format->top_field_first;
242 p_pic->i_nb_fields = 2;
244 return p_schroframe;
247 /*****************************************************************************
248 * SchroBufferFree: schro_buffer callback to release the associated block_t
249 *****************************************************************************/
250 static void SchroBufferFree( SchroBuffer *buf, void *priv )
252 block_t *p_block = priv;
254 if( !p_block )
255 return;
257 block_Release( p_block );
258 (void)buf;
261 /*****************************************************************************
262 * CloseDecoder: decoder destruction
263 *****************************************************************************/
264 static void CloseDecoder( vlc_object_t *p_this )
266 decoder_t *p_dec = (decoder_t *)p_this;
267 decoder_sys_t *p_sys = p_dec->p_sys;
269 schro_decoder_free( p_sys->p_schro );
270 free( p_sys );
273 /****************************************************************************
274 * DecodeBlock: the whole thing
275 ****************************************************************************
276 * Blocks need not be Dirac dataunit aligned.
277 * If a block has a PTS signaled, it applies to the first picture at or after p_block
279 * If this function returns a picture (!NULL), it is called again and the
280 * same block is resubmitted. To avoid this, set *pp_block to NULL;
281 * If this function returns NULL, the *pp_block is lost (and leaked).
282 * This function must free all blocks when finished with them.
283 ****************************************************************************/
284 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
286 decoder_sys_t *p_sys = p_dec->p_sys;
288 if( !pp_block ) return NULL;
290 if ( *pp_block ) {
291 block_t *p_block = *pp_block;
293 /* reset the decoder when seeking as the decode in progress is invalid */
294 /* discard the block as it is just a null magic block */
295 if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) {
296 schro_decoder_reset( p_sys->p_schro );
298 p_sys->i_lastpts = VLC_TS_INVALID;
299 block_Release( p_block );
300 *pp_block = NULL;
301 return NULL;
304 SchroBuffer *p_schrobuffer;
305 p_schrobuffer = schro_buffer_new_with_data( p_block->p_buffer, p_block->i_buffer );
306 p_schrobuffer->free = SchroBufferFree;
307 p_schrobuffer->priv = p_block;
308 if( p_block->i_pts > VLC_TS_INVALID ) {
309 mtime_t *p_pts = malloc( sizeof(*p_pts) );
310 if( p_pts ) {
311 *p_pts = p_block->i_pts;
312 /* if this call fails, p_pts is freed automatically */
313 p_schrobuffer->tag = schro_tag_new( p_pts, free );
317 /* this stops the same block being fed back into this function if
318 * we were on the next iteration of this loop to output a picture */
319 *pp_block = NULL;
320 schro_decoder_autoparse_push( p_sys->p_schro, p_schrobuffer );
321 /* DO NOT refer to p_block after this point, it may have been freed */
324 while( 1 )
326 SchroFrame *p_schroframe;
327 picture_t *p_pic;
328 int state = schro_decoder_autoparse_wait( p_sys->p_schro );
330 switch( state )
332 case SCHRO_DECODER_FIRST_ACCESS_UNIT:
333 SetVideoFormat( p_dec );
334 break;
336 case SCHRO_DECODER_NEED_BITS:
337 return NULL;
339 case SCHRO_DECODER_NEED_FRAME:
340 p_schroframe = CreateSchroFrameFromPic( p_dec );
342 if( !p_schroframe )
344 msg_Err( p_dec, "Could not allocate picture for decoder");
345 return NULL;
348 schro_decoder_add_output_picture( p_sys->p_schro, p_schroframe);
349 break;
351 case SCHRO_DECODER_OK: {
352 SchroTag *p_tag = schro_decoder_get_picture_tag( p_sys->p_schro );
353 p_schroframe = schro_decoder_pull( p_sys->p_schro );
354 if( !p_schroframe || !p_schroframe->priv )
356 /* frame can't be one that was allocated by us
357 * -- no private data: discard */
358 if( p_tag ) schro_tag_free( p_tag );
359 if( p_schroframe ) schro_frame_unref( p_schroframe );
360 break;
362 p_pic = ((struct picture_free_t*) p_schroframe->priv)->p_pic;
363 p_schroframe->priv = NULL;
365 if( p_tag )
367 /* free is handled by schro_frame_unref */
368 p_pic->date = *(mtime_t*) p_tag->value;
369 schro_tag_free( p_tag );
371 else if( p_sys->i_lastpts > VLC_TS_INVALID )
373 /* NB, this shouldn't happen since the packetizer does a
374 * very thorough job of inventing timestamps. The
375 * following is just a very rough fall back incase packetizer
376 * is missing. */
377 /* maybe it would be better to set p_pic->b_force ? */
378 p_pic->date = p_sys->i_lastpts + p_sys->i_frame_pts_delta;
380 p_sys->i_lastpts = p_pic->date;
382 schro_frame_unref( p_schroframe );
383 return p_pic;
385 case SCHRO_DECODER_EOS:
386 /* NB, the new api will not emit _EOS, it handles the reset internally */
387 break;
389 case SCHRO_DECODER_ERROR:
390 msg_Err( p_dec, "SCHRO_DECODER_ERROR");
391 return NULL;