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 /*****************************************************************************
28 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
38 #include <schroedinger/schro.h>
40 /*****************************************************************************
42 *****************************************************************************/
43 static int OpenDecoder ( vlc_object_t
* );
44 static void CloseDecoder ( vlc_object_t
* );
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" )
56 /*****************************************************************************
58 *****************************************************************************/
59 static picture_t
*DecodeBlock ( decoder_t
*p_dec
, block_t
**pp_block
);
67 /*****************************************************************************
68 * decoder_sys_t : Schroedinger decoder descriptor
69 *****************************************************************************/
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
;
88 SchroDecoder
*p_schro
;
90 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_DIRAC
)
95 /* Allocate the memory needed to store the decoder's structure */
96 p_sys
= malloc(sizeof(decoder_sys_t
));
100 /* Initialise the schroedinger (and hence liboil libraries */
101 /* This does no allocation and is safe to call */
104 /* Initialise the schroedinger decoder */
105 if( !(p_schro
= schro_decoder_new()) )
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
;
122 p_dec
->pf_decode_video
= DecodeBlock
;
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;
147 p_dec
->fmt_out
.i_codec
= 0;
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
;
181 decoder_DeletePicture( p_free
->p_dec
, p_free
->p_pic
);
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
;
199 p_pic
= decoder_NewPicture( p_dec
);
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
;
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;
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
;
257 block_Release( p_block
);
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
);
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
;
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
);
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
) );
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 */
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 */
326 SchroFrame
*p_schroframe
;
328 int state
= schro_decoder_autoparse_wait( p_sys
->p_schro
);
332 case SCHRO_DECODER_FIRST_ACCESS_UNIT
:
333 SetVideoFormat( p_dec
);
336 case SCHRO_DECODER_NEED_BITS
:
339 case SCHRO_DECODER_NEED_FRAME
:
340 p_schroframe
= CreateSchroFrameFromPic( p_dec
);
344 msg_Err( p_dec
, "Could not allocate picture for decoder");
348 schro_decoder_add_output_picture( p_sys
->p_schro
, p_schroframe
);
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
);
362 p_pic
= ((struct picture_free_t
*) p_schroframe
->priv
)->p_pic
;
363 p_schroframe
->priv
= NULL
;
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
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
);
385 case SCHRO_DECODER_EOS
:
386 /* NB, the new api will not emit _EOS, it handles the reset internally */
389 case SCHRO_DECODER_ERROR
:
390 msg_Err( p_dec
, "SCHRO_DECODER_ERROR");