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 the VideoLAN team
9 * Authors: Jonathan Rosser <jonathan.rosser@gmail.com>
10 * David Flynn <davidf at rd dot bbc.co.uk>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_codec.h>
41 #include <schroedinger/schro.h>
43 /*****************************************************************************
45 *****************************************************************************/
46 static int OpenDecoder ( vlc_object_t
* );
47 static void CloseDecoder ( vlc_object_t
* );
48 static int OpenEncoder ( vlc_object_t
* );
49 static void CloseEncoder ( vlc_object_t
* );
51 #define ENC_CFG_PREFIX "sout-schro-"
53 #define ENC_CHROMAFMT "chroma_fmt"
54 #define ENC_CHROMAFMT_TEXT N_("Chroma format")
55 #define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
56 "conversion of the video into that format")
57 static const char *const enc_chromafmt_list
[] =
58 { "420", "422", "444" };
59 static const char *const enc_chromafmt_list_text
[] =
60 { N_("4:2:0"), N_("4:2:2"), N_("4:4:4") };
62 #define ENC_RATE_CONTROL "rate_control"
63 #define ENC_RATE_CONTROL_TEXT N_("Rate control method")
64 #define ENC_RATE_CONTROL_LONGTEXT N_("Method used to encode the video sequence")
66 static const char *enc_rate_control_list
[] = {
67 "constant_noise_threshold",
76 static const char *enc_rate_control_list_text
[] = {
77 N_("Constant noise threshold mode"),
78 N_("Constant bitrate mode (CBR)"),
81 N_("Constant lambda mode"),
82 N_("Constant error mode"),
83 N_("Constant quality mode")
86 #define ENC_GOP_STRUCTURE "gop_structure"
87 #define ENC_GOP_STRUCTURE_TEXT N_("GOP structure")
88 #define ENC_GOP_STRUCTURE_LONGTEXT N_("GOP structure used to encode the video sequence")
90 static const char *enc_gop_structure_list
[] = {
99 static const char *enc_gop_structure_list_text
[] = {
100 N_("No fixed gop structure. A picture can be intra or inter and refer to previous or future pictures."),
101 N_("I-frame only sequence"),
102 N_("Inter pictures refere to previous pictures only"),
103 N_("Inter pictures refere to previous pictures only"),
104 N_("Inter pictures can refer to previoius or future pictures"),
105 N_("Inter pictures can refer to previoius or future pictures")
108 #define ENC_QUALITY "quality"
109 #define ENC_QUALITY_TEXT N_("Constant quality factor")
110 #define ENC_QUALITY_LONGTEXT N_("Quality factor to use in constant quality mode")
112 #define ENC_BITRATE "bitrate"
113 #define ENC_BITRATE_TEXT N_("CBR bitrate (kbps)")
114 #define ENC_BITRATE_LONGTEXT N_("Target bitrate in kbps when encoding in constant bitrate mode")
116 #define ENC_AU_DISTANCE "gop_length"
117 #define ENC_AU_DISTANCE_TEXT N_("GOP length")
118 #define ENC_AU_DISTANCE_LONGTEXT N_("Number of pictures between successive sequenence headers i.e. length of the group of pictures")
121 #define ENC_PREFILTER "filtering"
122 #define ENC_PREFILTER_TEXT N_("Prefilter")
123 #define ENC_PREFILTER_LONGTEXT N_("Enable adaptive prefiltering")
125 static const char *enc_filtering_list
[] = {
127 "center_weighted_median",
134 static const char *enc_filtering_list_text
[] = {
135 N_("No pre-filtering"),
136 N_("Centre Weighted Median"),
137 N_("Gaussian Low Pass Filter"),
139 N_("Gaussian Adaptive Low Pass Filter"),
140 N_("Low Pass Ffilter"),
143 #define ENC_PREFILTER_STRENGTH "filter_value"
144 #define ENC_PREFILTER_STRENGTH_TEXT N_("Amount of prefiltering")
145 #define ENC_PREFILTER_STRENGTH_LONGTEXT N_("Higher value implies more prefiltering")
147 #define ENC_CODINGMODE "coding-mode"
148 #define ENC_CODINGMODE_TEXT N_("Picture coding mode")
149 #define ENC_CODINGMODE_LONGTEXT N_("Field coding is where interlaced fields are coded" \
150 " separately as opposed to a pseudo-progressive frame")
151 static const char *const enc_codingmode_list
[] =
152 { "auto", "progressive", "field" };
153 static const char *const enc_codingmode_list_text
[] =
154 { N_("auto - let encoder decide based upon input (Best)"),
155 N_("force coding frame as single picture"),
156 N_("force coding frame as separate interlaced fields"),
159 #define ENC_MCBLK_SIZE "motion_block_size"
160 #define ENC_MCBLK_SIZE_TEXT N_("Size of motion compensation blocks")
161 #define ENC_MCBLK_SIZE_LONGTEXT N_("")
163 static const char *enc_block_size_list
[] = {
169 static const char *const enc_block_size_list_text
[] =
170 { N_("automatic - let encoder decide based upon input (Best)"),
171 N_("small - use small motion compensation blocks"),
172 N_("medium - use medium motion compensation blocks"),
173 N_("large - use large motion compensation blocks"),
176 #define ENC_MCBLK_OVERLAP "motion_block_overlap"
177 #define ENC_MCBLK_OVERLAP_TEXT N_("Overlap of motion compensation blocks")
178 #define ENC_MCBLK_OVERLAP_LONGTEXT N_("")
180 static const char *enc_block_overlap_list
[] = {
186 static const char *const enc_block_overlap_list_text
[] =
187 { N_("automatic - let encoder decide based upon input (Best)"),
188 N_("none - Motion compensation blocks do not overlap"),
189 N_("partial - Motion compensation blocks only partially overlap"),
190 N_("full - Motion compensation blocks fully overlap"),
194 #define ENC_MVPREC "mv_precision"
195 #define ENC_MVPREC_TEXT N_("Motion Vector precision")
196 #define ENC_MVPREC_LONGTEXT N_("Motion Vector precision in pels")
197 static const char *const enc_mvprec_list
[] =
198 { "1", "1/2", "1/4", "1/8" };
200 #define ENC_ME_COMBINED "me_combined"
201 #define ENC_ME_COMBINED_TEXT N_("Three component motion estimation")
202 #define ENC_ME_COMBINED_LONGTEXT N_("Use chroma as part of the motion estimation process")
204 #define ENC_DWTINTRA "intra_wavelet"
205 #define ENC_DWTINTRA_TEXT N_("Intra picture DWT filter")
206 #define ENC_DWTINTRA_LONGTEXT ENC_DWTINTRA_TEXT
208 #define ENC_DWTINTER "inter_wavelet"
209 #define ENC_DWTINTER_TEXT N_("Inter picture DWT filter")
210 #define ENC_DWTINTER_LONGTEXT ENC_DWTINTER_TEXT
212 static const char *enc_wavelet_list
[] = {
222 static const char *enc_wavelet_list_text
[] = {
223 "Deslauriers-Dubuc (9,7)",
225 "Deslauriers-Dubuc (13,7)",
226 "Haar with no shift",
227 "Haar with single shift per level",
229 "Daubechies (9,7) integer approximation"
232 #define ENC_DWTDEPTH "transform_depth"
233 #define ENC_DWTDEPTH_TEXT N_("Number of DWT iterations")
234 #define ENC_DWTDEPTH_LONGTEXT N_("Also known as DWT levels")
237 /* advanced option only */
238 #define ENC_MULTIQUANT "enable_multiquant"
239 #define ENC_MULTIQUANT_TEXT N_("Enable multiple quantizers")
240 #define ENC_MULTIQUANT_LONGTEXT N_("Enable multiple quantizers per subband (one per codeblock)")
242 #define ENC_NOAC "enable_noarith"
243 #define ENC_NOAC_TEXT N_("Disable arithmetic coding")
244 #define ENC_NOAC_LONGTEXT N_("Use variable length codes instead, useful for very high bitrates")
246 /* visual modelling */
247 /* advanced option only */
248 #define ENC_PWT "perceptual_weighting"
249 #define ENC_PWT_TEXT N_("perceptual weighting method")
250 #define ENC_PWT_LONGTEXT ENC_PWT_TEXT
252 static const char *enc_perceptual_weighting_list
[] = {
259 #define ENC_PDIST "perceptual_distance"
260 #define ENC_PDIST_TEXT N_("perceptual distance")
261 #define ENC_PDIST_LONGTEXT N_("perceptual distance to calculate perceptual weight")
263 static const char *const const ppsz_enc_options
[] = {
264 ENC_RATE_CONTROL
, ENC_GOP_STRUCTURE
, ENC_QUALITY
, ENC_BITRATE
,
265 ENC_AU_DISTANCE
, ENC_CHROMAFMT
, ENC_PREFILTER
, ENC_PREFILTER_STRENGTH
,
266 ENC_CODINGMODE
, ENC_MCBLK_SIZE
, ENC_MCBLK_OVERLAP
, ENC_MVPREC
,
267 ENC_ME_COMBINED
, ENC_DWTINTRA
, ENC_DWTINTER
, ENC_DWTDEPTH
, ENC_MULTIQUANT
,
268 ENC_NOAC
, ENC_PWT
, ENC_PDIST
,
273 set_category( CAT_INPUT
)
274 set_subcategory( SUBCAT_INPUT_VCODEC
)
275 set_description( N_("Schroedinger video decoder") )
276 set_capability( "decoder", 200 )
277 set_callbacks( OpenDecoder
, CloseDecoder
)
278 add_shortcut( "schroedinger" )
281 set_description( N_("Schroedinger video encoder") )
282 set_capability( "encoder", 200 )
283 set_callbacks( OpenEncoder
, CloseEncoder
)
284 add_shortcut( "schroedinger" )
286 add_string ( ENC_CFG_PREFIX ENC_RATE_CONTROL
, NULL
, NULL
,
287 ENC_RATE_CONTROL_TEXT
, ENC_RATE_CONTROL_LONGTEXT
, false )
288 change_string_list( enc_rate_control_list
, enc_rate_control_list_text
, 0 );
290 add_string ( ENC_CFG_PREFIX ENC_GOP_STRUCTURE
, NULL
, NULL
,
291 ENC_GOP_STRUCTURE_TEXT
, ENC_GOP_STRUCTURE_LONGTEXT
, false )
292 change_string_list( enc_gop_structure_list
, enc_gop_structure_list_text
, 0 );
294 add_float( ENC_CFG_PREFIX ENC_QUALITY
, -1, NULL
,
295 ENC_QUALITY_TEXT
, ENC_QUALITY_LONGTEXT
, false )
296 change_float_range(-1., 10.);
298 add_integer( ENC_CFG_PREFIX ENC_BITRATE
, 0, NULL
,
299 ENC_BITRATE_TEXT
, ENC_BITRATE_LONGTEXT
, false )
300 change_integer_range(0, INT_MAX
);
302 add_integer( ENC_CFG_PREFIX ENC_AU_DISTANCE
, -1, NULL
,
303 ENC_AU_DISTANCE_TEXT
, ENC_AU_DISTANCE_LONGTEXT
, false )
304 change_integer_range(-1, INT_MAX
);
306 add_string( ENC_CFG_PREFIX ENC_CHROMAFMT
, "420", NULL
,
307 ENC_CHROMAFMT_TEXT
, ENC_CHROMAFMT_LONGTEXT
, false )
308 change_string_list( enc_chromafmt_list
, enc_chromafmt_list_text
, 0 );
310 add_string( ENC_CFG_PREFIX ENC_PREFILTER
, NULL
, NULL
,
311 ENC_PREFILTER_TEXT
, ENC_PREFILTER_LONGTEXT
, false )
312 change_string_list( enc_filtering_list
, enc_filtering_list_text
, 0 );
314 add_float( ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH
, 5.0, NULL
,
315 ENC_PREFILTER_STRENGTH_TEXT
, ENC_PREFILTER_STRENGTH_LONGTEXT
, false )
316 change_float_range(0.0, 100.0);
318 add_string( ENC_CFG_PREFIX ENC_CODINGMODE
, "auto", NULL
,
319 ENC_CODINGMODE_TEXT
, ENC_CODINGMODE_LONGTEXT
, false )
320 change_string_list( enc_codingmode_list
, enc_codingmode_list_text
, 0 );
322 add_string( ENC_CFG_PREFIX ENC_MCBLK_SIZE
, NULL
, NULL
,
323 ENC_MCBLK_SIZE_TEXT
, ENC_MCBLK_SIZE_LONGTEXT
, false )
324 change_string_list( enc_block_size_list
, enc_block_size_list_text
, 0 );
327 add_string( ENC_CFG_PREFIX ENC_MCBLK_OVERLAP
, NULL
, NULL
,
328 ENC_MCBLK_OVERLAP_TEXT
, ENC_MCBLK_OVERLAP_LONGTEXT
, false )
329 change_string_list( enc_block_overlap_list
, enc_block_overlap_list_text
, 0 );
331 add_string( ENC_CFG_PREFIX ENC_MVPREC
, NULL
, NULL
,
332 ENC_MVPREC_TEXT
, ENC_MVPREC_LONGTEXT
, false )
333 change_string_list( enc_mvprec_list
, enc_mvprec_list
, 0 );
335 /* NOTE: do we need to check for Schro version here */
336 add_bool( ENC_CFG_PREFIX ENC_ME_COMBINED
, false, NULL
,
337 ENC_ME_COMBINED_TEXT
, ENC_ME_COMBINED_LONGTEXT
, false )
339 add_string( ENC_CFG_PREFIX ENC_DWTINTRA
, NULL
, NULL
,
340 ENC_DWTINTRA_TEXT
, ENC_DWTINTRA_LONGTEXT
, false )
341 change_string_list( enc_wavelet_list
, enc_wavelet_list_text
, 0 );
343 add_string( ENC_CFG_PREFIX ENC_DWTINTER
, NULL
, NULL
,
344 ENC_DWTINTER_TEXT
, ENC_DWTINTER_LONGTEXT
, false )
345 change_string_list( enc_wavelet_list
, enc_wavelet_list_text
, 0 );
347 add_integer( ENC_CFG_PREFIX ENC_DWTDEPTH
, -1, NULL
,
348 ENC_DWTDEPTH_TEXT
, ENC_DWTDEPTH_LONGTEXT
, false )
349 change_integer_range(-1, SCHRO_LIMIT_ENCODER_TRANSFORM_DEPTH
);
351 /* advanced option only */
352 /* NB, unforunately vlc doesn't have a concept of 'dont care' */
353 add_integer( ENC_CFG_PREFIX ENC_MULTIQUANT
, -1, NULL
,
354 ENC_MULTIQUANT_TEXT
, ENC_MULTIQUANT_LONGTEXT
, true )
355 change_integer_range(-1, 1);
357 add_bool( ENC_CFG_PREFIX ENC_NOAC
, false, NULL
,
358 ENC_NOAC_TEXT
, ENC_NOAC_LONGTEXT
, false )
360 add_string( ENC_CFG_PREFIX ENC_PWT
, NULL
, NULL
,
361 ENC_PWT_TEXT
, ENC_PWT_LONGTEXT
, false )
362 change_string_list( enc_perceptual_weighting_list
, enc_perceptual_weighting_list
, 0 );
364 add_float( ENC_CFG_PREFIX ENC_PDIST
, -1, NULL
,
365 ENC_PDIST_TEXT
, ENC_PDIST_LONGTEXT
, false )
366 change_float_range(-1., 100.);
371 /*****************************************************************************
373 *****************************************************************************/
374 static picture_t
*DecodeBlock ( decoder_t
*p_dec
, block_t
**pp_block
);
376 struct picture_free_t
382 /*****************************************************************************
383 * decoder_sys_t : Schroedinger decoder descriptor
384 *****************************************************************************/
391 mtime_t i_frame_pts_delta
;
392 SchroDecoder
*p_schro
;
393 SchroVideoFormat
*p_format
;
396 /*****************************************************************************
397 * OpenDecoder: probe the decoder and return score
398 *****************************************************************************/
399 static int OpenDecoder( vlc_object_t
*p_this
)
401 decoder_t
*p_dec
= (decoder_t
*)p_this
;
402 decoder_sys_t
*p_sys
;
403 SchroDecoder
*p_schro
;
405 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_DIRAC
)
410 /* Allocate the memory needed to store the decoder's structure */
411 p_sys
= malloc(sizeof(decoder_sys_t
));
415 /* Initialise the schroedinger (and hence liboil libraries */
416 /* This does no allocation and is safe to call */
419 /* Initialise the schroedinger decoder */
420 if( !(p_schro
= schro_decoder_new()) )
426 p_dec
->p_sys
= p_sys
;
427 p_sys
->p_schro
= p_schro
;
428 p_sys
->p_format
= NULL
;
429 p_sys
->i_lastpts
= VLC_TS_INVALID
;
430 p_sys
->i_frame_pts_delta
= 0;
432 /* Set output properties */
433 p_dec
->fmt_out
.i_cat
= VIDEO_ES
;
434 p_dec
->fmt_out
.i_codec
= VLC_CODEC_I420
;
437 p_dec
->pf_decode_video
= DecodeBlock
;
442 /*****************************************************************************
443 * SetPictureFormat: Set the decoded picture params to the ones from the stream
444 *****************************************************************************/
445 static void SetVideoFormat( decoder_t
*p_dec
)
447 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
449 p_sys
->p_format
= schro_decoder_get_video_format(p_sys
->p_schro
);
450 if( p_sys
->p_format
== NULL
) return;
452 p_sys
->i_frame_pts_delta
= INT64_C(1000000)
453 * p_sys
->p_format
->frame_rate_denominator
454 / p_sys
->p_format
->frame_rate_numerator
;
456 switch( p_sys
->p_format
->chroma_format
)
458 case SCHRO_CHROMA_420
: p_dec
->fmt_out
.i_codec
= VLC_CODEC_I420
; break;
459 case SCHRO_CHROMA_422
: p_dec
->fmt_out
.i_codec
= VLC_CODEC_I422
; break;
460 case SCHRO_CHROMA_444
: p_dec
->fmt_out
.i_codec
= VLC_CODEC_I444
; break;
462 p_dec
->fmt_out
.i_codec
= 0;
466 p_dec
->fmt_out
.video
.i_visible_width
= p_sys
->p_format
->clean_width
;
467 p_dec
->fmt_out
.video
.i_x_offset
= p_sys
->p_format
->left_offset
;
468 p_dec
->fmt_out
.video
.i_width
= p_sys
->p_format
->width
;
470 p_dec
->fmt_out
.video
.i_visible_height
= p_sys
->p_format
->clean_height
;
471 p_dec
->fmt_out
.video
.i_y_offset
= p_sys
->p_format
->top_offset
;
472 p_dec
->fmt_out
.video
.i_height
= p_sys
->p_format
->height
;
474 /* aspect_ratio_[numerator|denominator] describes the pixel aspect ratio */
475 p_dec
->fmt_out
.video
.i_sar_num
= p_sys
->p_format
->aspect_ratio_numerator
;
476 p_dec
->fmt_out
.video
.i_sar_den
= p_sys
->p_format
->aspect_ratio_denominator
;
478 p_dec
->fmt_out
.video
.i_frame_rate
=
479 p_sys
->p_format
->frame_rate_numerator
;
480 p_dec
->fmt_out
.video
.i_frame_rate_base
=
481 p_sys
->p_format
->frame_rate_denominator
;
484 /*****************************************************************************
485 * SchroFrameFree: schro_frame callback to release the associated picture_t
486 * When schro_decoder_reset() is called there will be pictures in the
487 * decoding pipeline that need to be released rather than displayed.
488 *****************************************************************************/
489 static void SchroFrameFree( SchroFrame
*frame
, void *priv
)
491 struct picture_free_t
*p_free
= priv
;
496 decoder_DeletePicture( p_free
->p_dec
, p_free
->p_pic
);
501 /*****************************************************************************
502 * CreateSchroFrameFromPic: wrap a picture_t in a SchroFrame
503 *****************************************************************************/
504 static SchroFrame
*CreateSchroFrameFromPic( decoder_t
*p_dec
)
506 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
507 SchroFrame
*p_schroframe
= schro_frame_new();
508 picture_t
*p_pic
= NULL
;
509 struct picture_free_t
*p_free
;
514 p_pic
= decoder_NewPicture( p_dec
);
519 p_schroframe
->format
= SCHRO_FRAME_FORMAT_U8_420
;
520 if( p_sys
->p_format
->chroma_format
== SCHRO_CHROMA_422
)
522 p_schroframe
->format
= SCHRO_FRAME_FORMAT_U8_422
;
524 else if( p_sys
->p_format
->chroma_format
== SCHRO_CHROMA_444
)
526 p_schroframe
->format
= SCHRO_FRAME_FORMAT_U8_444
;
529 p_schroframe
->width
= p_sys
->p_format
->width
;
530 p_schroframe
->height
= p_sys
->p_format
->height
;
532 p_free
= malloc( sizeof( *p_free
) );
533 p_free
->p_pic
= p_pic
;
534 p_free
->p_dec
= p_dec
;
535 schro_frame_set_free_callback( p_schroframe
, SchroFrameFree
, p_free
);
537 for( int i
=0; i
<3; i
++ )
539 p_schroframe
->components
[i
].width
= p_pic
->p
[i
].i_visible_pitch
;
540 p_schroframe
->components
[i
].stride
= p_pic
->p
[i
].i_pitch
;
541 p_schroframe
->components
[i
].height
= p_pic
->p
[i
].i_visible_lines
;
542 p_schroframe
->components
[i
].length
=
543 p_pic
->p
[i
].i_pitch
* p_pic
->p
[i
].i_lines
;
544 p_schroframe
->components
[i
].data
= p_pic
->p
[i
].p_pixels
;
548 p_schroframe
->components
[i
].v_shift
=
549 SCHRO_FRAME_FORMAT_V_SHIFT( p_schroframe
->format
);
550 p_schroframe
->components
[i
].h_shift
=
551 SCHRO_FRAME_FORMAT_H_SHIFT( p_schroframe
->format
);
555 p_pic
->b_progressive
= !p_sys
->p_format
->interlaced
;
556 p_pic
->b_top_field_first
= p_sys
->p_format
->top_field_first
;
557 p_pic
->i_nb_fields
= 2;
562 /*****************************************************************************
563 * SchroBufferFree: schro_buffer callback to release the associated block_t
564 *****************************************************************************/
565 static void SchroBufferFree( SchroBuffer
*buf
, void *priv
)
567 block_t
*p_block
= priv
;
572 block_Release( p_block
);
576 /*****************************************************************************
577 * CloseDecoder: decoder destruction
578 *****************************************************************************/
579 static void CloseDecoder( vlc_object_t
*p_this
)
581 decoder_t
*p_dec
= (decoder_t
*)p_this
;
582 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
584 schro_decoder_free( p_sys
->p_schro
);
588 /****************************************************************************
589 * DecodeBlock: the whole thing
590 ****************************************************************************
591 * Blocks need not be Dirac dataunit aligned.
592 * If a block has a PTS signaled, it applies to the first picture at or after p_block
594 * If this function returns a picture (!NULL), it is called again and the
595 * same block is resubmitted. To avoid this, set *pp_block to NULL;
596 * If this function returns NULL, the *pp_block is lost (and leaked).
597 * This function must free all blocks when finished with them.
598 ****************************************************************************/
599 static picture_t
*DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
601 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
603 if( !pp_block
) return NULL
;
606 block_t
*p_block
= *pp_block
;
608 /* reset the decoder when seeking as the decode in progress is invalid */
609 /* discard the block as it is just a null magic block */
610 if( p_block
->i_flags
& BLOCK_FLAG_DISCONTINUITY
) {
611 schro_decoder_reset( p_sys
->p_schro
);
613 p_sys
->i_lastpts
= VLC_TS_INVALID
;
614 block_Release( p_block
);
619 SchroBuffer
*p_schrobuffer
;
620 p_schrobuffer
= schro_buffer_new_with_data( p_block
->p_buffer
, p_block
->i_buffer
);
621 p_schrobuffer
->free
= SchroBufferFree
;
622 p_schrobuffer
->priv
= p_block
;
623 if( p_block
->i_pts
> VLC_TS_INVALID
) {
624 mtime_t
*p_pts
= malloc( sizeof(*p_pts
) );
626 *p_pts
= p_block
->i_pts
;
627 /* if this call fails, p_pts is freed automatically */
628 p_schrobuffer
->tag
= schro_tag_new( p_pts
, free
);
632 /* this stops the same block being fed back into this function if
633 * we were on the next iteration of this loop to output a picture */
635 schro_decoder_autoparse_push( p_sys
->p_schro
, p_schrobuffer
);
636 /* DO NOT refer to p_block after this point, it may have been freed */
641 SchroFrame
*p_schroframe
;
643 int state
= schro_decoder_autoparse_wait( p_sys
->p_schro
);
647 case SCHRO_DECODER_FIRST_ACCESS_UNIT
:
648 SetVideoFormat( p_dec
);
651 case SCHRO_DECODER_NEED_BITS
:
654 case SCHRO_DECODER_NEED_FRAME
:
655 p_schroframe
= CreateSchroFrameFromPic( p_dec
);
659 msg_Err( p_dec
, "Could not allocate picture for decoder");
663 schro_decoder_add_output_picture( p_sys
->p_schro
, p_schroframe
);
666 case SCHRO_DECODER_OK
: {
667 SchroTag
*p_tag
= schro_decoder_get_picture_tag( p_sys
->p_schro
);
668 p_schroframe
= schro_decoder_pull( p_sys
->p_schro
);
669 if( !p_schroframe
|| !p_schroframe
->priv
)
671 /* frame can't be one that was allocated by us
672 * -- no private data: discard */
673 if( p_tag
) schro_tag_free( p_tag
);
674 if( p_schroframe
) schro_frame_unref( p_schroframe
);
677 p_pic
= ((struct picture_free_t
*) p_schroframe
->priv
)->p_pic
;
678 p_schroframe
->priv
= NULL
;
682 /* free is handled by schro_frame_unref */
683 p_pic
->date
= *(mtime_t
*) p_tag
->value
;
684 schro_tag_free( p_tag
);
686 else if( p_sys
->i_lastpts
> VLC_TS_INVALID
)
688 /* NB, this shouldn't happen since the packetizer does a
689 * very thorough job of inventing timestamps. The
690 * following is just a very rough fall back incase packetizer
692 /* maybe it would be better to set p_pic->b_force ? */
693 p_pic
->date
= p_sys
->i_lastpts
+ p_sys
->i_frame_pts_delta
;
695 p_sys
->i_lastpts
= p_pic
->date
;
697 schro_frame_unref( p_schroframe
);
700 case SCHRO_DECODER_EOS
:
701 /* NB, the new api will not emit _EOS, it handles the reset internally */
704 case SCHRO_DECODER_ERROR
:
705 msg_Err( p_dec
, "SCHRO_DECODER_ERROR");
711 /*****************************************************************************
713 *****************************************************************************/
714 static block_t
*Encode(encoder_t
*p_enc
, picture_t
*p_pict
);
717 /*****************************************************************************
718 * picture_pts_t : store pts alongside picture number, not carried through
720 *****************************************************************************/
723 bool b_empty
; /* entry is invalid */
724 uint32_t u_pnum
; /* dirac picture number */
725 mtime_t i_pts
; /* associated pts */
728 /*****************************************************************************
729 * encoder_sys_t : Schroedinger encoder descriptor
730 *****************************************************************************/
731 #define SCHRO_PTS_TLB_SIZE 256
737 SchroEncoder
*p_schro
;
738 SchroVideoFormat
*p_format
;
740 bool b_auto_field_coding
;
742 uint8_t *p_buffer_in
;
744 uint32_t i_input_picnum
;
745 block_fifo_t
*p_dts_fifo
;
748 uint8_t *p_buffer_out
;
751 struct picture_pts_t pts_tlb
[SCHRO_PTS_TLB_SIZE
];
752 mtime_t i_pts_offset
;
753 mtime_t i_field_time
;
761 unsigned int i_height
;
763 SchroVideoFormatEnum i_vf
;
764 } schro_format_guess
[] = {
765 /* Important: Keep this list ordered in ascending picture height */
766 {1, 0, SCHRO_VIDEO_FORMAT_CUSTOM
},
767 {120, 15, SCHRO_VIDEO_FORMAT_QSIF
},
768 {144, 12, SCHRO_VIDEO_FORMAT_QCIF
},
769 {240, 15, SCHRO_VIDEO_FORMAT_SIF
},
770 {288, 12, SCHRO_VIDEO_FORMAT_CIF
},
771 {480, 30, SCHRO_VIDEO_FORMAT_SD480I_60
},
772 {480, 15, SCHRO_VIDEO_FORMAT_4SIF
},
773 {576, 12, SCHRO_VIDEO_FORMAT_4CIF
},
774 {576, 25, SCHRO_VIDEO_FORMAT_SD576I_50
},
775 {720, 50, SCHRO_VIDEO_FORMAT_HD720P_50
},
776 {720, 60, SCHRO_VIDEO_FORMAT_HD720P_60
},
777 {1080, 24, SCHRO_VIDEO_FORMAT_DC2K_24
},
778 {1080, 25, SCHRO_VIDEO_FORMAT_HD1080I_50
},
779 {1080, 30, SCHRO_VIDEO_FORMAT_HD1080I_60
},
780 {1080, 50, SCHRO_VIDEO_FORMAT_HD1080P_50
},
781 {1080, 60, SCHRO_VIDEO_FORMAT_HD1080P_60
},
782 {2160, 24, SCHRO_VIDEO_FORMAT_DC4K_24
},
786 /*****************************************************************************
787 * ResetPTStlb: Purge all entries in @p_enc@'s PTS-tlb
788 *****************************************************************************/
789 static void ResetPTStlb( encoder_t
*p_enc
)
791 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
792 for( int i
=0; i
<SCHRO_PTS_TLB_SIZE
; i
++)
794 p_sys
->pts_tlb
[i
].b_empty
= true;
799 /*****************************************************************************
800 * StorePicturePTS: Store the PTS value for a particular picture number
801 *****************************************************************************/
802 static void StorePicturePTS( encoder_t
*p_enc
, uint32_t u_pnum
, mtime_t i_pts
)
804 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
806 for( int i
=0; i
<SCHRO_PTS_TLB_SIZE
; i
++ )
808 if( p_sys
->pts_tlb
[i
].b_empty
)
810 p_sys
->pts_tlb
[i
].u_pnum
= u_pnum
;
811 p_sys
->pts_tlb
[i
].i_pts
= i_pts
;
812 p_sys
->pts_tlb
[i
].b_empty
= false;
818 msg_Err( p_enc
, "Could not store PTS %"PRId64
" for frame %u", i_pts
, u_pnum
);
821 /*****************************************************************************
822 * GetPicturePTS: Retrieve the PTS value for a particular picture number
823 *****************************************************************************/
824 static mtime_t
GetPicturePTS( encoder_t
*p_enc
, uint32_t u_pnum
)
826 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
828 for( int i
=0; i
<SCHRO_PTS_TLB_SIZE
; i
++ )
830 if( !p_sys
->pts_tlb
[i
].b_empty
&&
831 p_sys
->pts_tlb
[i
].u_pnum
== u_pnum
)
833 p_sys
->pts_tlb
[i
].b_empty
= true;
834 return p_sys
->pts_tlb
[i
].i_pts
;
838 msg_Err( p_enc
, "Could not retrieve PTS for picture %u", u_pnum
);
843 #define SCHRO_SET_ENUM(list,name, name_text, value) \
844 if(list && name_text && name && value) { \
847 int list_size = ARRAY_SIZE(list); \
848 for (i = 0; i < list_size; ++i) { \
849 if (strcmp(list[i], value)) \
852 schro_encoder_setting_set_double(p_sys->p_schro, name, i); \
856 msg_Err(p_enc, "Invalid %s: %s", name_text, value); \
861 /*****************************************************************************
862 * OpenEncoder: probe the encoder and return score
863 *****************************************************************************/
864 static int OpenEncoder( vlc_object_t
*p_this
)
866 encoder_t
*p_enc
= (encoder_t
*)p_this
;
867 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
872 if( p_enc
->fmt_out
.i_codec
!= VLC_CODEC_DIRAC
&&
878 if( !p_enc
->fmt_in
.video
.i_frame_rate
|| !p_enc
->fmt_in
.video
.i_frame_rate_base
||
879 !p_enc
->fmt_in
.video
.i_height
|| !p_enc
->fmt_in
.video
.i_width
)
881 msg_Err( p_enc
, "Framerate and picture dimensions must be non-zero" );
885 /* Allocate the memory needed to store the decoder's structure */
886 if( ( p_sys
= calloc( 1, sizeof(*p_sys
) ) ) == NULL
)
889 p_enc
->p_sys
= p_sys
;
890 p_enc
->pf_encode_video
= Encode
;
891 p_enc
->fmt_out
.i_codec
= VLC_CODEC_DIRAC
;
892 p_enc
->fmt_out
.i_cat
= VIDEO_ES
;
894 if( ( p_sys
->p_dts_fifo
= block_FifoNew() ) == NULL
)
896 CloseEncoder( p_this
);
900 ResetPTStlb( p_enc
);
902 /* guess the video format based upon number of lines and picture height */
904 SchroVideoFormatEnum guessed_video_fmt
= SCHRO_VIDEO_FORMAT_CUSTOM
;
905 /* Pick the dirac_video_format in this order of preference:
906 * 1. an exact match in frame height and an approximate fps match
907 * 2. the previous preset with a smaller number of lines.
911 if( schro_format_guess
[i
].i_height
> p_enc
->fmt_in
.video
.i_height
)
913 guessed_video_fmt
= schro_format_guess
[i
-1].i_vf
;
916 if( schro_format_guess
[i
].i_height
!= p_enc
->fmt_in
.video
.i_height
)
918 int src_fps
= p_enc
->fmt_in
.video
.i_frame_rate
/ p_enc
->fmt_in
.video
.i_frame_rate_base
;
919 int delta_fps
= abs( schro_format_guess
[i
].i_approx_fps
- src_fps
);
923 guessed_video_fmt
= schro_format_guess
[i
].i_vf
;
925 } while( schro_format_guess
[++i
].i_height
);
928 p_sys
->p_schro
= schro_encoder_new();
929 p_sys
->p_format
= schro_encoder_get_video_format(p_sys
->p_schro
);
931 /* initialise the video format parameters to the guessed format */
932 schro_video_format_set_std_video_format(p_sys
->p_format
, guessed_video_fmt
);
934 /* constants set from the input video format */
935 p_sys
->p_format
->width
= p_enc
->fmt_in
.video
.i_width
;
936 p_sys
->p_format
->height
= p_enc
->fmt_in
.video
.i_height
;
937 p_sys
->p_format
->frame_rate_numerator
= p_enc
->fmt_in
.video
.i_frame_rate
;
938 p_sys
->p_format
->frame_rate_denominator
= p_enc
->fmt_in
.video
.i_frame_rate_base
;
939 unsigned u_asr_num
, u_asr_den
;
940 vlc_ureduce( &u_asr_num
, &u_asr_den
,
941 p_enc
->fmt_in
.video
.i_sar_num
,
942 p_enc
->fmt_in
.video
.i_sar_den
, 0 );
943 p_sys
->p_format
->aspect_ratio_numerator
= u_asr_num
;
944 p_sys
->p_format
->aspect_ratio_denominator
= u_asr_den
;
946 config_ChainParse( p_enc
, ENC_CFG_PREFIX
, ppsz_enc_options
, p_enc
->p_cfg
);
948 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_RATE_CONTROL
);
951 else if( *psz_tmp
!= '\0') {
952 SCHRO_SET_ENUM(enc_rate_control_list
, ENC_RATE_CONTROL
, ENC_RATE_CONTROL_TEXT
, psz_tmp
);
956 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_GOP_STRUCTURE
);
959 else if( *psz_tmp
!= '\0') {
960 SCHRO_SET_ENUM(enc_gop_structure_list
, ENC_GOP_STRUCTURE
, ENC_GOP_STRUCTURE_TEXT
, psz_tmp
)
964 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_CHROMAFMT
);
967 else if( !strcmp( psz_tmp
, "420" ) ) {
968 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I420
;
969 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 12;
970 p_sys
->p_format
->chroma_format
= SCHRO_CHROMA_420
;
971 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 3 / 2;
973 else if( !strcmp( psz_tmp
, "422" ) ) {
974 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I422
;
975 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 16;
976 p_sys
->p_format
->chroma_format
= SCHRO_CHROMA_422
;
977 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 2;
979 else if( !strcmp( psz_tmp
, "444" ) ) {
980 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I444
;
981 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 24;
982 p_sys
->p_format
->chroma_format
= SCHRO_CHROMA_444
;
983 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 3;
986 msg_Err( p_enc
, "Invalid chroma format: %s", psz_tmp
);
992 f_tmp
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_QUALITY
);
994 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_QUALITY
, f_tmp
);
996 /* use bitrate from sout-transcode-vb in kbps */
997 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_BITRATE
);
999 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_BITRATE
, i_tmp
* 1000 );
1001 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_BITRATE
, p_enc
->fmt_out
.i_bitrate
);
1003 p_enc
->fmt_out
.i_bitrate
= schro_encoder_setting_get_double (p_sys
->p_schro
, ENC_BITRATE
);
1005 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_AU_DISTANCE
);
1007 schro_encoder_setting_set_double( p_sys
->p_schro
, "au_distance", i_tmp
);
1010 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_PREFILTER
);
1013 else if( *psz_tmp
!= '\0') {
1014 SCHRO_SET_ENUM(enc_filtering_list
, ENC_PREFILTER
, ENC_PREFILTER_TEXT
, psz_tmp
)
1018 f_tmp
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH
);
1020 schro_encoder_setting_set_double( p_sys
->p_schro
, "filter_value", f_tmp
);
1023 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_CODINGMODE
);
1026 else if( !strcmp( psz_tmp
, "auto" ) ) {
1027 p_sys
->b_auto_field_coding
= true;
1029 else if( !strcmp( psz_tmp
, "progressive" ) ) {
1030 p_sys
->b_auto_field_coding
= false;
1031 schro_encoder_setting_set_double( p_sys
->p_schro
, "interlaced_coding", false);
1033 else if( !strcmp( psz_tmp
, "field" ) ) {
1034 p_sys
->b_auto_field_coding
= false;
1035 schro_encoder_setting_set_double( p_sys
->p_schro
, "interlaced_coding", true);
1038 msg_Err( p_enc
, "Invalid codingmode: %s", psz_tmp
);
1044 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_SIZE
);
1047 else if( *psz_tmp
!= '\0') {
1048 SCHRO_SET_ENUM(enc_block_size_list
, ENC_MCBLK_SIZE
, ENC_MCBLK_SIZE_TEXT
, psz_tmp
)
1052 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP
);
1055 else if( *psz_tmp
!= '\0') {
1056 SCHRO_SET_ENUM(enc_block_overlap_list
, ENC_MCBLK_OVERLAP
, ENC_MCBLK_OVERLAP_TEXT
, psz_tmp
)
1060 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_MVPREC
);
1063 else if( *psz_tmp
!= '\0') {
1064 if( !strcmp( psz_tmp
, "1" ) ) {
1065 schro_encoder_setting_set_double( p_sys
->p_schro
, "mv_precision", 0 );
1067 else if( !strcmp( psz_tmp
, "1/2" ) ) {
1068 schro_encoder_setting_set_double( p_sys
->p_schro
, "mv_precision", 1 );
1070 else if( !strcmp( psz_tmp
, "1/4" ) ) {
1071 schro_encoder_setting_set_double( p_sys
->p_schro
, "mv_precision", 2 );
1073 else if( !strcmp( psz_tmp
, "1/8" ) ) {
1074 schro_encoder_setting_set_double( p_sys
->p_schro
, "mv_precision", 3 );
1077 msg_Err( p_enc
, "Invalid mv_precision: %s", psz_tmp
);
1084 /* NOTE: do we need to check to Schro version here */
1085 schro_encoder_setting_set_double( p_sys
->p_schro
, "enable_chroma_me", var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_ME_COMBINED
) );
1088 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_DWTINTRA
);
1091 else if( *psz_tmp
!= '\0') {
1092 SCHRO_SET_ENUM(enc_wavelet_list
, ENC_DWTINTRA
, ENC_DWTINTRA_TEXT
, psz_tmp
)
1096 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_DWTINTER
);
1099 else if( *psz_tmp
!= '\0') {
1100 SCHRO_SET_ENUM(enc_wavelet_list
, ENC_DWTINTER
, ENC_DWTINTER_TEXT
, psz_tmp
)
1104 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTDEPTH
);
1106 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_DWTDEPTH
, i_tmp
);
1108 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MULTIQUANT
);
1110 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_MULTIQUANT
, i_tmp
);
1112 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_NOAC
, var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_NOAC
) );
1114 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_PWT
);
1117 else if( *psz_tmp
!= '\0' ) {
1118 SCHRO_SET_ENUM(enc_perceptual_weighting_list
, ENC_PWT
, ENC_PWT_TEXT
, psz_tmp
)
1122 f_tmp
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_PDIST
);
1124 schro_encoder_setting_set_double( p_sys
->p_schro
, ENC_PDIST
, f_tmp
);
1127 /* Allocate the buffer for inputing frames into the encoder */
1128 if( ( p_sys
->p_buffer_in
= malloc( p_sys
->i_buffer_in
) ) == NULL
)
1130 CloseEncoder( p_this
);
1134 /* Set up output buffer */
1135 /* Unfortunately it isn't possible to determine if the buffer
1136 * is too small (and then reallocate it) */
1137 p_sys
->i_buffer_out
= 4096 + p_sys
->i_buffer_in
;
1138 if( ( p_sys
->p_buffer_out
= malloc( p_sys
->i_buffer_out
) ) == NULL
)
1140 CloseEncoder( p_this
);
1150 CloseEncoder( p_this
);
1151 return VLC_EGENERIC
;
1155 struct enc_picture_free_t
1161 /*****************************************************************************
1162 * EncSchroFrameFree: schro_frame callback to release the associated picture_t
1163 * When schro_encoder_reset() is called there will be pictures in the
1164 * encoding pipeline that need to be released rather than displayed.
1165 *****************************************************************************/
1166 static void EncSchroFrameFree( SchroFrame
*frame
, void *priv
)
1168 struct enc_picture_free_t
*p_free
= priv
;
1173 /* FIXME - who free the picture ??? */
1174 picture_Release ( p_free
->p_pic
);
1179 /*****************************************************************************
1180 * CreateSchroFrameFromPic: wrap a picture_t in a SchroFrame
1181 *****************************************************************************/
1182 static SchroFrame
*CreateSchroFrameFromInputPic( encoder_t
*p_enc
, picture_t
*p_pic
)
1184 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
1185 SchroFrame
*p_schroframe
= schro_frame_new();
1186 struct enc_picture_free_t
*p_free
;
1194 p_schroframe
->format
= SCHRO_FRAME_FORMAT_U8_420
;
1195 if( p_sys
->p_format
->chroma_format
== SCHRO_CHROMA_422
)
1197 p_schroframe
->format
= SCHRO_FRAME_FORMAT_U8_422
;
1199 else if( p_sys
->p_format
->chroma_format
== SCHRO_CHROMA_444
)
1201 p_schroframe
->format
= SCHRO_FRAME_FORMAT_U8_444
;
1204 p_schroframe
->width
= p_sys
->p_format
->width
;
1205 p_schroframe
->height
= p_sys
->p_format
->height
;
1207 p_free
= malloc( sizeof( *p_free
) );
1208 p_free
->p_pic
= p_pic
;
1209 p_free
->p_enc
= p_enc
;
1210 schro_frame_set_free_callback( p_schroframe
, EncSchroFrameFree
, p_free
);
1212 for( int i
=0; i
<3; i
++ )
1214 p_schroframe
->components
[i
].width
= p_pic
->p
[i
].i_visible_pitch
;
1215 p_schroframe
->components
[i
].stride
= p_pic
->p
[i
].i_pitch
;
1216 p_schroframe
->components
[i
].height
= p_pic
->p
[i
].i_visible_lines
;
1217 p_schroframe
->components
[i
].length
=
1218 p_pic
->p
[i
].i_pitch
* p_pic
->p
[i
].i_lines
;
1219 p_schroframe
->components
[i
].data
= p_pic
->p
[i
].p_pixels
;
1223 p_schroframe
->components
[i
].v_shift
=
1224 SCHRO_FRAME_FORMAT_V_SHIFT( p_schroframe
->format
);
1225 p_schroframe
->components
[i
].h_shift
=
1226 SCHRO_FRAME_FORMAT_H_SHIFT( p_schroframe
->format
);
1230 return p_schroframe
;
1233 /* Attempt to find dirac picture number in an encapsulation unit */
1234 static int ReadDiracPictureNumber( uint32_t *p_picnum
, block_t
*p_block
)
1237 /* protect against falling off the edge */
1238 while( u_pos
+ 13 < p_block
->i_buffer
)
1240 /* find the picture startcode */
1241 if( p_block
->p_buffer
[u_pos
] & 0x08 )
1243 *p_picnum
= GetDWBE( p_block
->p_buffer
+ u_pos
+ 9 );
1246 /* skip to the next dirac data unit */
1247 uint32_t u_npo
= GetDWBE( p_block
->p_buffer
+ u_pos
+ 1 );
1248 assert( u_npo
<= UINT32_MAX
- u_pos
);
1257 static block_t
*Encode( encoder_t
*p_enc
, picture_t
*p_pic
)
1259 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
1260 block_t
*p_block
, *p_output_chain
= NULL
;
1261 int i_plane
, i_line
, i_width
, i_src_stride
;
1267 if( !p_sys
->started
|| p_sys
->eos_pulled
)
1270 if( !p_sys
->eos_signalled
) {
1271 p_sys
->eos_signalled
= 1;
1272 schro_encoder_end_of_stream( p_sys
->p_schro
);
1275 /* we only know if the sequence is interlaced when the first
1276 * picture arrives, so final setup is done here */
1277 /* XXX todo, detect change of interlace */
1278 p_sys
->p_format
->interlaced
= !p_pic
->b_progressive
;
1279 p_sys
->p_format
->top_field_first
= p_pic
->b_top_field_first
;
1281 if( p_sys
->b_auto_field_coding
)
1282 schro_encoder_setting_set_double( p_sys
->p_schro
, "interlaced_coding", !p_pic
->b_progressive
);
1285 if( !p_sys
->started
) {
1288 date_Init (&date
, p_enc
->fmt_in
.video
.i_frame_rate
, p_enc
->fmt_in
.video
.i_frame_rate_base
);
1289 /* FIXME - Unlike dirac-research codec Schro doesn't have a function that returns the delay in pics yet.
1290 * Use a default of 1
1292 date_Increment( &date
, 1 );
1293 p_sys
->i_pts_offset
= date_Get( &date
);
1294 if( schro_encoder_setting_get_double(p_sys
->p_schro
, "interlaced_coding") > 0.0 ) {
1295 date_Set( &date
, 0 );
1296 date_Increment( &date
, 1);
1297 p_sys
->i_field_time
= date_Get( &date
) / 2;
1300 schro_video_format_set_std_signal_range(p_sys
->p_format
,
1301 SCHRO_SIGNAL_RANGE_8BIT_VIDEO
);
1302 schro_encoder_set_video_format( p_sys
->p_schro
, p_sys
->p_format
);
1303 schro_encoder_start( p_sys
->p_schro
);
1307 if( !p_sys
->eos_signalled
) {
1308 /* create a schro frame from the input pic and load */
1309 /* Increase ref count by 1 so that the picture is not freed until
1310 Schro finishes with it */
1311 picture_Hold( p_pic
);
1313 frame
= CreateSchroFrameFromInputPic( p_enc
, p_pic
);
1316 schro_encoder_push_frame( p_sys
->p_schro
, frame
);
1319 /* store pts in a lookaside buffer, so that the same pts may
1320 * be used for the picture in coded order */
1321 StorePicturePTS( p_enc
, p_sys
->i_input_picnum
, p_pic
->date
);
1322 p_sys
->i_input_picnum
++;
1324 /* store dts in a queue, so that they appear in order in
1326 p_block
= block_New( p_enc
, 1 );
1329 p_block
->i_dts
= p_pic
->date
- p_sys
->i_pts_offset
;
1330 block_FifoPut( p_sys
->p_dts_fifo
, p_block
);
1333 /* for field coding mode, insert an extra value into both the
1334 * pts lookaside buffer and dts queue, offset to correspond
1335 * to a one field delay. */
1336 if( schro_encoder_setting_get_double(p_sys
->p_schro
, "interlaced_coding") > 0.0 ) {
1337 StorePicturePTS( p_enc
, p_sys
->i_input_picnum
, p_pic
->date
+ p_sys
->i_field_time
);
1338 p_sys
->i_input_picnum
++;
1340 p_block
= block_New( p_enc
, 1 );
1343 p_block
->i_dts
= p_pic
->date
- p_sys
->i_pts_offset
+ p_sys
->i_field_time
;
1344 block_FifoPut( p_sys
->p_dts_fifo
, p_block
);
1351 SchroStateEnum state
;
1352 state
= schro_encoder_wait(p_sys
->p_schro
);
1355 case SCHRO_STATE_NEED_FRAME
:
1358 case SCHRO_STATE_AGAIN
:
1360 case SCHRO_STATE_END_OF_STREAM
:
1361 p_sys
->eos_pulled
= 1;
1364 case SCHRO_STATE_HAVE_BUFFER
:
1366 SchroBuffer
*enc_buf
;
1368 int presentation_frame
;
1369 enc_buf
= schro_encoder_pull(p_sys
->p_schro
, &presentation_frame
);
1370 p_block
= block_New( p_enc
, enc_buf
->length
);
1374 memcpy( p_block
->p_buffer
, enc_buf
->data
, enc_buf
->length
);
1375 schro_buffer_unref( enc_buf
);
1377 /* if some flags were set for a previous block, prevent
1378 * them from getting lost */
1379 if( p_sys
->p_chain
)
1380 p_block
->i_flags
|= p_sys
->p_chain
->i_flags
;
1383 /* store all extracted blocks in a chain and gather up when an
1384 * entire encapsulation unit is avaliable (ends with a picture) */
1385 block_ChainAppend( &p_sys
->p_chain
, p_block
);
1387 /* Presence of a Sequence header indicates a seek point */
1388 if( 0 == p_block
->p_buffer
[4] )
1390 p_block
->i_flags
|= BLOCK_FLAG_TYPE_I
;
1392 if( !p_enc
->fmt_out
.p_extra
) {
1393 const uint8_t eos
[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
1394 uint32_t len
= GetDWBE( p_block
->p_buffer
+ 5 );
1395 /* if it hasn't been done so far, stash a copy of the
1396 * sequence header for muxers such as ogg */
1397 /* The OggDirac spec advises that a Dirac EOS DataUnit
1398 * is appended to the sequence header to allow guard
1399 * against poor streaming servers */
1400 /* XXX, should this be done using the packetizer ? */
1401 p_enc
->fmt_out
.p_extra
= malloc( len
+ sizeof(eos
) );
1402 if( !p_enc
->fmt_out
.p_extra
)
1404 memcpy( p_enc
->fmt_out
.p_extra
, p_block
->p_buffer
, len
);
1405 memcpy( (uint8_t*)p_enc
->fmt_out
.p_extra
+ len
, eos
, sizeof(eos
) );
1406 SetDWBE( (uint8_t*)p_enc
->fmt_out
.p_extra
+ len
+ 10, len
);
1407 p_enc
->fmt_out
.i_extra
= len
+ sizeof(eos
);
1411 if( ReadDiracPictureNumber( &pic_num
, p_block
) )
1413 /* Finding a picture terminates an ecapsulation unit, gather
1414 * all data and output; use the next dts value queued up
1415 * and find correct pts in the tlb */
1416 p_block
= block_FifoGet( p_sys
->p_dts_fifo
);
1417 p_sys
->p_chain
->i_dts
= p_block
->i_dts
;
1418 p_sys
->p_chain
->i_pts
= GetPicturePTS( p_enc
, pic_num
);
1419 block_Release( p_block
);
1420 block_ChainAppend( &p_output_chain
, block_ChainGather( p_sys
->p_chain
) );
1421 p_sys
->p_chain
= NULL
;
1432 return p_output_chain
;
1435 /*****************************************************************************
1436 * CloseEncoder: Schro encoder destruction
1437 *****************************************************************************/
1438 static void CloseEncoder( vlc_object_t
*p_this
)
1440 encoder_t
*p_enc
= (encoder_t
*)p_this
;
1441 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
1443 /* Free the encoder resources */
1444 if( p_sys
->p_schro
)
1445 schro_encoder_free( p_sys
->p_schro
);
1447 free (p_sys
->p_format
);
1449 free( p_sys
->p_buffer_in
);
1450 free( p_sys
->p_buffer_out
);
1452 if( p_sys
->p_dts_fifo
)
1453 block_FifoRelease( p_sys
->p_dts_fifo
);
1455 block_ChainRelease( p_sys
->p_chain
);