Add encoder support for Dirac using the Schroedinger library.
[vlc/asuraparaju-public.git] / modules / codec / schroedinger.c
blobd722ffd802b12260e4cefe0a5ab88b4b9079a0e9
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
7 * $Id$
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 /*****************************************************************************
28 * Preamble
29 *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
34 #include <assert.h>
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_codec.h>
39 #include <vlc_sout.h>
41 #include <schroedinger/schro.h>
43 /*****************************************************************************
44 * Module descriptor
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",
68 "constant_bitrate",
69 "low_delay",
70 "lossless",
71 "constant_lambda",
72 "constant_error",
73 "constant_quality"
76 static const char *enc_rate_control_list_text[] = {
77 N_("Constant noise threshold mode"),
78 N_("Constant bitrate mode (CBR)"),
79 N_("Low Delay mode"),
80 N_("Lossless mode"),
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[] = {
91 "adaptive",
92 "intra_only",
93 "backref",
94 "chained_backref",
95 "biref",
96 "chained_biref"
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[] = {
126 "none",
127 "center_weighted_median",
128 "gaussian",
129 "add_noise",
130 "adaptive_gaussian",
131 "lowpass"
134 static const char *enc_filtering_list_text[] = {
135 N_("No pre-filtering"),
136 N_("Centre Weighted Median"),
137 N_("Gaussian Low Pass Filter"),
138 N_("Add Noise"),
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[] = {
164 "automatic",
165 "small",
166 "medium",
167 "large"
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[] = {
181 "automatic",
182 "none",
183 "partial",
184 "full"
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[] = {
213 "desl_dubuc_9_7",
214 "le_gall_5_3",
215 "desl_dubuc_13_7",
216 "haar_0",
217 "haar_1",
218 "fidelity",
219 "daub_9_7"
222 static const char *enc_wavelet_list_text[] = {
223 "Deslauriers-Dubuc (9,7)",
224 "LeGall (5,3)",
225 "Deslauriers-Dubuc (13,7)",
226 "Haar with no shift",
227 "Haar with single shift per level",
228 "Fidelity filter",
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[] = {
253 "none",
254 "ccir959",
255 "moo",
256 "manos_sakrison"
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,
269 NULL
272 vlc_module_begin ()
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" )
280 add_submodule()
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.);
368 vlc_module_end ()
371 /*****************************************************************************
372 * Local prototypes
373 *****************************************************************************/
374 static picture_t *DecodeBlock ( decoder_t *p_dec, block_t **pp_block );
376 struct picture_free_t
378 picture_t *p_pic;
379 decoder_t *p_dec;
382 /*****************************************************************************
383 * decoder_sys_t : Schroedinger decoder descriptor
384 *****************************************************************************/
385 struct decoder_sys_t
388 * Dirac properties
390 mtime_t i_lastpts;
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 )
407 return VLC_EGENERIC;
410 /* Allocate the memory needed to store the decoder's structure */
411 p_sys = malloc(sizeof(decoder_sys_t));
412 if( p_sys == NULL )
413 return VLC_ENOMEM;
415 /* Initialise the schroedinger (and hence liboil libraries */
416 /* This does no allocation and is safe to call */
417 schro_init();
419 /* Initialise the schroedinger decoder */
420 if( !(p_schro = schro_decoder_new()) )
422 free( p_sys );
423 return VLC_EGENERIC;
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;
436 /* Set callbacks */
437 p_dec->pf_decode_video = DecodeBlock;
439 return VLC_SUCCESS;
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;
461 default:
462 p_dec->fmt_out.i_codec = 0;
463 break;
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;
493 if( !p_free )
494 return;
496 decoder_DeletePicture( p_free->p_dec, p_free->p_pic );
497 free(p_free);
498 (void)frame;
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;
511 if( !p_schroframe )
512 return NULL;
514 p_pic = decoder_NewPicture( p_dec );
516 if( !p_pic )
517 return NULL;
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;
546 if(i!=0)
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;
559 return p_schroframe;
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;
569 if( !p_block )
570 return;
572 block_Release( p_block );
573 (void)buf;
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 );
585 free( p_sys );
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;
605 if ( *pp_block ) {
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 );
615 *pp_block = NULL;
616 return NULL;
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) );
625 if( 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 */
634 *pp_block = NULL;
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 */
639 while( 1 )
641 SchroFrame *p_schroframe;
642 picture_t *p_pic;
643 int state = schro_decoder_autoparse_wait( p_sys->p_schro );
645 switch( state )
647 case SCHRO_DECODER_FIRST_ACCESS_UNIT:
648 SetVideoFormat( p_dec );
649 break;
651 case SCHRO_DECODER_NEED_BITS:
652 return NULL;
654 case SCHRO_DECODER_NEED_FRAME:
655 p_schroframe = CreateSchroFrameFromPic( p_dec );
657 if( !p_schroframe )
659 msg_Err( p_dec, "Could not allocate picture for decoder");
660 return NULL;
663 schro_decoder_add_output_picture( p_sys->p_schro, p_schroframe);
664 break;
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 );
675 break;
677 p_pic = ((struct picture_free_t*) p_schroframe->priv)->p_pic;
678 p_schroframe->priv = NULL;
680 if( p_tag )
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
691 * is missing. */
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 );
698 return p_pic;
700 case SCHRO_DECODER_EOS:
701 /* NB, the new api will not emit _EOS, it handles the reset internally */
702 break;
704 case SCHRO_DECODER_ERROR:
705 msg_Err( p_dec, "SCHRO_DECODER_ERROR");
706 return NULL;
711 /*****************************************************************************
712 * Local prototypes
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
719 * encoder
720 *****************************************************************************/
721 struct picture_pts_t
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
732 struct encoder_sys_t
735 * Dirac properties
737 SchroEncoder *p_schro;
738 SchroVideoFormat *p_format;
739 int started;
740 bool b_auto_field_coding;
742 uint8_t *p_buffer_in;
743 int i_buffer_in;
744 uint32_t i_input_picnum;
745 block_fifo_t *p_dts_fifo;
747 int i_buffer_out;
748 uint8_t *p_buffer_out;
749 block_t *p_chain;
751 struct picture_pts_t pts_tlb[SCHRO_PTS_TLB_SIZE];
752 mtime_t i_pts_offset;
753 mtime_t i_field_time;
755 bool eos_signalled;
756 bool eos_pulled;
759 static struct
761 unsigned int i_height;
762 int i_approx_fps;
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},
783 {0, 0, 0},
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;
814 return;
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 );
839 return 0;
843 #define SCHRO_SET_ENUM(list,name, name_text, value) \
844 if(list && name_text && name && value) { \
845 int i; \
846 int index = -1; \
847 int list_size = ARRAY_SIZE(list); \
848 for (i = 0; i < list_size; ++i) { \
849 if (strcmp(list[i], value)) \
850 continue; \
851 index = i; \
852 schro_encoder_setting_set_double(p_sys->p_schro, name, i); \
853 break; \
855 if (index == -1) { \
856 msg_Err(p_enc, "Invalid %s: %s", name_text, value); \
857 free(value); \
858 goto error; \
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;
868 int i_tmp;
869 float f_tmp;
870 char *psz_tmp;
872 if( p_enc->fmt_out.i_codec != VLC_CODEC_DIRAC &&
873 !p_enc->b_force )
875 return VLC_EGENERIC;
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" );
882 return VLC_EGENERIC;
885 /* Allocate the memory needed to store the decoder's structure */
886 if( ( p_sys = calloc( 1, sizeof(*p_sys) ) ) == NULL )
887 return VLC_ENOMEM;
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 );
897 return VLC_ENOMEM;
900 ResetPTStlb( p_enc );
902 /* guess the video format based upon number of lines and picture height */
903 int i = 0;
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;
914 break;
916 if( schro_format_guess[i].i_height != p_enc->fmt_in.video.i_height )
917 continue;
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 );
920 if( delta_fps > 2 )
921 continue;
923 guessed_video_fmt = schro_format_guess[i].i_vf;
924 break;
925 } while( schro_format_guess[++i].i_height );
927 schro_init();
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 );
949 if( !psz_tmp )
950 goto error;
951 else if( *psz_tmp != '\0') {
952 SCHRO_SET_ENUM(enc_rate_control_list, ENC_RATE_CONTROL, ENC_RATE_CONTROL_TEXT, psz_tmp);
954 free( psz_tmp );
956 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_GOP_STRUCTURE );
957 if( !psz_tmp )
958 goto error;
959 else if( *psz_tmp != '\0') {
960 SCHRO_SET_ENUM(enc_gop_structure_list, ENC_GOP_STRUCTURE, ENC_GOP_STRUCTURE_TEXT, psz_tmp)
962 free( psz_tmp );
964 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CHROMAFMT );
965 if( !psz_tmp )
966 goto error;
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;
985 else {
986 msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
987 free( psz_tmp );
988 goto error;
990 free( psz_tmp );
992 f_tmp = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_QUALITY );
993 if (f_tmp > 0)
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 );
998 if( i_tmp > -1 )
999 schro_encoder_setting_set_double( p_sys->p_schro, ENC_BITRATE, i_tmp * 1000 );
1000 else
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 );
1006 if( i_tmp > -1 )
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 );
1011 if( !psz_tmp )
1012 goto error;
1013 else if( *psz_tmp != '\0') {
1014 SCHRO_SET_ENUM(enc_filtering_list, ENC_PREFILTER, ENC_PREFILTER_TEXT, psz_tmp)
1016 free( psz_tmp );
1018 f_tmp = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH );
1019 if (f_tmp > -1)
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 );
1024 if( !psz_tmp )
1025 goto error;
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);
1037 else {
1038 msg_Err( p_enc, "Invalid codingmode: %s", psz_tmp );
1039 free( psz_tmp );
1040 goto error;
1042 free( psz_tmp );
1044 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MCBLK_SIZE );
1045 if( !psz_tmp )
1046 goto error;
1047 else if( *psz_tmp != '\0') {
1048 SCHRO_SET_ENUM(enc_block_size_list, ENC_MCBLK_SIZE, ENC_MCBLK_SIZE_TEXT, psz_tmp)
1050 free( psz_tmp );
1052 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP );
1053 if( !psz_tmp )
1054 goto error;
1055 else if( *psz_tmp != '\0') {
1056 SCHRO_SET_ENUM(enc_block_overlap_list, ENC_MCBLK_OVERLAP, ENC_MCBLK_OVERLAP_TEXT, psz_tmp)
1058 free( psz_tmp );
1060 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MVPREC );
1061 if( !psz_tmp )
1062 goto error;
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 );
1076 else {
1077 msg_Err( p_enc, "Invalid mv_precision: %s", psz_tmp );
1078 free( psz_tmp );
1079 goto error;
1082 free( 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 );
1089 if( !psz_tmp )
1090 goto error;
1091 else if( *psz_tmp != '\0') {
1092 SCHRO_SET_ENUM(enc_wavelet_list, ENC_DWTINTRA, ENC_DWTINTRA_TEXT, psz_tmp)
1094 free( psz_tmp );
1096 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_DWTINTER );
1097 if( !psz_tmp )
1098 goto error;
1099 else if( *psz_tmp != '\0') {
1100 SCHRO_SET_ENUM(enc_wavelet_list, ENC_DWTINTER, ENC_DWTINTER_TEXT, psz_tmp)
1102 free( psz_tmp );
1104 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTDEPTH );
1105 if( i_tmp > -1 )
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 );
1109 if( i_tmp > -1 )
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 );
1115 if( !psz_tmp )
1116 goto error;
1117 else if( *psz_tmp != '\0' ) {
1118 SCHRO_SET_ENUM(enc_perceptual_weighting_list, ENC_PWT, ENC_PWT_TEXT, psz_tmp)
1120 free( psz_tmp );
1122 f_tmp = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_PDIST );
1123 if (f_tmp >= 0)
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 );
1131 return VLC_ENOMEM;
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 );
1141 return VLC_ENOMEM;
1146 p_sys->started = 0;
1148 return VLC_SUCCESS;
1149 error:
1150 CloseEncoder( p_this );
1151 return VLC_EGENERIC;
1155 struct enc_picture_free_t
1157 picture_t *p_pic;
1158 encoder_t *p_enc;
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;
1170 if( !p_free )
1171 return;
1173 /* FIXME - who free the picture ??? */
1174 picture_Release ( p_free->p_pic );
1175 free(p_free);
1176 (void)frame;
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;
1188 if( !p_schroframe )
1189 return NULL;
1191 if( !p_pic )
1192 return NULL;
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;
1221 if(i!=0)
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 )
1236 uint32_t u_pos = 4;
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 );
1244 return 1;
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 );
1249 if( u_npo == 0 )
1250 u_npo = 13;
1251 u_pos += u_npo;
1253 return 0;
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;
1262 uint8_t *p_dst;
1263 SchroFrame *frame;
1264 int go = 1;
1266 if( !p_pic ) {
1267 if( !p_sys->started || p_sys->eos_pulled )
1268 return NULL;
1270 if( !p_sys->eos_signalled ) {
1271 p_sys->eos_signalled = 1;
1272 schro_encoder_end_of_stream( p_sys->p_schro);
1274 } else {
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 ) {
1286 date_t date;
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 );
1304 p_sys->started = 1;
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 );
1314 if( !frame )
1315 return NULL;
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
1325 * coded order */
1326 p_block = block_New( p_enc, 1 );
1327 if( !p_block )
1328 return NULL;
1329 p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
1330 block_FifoPut( p_sys->p_dts_fifo, p_block );
1331 p_block = NULL;
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 );
1341 if( !p_block )
1342 return NULL;
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 );
1345 p_block = NULL;
1351 SchroStateEnum state;
1352 state = schro_encoder_wait(p_sys->p_schro);
1353 switch( state )
1355 case SCHRO_STATE_NEED_FRAME:
1356 go = 0;
1357 break;
1358 case SCHRO_STATE_AGAIN:
1359 break;
1360 case SCHRO_STATE_END_OF_STREAM:
1361 p_sys->eos_pulled = 1;
1362 go = 0;
1363 break;
1364 case SCHRO_STATE_HAVE_BUFFER:
1366 SchroBuffer *enc_buf;
1367 uint32_t pic_num;
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);
1371 if( !p_block )
1372 return NULL;
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 )
1403 return NULL;
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;
1422 } else {
1423 p_block = NULL;
1425 break;
1427 default:
1428 break;
1430 } while(go);
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 );
1457 free( p_sys );