1 /*****************************************************************************
2 * schroedinger.c: Dirac decoder module making use of libschroedinger.
3 * (http://www.bbc.co.uk/rd/projects/dirac/index.shtml)
4 * (http://diracvideo.org)
5 *****************************************************************************
6 * Copyright (C) 2008-2010 the VideoLAN team
8 * Authors: Jonathan Rosser <jonathan.rosser@gmail.com>
9 * David Flynn <davidf at rd dot bbc.co.uk>
10 * Anuradha Suraparaju <asuraparaju at gmail dot com> (encoding)
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") };
63 #define ENC_CODINGMODE "auto_coding_mode"
64 #define ENC_CODINGMODE_TEXT N_("Automate picture coding mode")
65 #define ENC_CODINGMODE_LONGTEXT N_("Use the input picture to determine how to" \
66 " code it - interlaced or progressive")
68 static const char **ppsz_enc_options = NULL;
71 set_category( CAT_INPUT )
72 set_subcategory( SUBCAT_INPUT_VCODEC )
73 set_shortname( "Schroedinger" )
74 set_description( N_("Dirac video decoder using libschroedinger") )
75 set_capability( "decoder", 200 )
76 set_callbacks( OpenDecoder, CloseDecoder )
77 add_shortcut( "schroedinger" )
80 set_section( N_("Encoding") , NULL )
81 set_description( N_("Dirac video encoder using libschroedinger") )
82 set_capability( "encoder", 110 )
83 set_callbacks( OpenEncoder, CloseEncoder )
84 add_shortcut( "schroedinger", "schro" )
86 int i_numopts = schro_encoder_get_n_settings();
87 /* Allocate for schro encoder options + chroma format + coding mode
89 ppsz_enc_options = (const char **)malloc( sizeof( char * )*( i_numopts + 3 ) );
90 if( unlikely( ppsz_enc_options == NULL ) )
93 for( int i = 0; i < i_numopts; ++i ) {
94 const SchroEncoderSetting *p_setting = schro_encoder_get_setting_info( i );
95 bool b_advanced = ( strlen( p_setting->name ) > 6 && !strncmp( p_setting->name, "magic_ ", 6 ) );
96 char *p_cfg_setting_name = malloc( strlen( ENC_CFG_PREFIX ) + strlen( p_setting->name ) + 1 );
98 if( unlikely( p_cfg_setting_name == NULL ) )
101 strcpy( p_cfg_setting_name, ENC_CFG_PREFIX );
102 strcat( p_cfg_setting_name, p_setting->name );
104 ppsz_enc_options[i] = strdup( p_setting->name );
105 switch( p_setting->type ) {
106 case SCHRO_ENCODER_SETTING_TYPE_BOOLEAN:
107 add_bool( p_cfg_setting_name, p_setting->default_value, p_setting->name, p_setting->name, b_advanced );
109 case SCHRO_ENCODER_SETTING_TYPE_INT:
110 add_integer( p_cfg_setting_name, p_setting->default_value, p_setting->name, p_setting->name, b_advanced );
111 change_integer_range( p_setting->min, p_setting->max );
113 case SCHRO_ENCODER_SETTING_TYPE_DOUBLE:
114 add_float( p_cfg_setting_name, p_setting->default_value, p_setting->name, p_setting->name, b_advanced );
115 change_float_range( p_setting->min, p_setting->max );
117 case SCHRO_ENCODER_SETTING_TYPE_ENUM:
118 add_string( p_cfg_setting_name, p_setting->enum_list[(int)p_setting->default_value], p_setting->name, p_setting->name, b_advanced );
119 vlc_config_set( p_config, VLC_CONFIG_LIST, (int)(p_setting->max-p_setting->min+1), p_setting->enum_list, p_setting->enum_list, 0 );
124 free( p_cfg_setting_name );
127 ppsz_enc_options[i_numopts] = strdup( ENC_CHROMAFMT );
128 add_string( ENC_CFG_PREFIX ENC_CHROMAFMT, "420",
129 ENC_CHROMAFMT_TEXT, ENC_CHROMAFMT_LONGTEXT, false )
130 change_string_list( enc_chromafmt_list, enc_chromafmt_list_text, 0 );
132 ppsz_enc_options[i_numopts+1] = strdup( ENC_CODINGMODE );
133 add_bool( ENC_CFG_PREFIX ENC_CODINGMODE, true,
134 ENC_CODINGMODE_TEXT, ENC_CODINGMODE_LONGTEXT, false )
136 ppsz_enc_options[i_numopts+2] = NULL;
140 /*****************************************************************************
142 *****************************************************************************/
143 static picture_t *DecodeBlock ( decoder_t *p_dec, block_t **pp_block );
145 struct picture_free_t
151 /*****************************************************************************
152 * decoder_sys_t : Schroedinger decoder descriptor
153 *****************************************************************************/
160 mtime_t i_frame_pts_delta;
161 SchroDecoder *p_schro;
162 SchroVideoFormat *p_format;
165 /*****************************************************************************
166 * OpenDecoder: probe the decoder and return score
167 *****************************************************************************/
168 static int OpenDecoder( vlc_object_t *p_this )
170 decoder_t *p_dec = (decoder_t*)p_this;
171 decoder_sys_t *p_sys;
172 SchroDecoder *p_schro;
174 if( p_dec->fmt_in.i_codec != VLC_CODEC_DIRAC )
179 /* Allocate the memory needed to store the decoder's structure */
180 p_sys = malloc(sizeof(decoder_sys_t));
184 /* Initialise the schroedinger (and hence liboil libraries */
185 /* This does no allocation and is safe to call */
188 /* Initialise the schroedinger decoder */
189 if( !(p_schro = schro_decoder_new()) )
195 p_dec->p_sys = p_sys;
196 p_sys->p_schro = p_schro;
197 p_sys->p_format = NULL;
198 p_sys->i_lastpts = VLC_TS_INVALID;
199 p_sys->i_frame_pts_delta = 0;
201 /* Set output properties */
202 p_dec->fmt_out.i_cat = VIDEO_ES;
203 p_dec->fmt_out.i_codec = VLC_CODEC_I420;
206 p_dec->pf_decode_video = DecodeBlock;
211 /*****************************************************************************
212 * SetPictureFormat: Set the decoded picture params to the ones from the stream
213 *****************************************************************************/
214 static void SetVideoFormat( decoder_t *p_dec )
216 decoder_sys_t *p_sys = p_dec->p_sys;
218 p_sys->p_format = schro_decoder_get_video_format(p_sys->p_schro);
219 if( p_sys->p_format == NULL ) return;
221 p_sys->i_frame_pts_delta = INT64_C(1000000)
222 * p_sys->p_format->frame_rate_denominator
223 / p_sys->p_format->frame_rate_numerator;
225 switch( p_sys->p_format->chroma_format )
227 case SCHRO_CHROMA_420: p_dec->fmt_out.i_codec = VLC_CODEC_I420; break;
228 case SCHRO_CHROMA_422: p_dec->fmt_out.i_codec = VLC_CODEC_I422; break;
229 case SCHRO_CHROMA_444: p_dec->fmt_out.i_codec = VLC_CODEC_I444; break;
231 p_dec->fmt_out.i_codec = 0;
235 p_dec->fmt_out.video.i_visible_width = p_sys->p_format->clean_width;
236 p_dec->fmt_out.video.i_x_offset = p_sys->p_format->left_offset;
237 p_dec->fmt_out.video.i_width = p_sys->p_format->width;
239 p_dec->fmt_out.video.i_visible_height = p_sys->p_format->clean_height;
240 p_dec->fmt_out.video.i_y_offset = p_sys->p_format->top_offset;
241 p_dec->fmt_out.video.i_height = p_sys->p_format->height;
243 /* aspect_ratio_[numerator|denominator] describes the pixel aspect ratio */
244 p_dec->fmt_out.video.i_sar_num = p_sys->p_format->aspect_ratio_numerator;
245 p_dec->fmt_out.video.i_sar_den = p_sys->p_format->aspect_ratio_denominator;
247 p_dec->fmt_out.video.i_frame_rate =
248 p_sys->p_format->frame_rate_numerator;
249 p_dec->fmt_out.video.i_frame_rate_base =
250 p_sys->p_format->frame_rate_denominator;
253 /*****************************************************************************
254 * SchroFrameFree: schro_frame callback to release the associated picture_t
255 * When schro_decoder_reset() is called there will be pictures in the
256 * decoding pipeline that need to be released rather than displayed.
257 *****************************************************************************/
258 static void SchroFrameFree( SchroFrame *frame, void *priv)
260 struct picture_free_t *p_free = priv;
265 decoder_DeletePicture( p_free->p_dec, p_free->p_pic );
270 /*****************************************************************************
271 * CreateSchroFrameFromPic: wrap a picture_t in a SchroFrame
272 *****************************************************************************/
273 static SchroFrame *CreateSchroFrameFromPic( decoder_t *p_dec )
275 decoder_sys_t *p_sys = p_dec->p_sys;
276 SchroFrame *p_schroframe = schro_frame_new();
277 picture_t *p_pic = NULL;
278 struct picture_free_t *p_free;
283 p_pic = decoder_NewPicture( p_dec );
288 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_420;
289 if( p_sys->p_format->chroma_format == SCHRO_CHROMA_422 )
291 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_422;
293 else if( p_sys->p_format->chroma_format == SCHRO_CHROMA_444 )
295 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_444;
298 p_schroframe->width = p_sys->p_format->width;
299 p_schroframe->height = p_sys->p_format->height;
301 p_free = malloc( sizeof( *p_free ) );
302 p_free->p_pic = p_pic;
303 p_free->p_dec = p_dec;
304 schro_frame_set_free_callback( p_schroframe, SchroFrameFree, p_free );
306 for( int i=0; i<3; i++ )
308 p_schroframe->components[i].width = p_pic->p[i].i_visible_pitch;
309 p_schroframe->components[i].stride = p_pic->p[i].i_pitch;
310 p_schroframe->components[i].height = p_pic->p[i].i_visible_lines;
311 p_schroframe->components[i].length =
312 p_pic->p[i].i_pitch * p_pic->p[i].i_lines;
313 p_schroframe->components[i].data = p_pic->p[i].p_pixels;
317 p_schroframe->components[i].v_shift =
318 SCHRO_FRAME_FORMAT_V_SHIFT( p_schroframe->format );
319 p_schroframe->components[i].h_shift =
320 SCHRO_FRAME_FORMAT_H_SHIFT( p_schroframe->format );
324 p_pic->b_progressive = !p_sys->p_format->interlaced;
325 p_pic->b_top_field_first = p_sys->p_format->top_field_first;
326 p_pic->i_nb_fields = 2;
331 /*****************************************************************************
332 * SchroBufferFree: schro_buffer callback to release the associated block_t
333 *****************************************************************************/
334 static void SchroBufferFree( SchroBuffer *buf, void *priv )
336 block_t *p_block = priv;
341 block_Release( p_block );
345 /*****************************************************************************
346 * CloseDecoder: decoder destruction
347 *****************************************************************************/
348 static void CloseDecoder( vlc_object_t *p_this )
350 decoder_t *p_dec = (decoder_t *)p_this;
351 decoder_sys_t *p_sys = p_dec->p_sys;
353 schro_decoder_free( p_sys->p_schro );
357 /****************************************************************************
358 * DecodeBlock: the whole thing
359 ****************************************************************************
360 * Blocks need not be Dirac dataunit aligned.
361 * If a block has a PTS signaled, it applies to the first picture at or after p_block
363 * If this function returns a picture (!NULL), it is called again and the
364 * same block is resubmitted. To avoid this, set *pp_block to NULL;
365 * If this function returns NULL, the *pp_block is lost (and leaked).
366 * This function must free all blocks when finished with them.
367 ****************************************************************************/
368 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
370 decoder_sys_t *p_sys = p_dec->p_sys;
372 if( !pp_block ) return NULL;
375 block_t *p_block = *pp_block;
377 /* reset the decoder when seeking as the decode in progress is invalid */
378 /* discard the block as it is just a null magic block */
379 if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) {
380 schro_decoder_reset( p_sys->p_schro );
382 p_sys->i_lastpts = VLC_TS_INVALID;
383 block_Release( p_block );
388 SchroBuffer *p_schrobuffer;
389 p_schrobuffer = schro_buffer_new_with_data( p_block->p_buffer, p_block->i_buffer );
390 p_schrobuffer->free = SchroBufferFree;
391 p_schrobuffer->priv = p_block;
392 if( p_block->i_pts > VLC_TS_INVALID ) {
393 mtime_t *p_pts = malloc( sizeof(*p_pts) );
395 *p_pts = p_block->i_pts;
396 /* if this call fails, p_pts is freed automatically */
397 p_schrobuffer->tag = schro_tag_new( p_pts, free );
401 /* this stops the same block being fed back into this function if
402 * we were on the next iteration of this loop to output a picture */
404 schro_decoder_autoparse_push( p_sys->p_schro, p_schrobuffer );
405 /* DO NOT refer to p_block after this point, it may have been freed */
410 SchroFrame *p_schroframe;
412 int state = schro_decoder_autoparse_wait( p_sys->p_schro );
416 case SCHRO_DECODER_FIRST_ACCESS_UNIT:
417 SetVideoFormat( p_dec );
420 case SCHRO_DECODER_NEED_BITS:
423 case SCHRO_DECODER_NEED_FRAME:
424 p_schroframe = CreateSchroFrameFromPic( p_dec );
428 msg_Err( p_dec, "Could not allocate picture for decoder");
432 schro_decoder_add_output_picture( p_sys->p_schro, p_schroframe);
435 case SCHRO_DECODER_OK: {
436 SchroTag *p_tag = schro_decoder_get_picture_tag( p_sys->p_schro );
437 p_schroframe = schro_decoder_pull( p_sys->p_schro );
438 if( !p_schroframe || !p_schroframe->priv )
440 /* frame can't be one that was allocated by us
441 * -- no private data: discard */
442 if( p_tag ) schro_tag_free( p_tag );
443 if( p_schroframe ) schro_frame_unref( p_schroframe );
446 p_pic = ((struct picture_free_t*) p_schroframe->priv)->p_pic;
447 p_schroframe->priv = NULL;
451 /* free is handled by schro_frame_unref */
452 p_pic->date = *(mtime_t*) p_tag->value;
453 schro_tag_free( p_tag );
455 else if( p_sys->i_lastpts > VLC_TS_INVALID )
457 /* NB, this shouldn't happen since the packetizer does a
458 * very thorough job of inventing timestamps. The
459 * following is just a very rough fall back incase packetizer
461 /* maybe it would be better to set p_pic->b_force ? */
462 p_pic->date = p_sys->i_lastpts + p_sys->i_frame_pts_delta;
464 p_sys->i_lastpts = p_pic->date;
466 schro_frame_unref( p_schroframe );
469 case SCHRO_DECODER_EOS:
470 /* NB, the new api will not emit _EOS, it handles the reset internally */
473 case SCHRO_DECODER_ERROR:
474 msg_Err( p_dec, "SCHRO_DECODER_ERROR");
480 /*****************************************************************************
482 *****************************************************************************/
483 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
486 /*****************************************************************************
487 * picture_pts_t : store pts alongside picture number, not carried through
489 *****************************************************************************/
492 bool b_empty; /* entry is invalid */
493 uint32_t u_pnum; /* dirac picture number */
494 mtime_t i_pts; /* associated pts */
497 /*****************************************************************************
498 * encoder_sys_t : Schroedinger encoder descriptor
499 *****************************************************************************/
500 #define SCHRO_PTS_TLB_SIZE 256
506 SchroEncoder *p_schro;
507 SchroVideoFormat *p_format;
509 bool b_auto_field_coding;
511 uint32_t i_input_picnum;
512 block_fifo_t *p_dts_fifo;
516 struct picture_pts_t pts_tlb[SCHRO_PTS_TLB_SIZE];
517 mtime_t i_pts_offset;
518 mtime_t i_field_time;
520 bool b_eos_signalled;
526 unsigned int i_height;
528 SchroVideoFormatEnum i_vf;
529 } schro_format_guess[] = {
530 /* Important: Keep this list ordered in ascending picture height */
531 {1, 0, SCHRO_VIDEO_FORMAT_CUSTOM},
532 {120, 15, SCHRO_VIDEO_FORMAT_QSIF},
533 {144, 12, SCHRO_VIDEO_FORMAT_QCIF},
534 {240, 15, SCHRO_VIDEO_FORMAT_SIF},
535 {288, 12, SCHRO_VIDEO_FORMAT_CIF},
536 {480, 30, SCHRO_VIDEO_FORMAT_SD480I_60},
537 {480, 15, SCHRO_VIDEO_FORMAT_4SIF},
538 {576, 12, SCHRO_VIDEO_FORMAT_4CIF},
539 {576, 25, SCHRO_VIDEO_FORMAT_SD576I_50},
540 {720, 50, SCHRO_VIDEO_FORMAT_HD720P_50},
541 {720, 60, SCHRO_VIDEO_FORMAT_HD720P_60},
542 {1080, 24, SCHRO_VIDEO_FORMAT_DC2K_24},
543 {1080, 25, SCHRO_VIDEO_FORMAT_HD1080I_50},
544 {1080, 30, SCHRO_VIDEO_FORMAT_HD1080I_60},
545 {1080, 50, SCHRO_VIDEO_FORMAT_HD1080P_50},
546 {1080, 60, SCHRO_VIDEO_FORMAT_HD1080P_60},
547 {2160, 24, SCHRO_VIDEO_FORMAT_DC4K_24},
551 /*****************************************************************************
552 * ResetPTStlb: Purge all entries in @p_enc@'s PTS-tlb
553 *****************************************************************************/
554 static void ResetPTStlb( encoder_t *p_enc )
556 encoder_sys_t *p_sys = p_enc->p_sys;
557 for( int i=0; i<SCHRO_PTS_TLB_SIZE; i++ )
559 p_sys->pts_tlb[i].b_empty = true;
564 /*****************************************************************************
565 * StorePicturePTS: Store the PTS value for a particular picture number
566 *****************************************************************************/
567 static void StorePicturePTS( encoder_t *p_enc, uint32_t u_pnum, mtime_t i_pts )
569 encoder_sys_t *p_sys = p_enc->p_sys;
571 for( int i=0; i<SCHRO_PTS_TLB_SIZE; i++ )
573 if( p_sys->pts_tlb[i].b_empty )
575 p_sys->pts_tlb[i].u_pnum = u_pnum;
576 p_sys->pts_tlb[i].i_pts = i_pts;
577 p_sys->pts_tlb[i].b_empty = false;
583 msg_Err( p_enc, "Could not store PTS %"PRId64" for frame %u", i_pts, u_pnum );
586 /*****************************************************************************
587 * GetPicturePTS: Retrieve the PTS value for a particular picture number
588 *****************************************************************************/
589 static mtime_t GetPicturePTS( encoder_t *p_enc, uint32_t u_pnum )
591 encoder_sys_t *p_sys = p_enc->p_sys;
593 for( int i=0; i<SCHRO_PTS_TLB_SIZE; i++ )
595 if( !p_sys->pts_tlb[i].b_empty &&
596 p_sys->pts_tlb[i].u_pnum == u_pnum )
598 p_sys->pts_tlb[i].b_empty = true;
599 return p_sys->pts_tlb[i].i_pts;
603 msg_Err( p_enc, "Could not retrieve PTS for picture %u", u_pnum );
607 static inline bool SchroSetEnum( const encoder_t *p_enc, const SchroEncoderSetting *p_setting, const char *psz_value ) {
608 encoder_sys_t *p_sys = p_enc->p_sys;
609 if( psz_value && p_setting && p_setting->type == SCHRO_ENCODER_SETTING_TYPE_ENUM ) {
611 int i_list_size = p_setting->max - p_setting->min + 1;
612 for( int i = 0; i < i_list_size; ++i ) {
613 if( strcmp( p_setting->enum_list[i], psz_value ) )
615 i_index = p_setting->min + i;
616 schro_encoder_setting_set_double( p_sys->p_schro, p_setting->name, i_index );
619 if( i_index == -1 ) {
620 msg_Err( p_enc, "Invalid %s: %s", p_setting->name, psz_value );
626 static bool SetEncChromaFormat( encoder_t *p_enc, uint32_t i_codec )
628 encoder_sys_t *p_sys = p_enc->p_sys;
632 p_enc->fmt_in.i_codec = i_codec;
633 p_enc->fmt_in.video.i_bits_per_pixel = 12;
634 p_sys->p_format->chroma_format = SCHRO_CHROMA_420;
637 p_enc->fmt_in.i_codec = i_codec;
638 p_enc->fmt_in.video.i_bits_per_pixel = 16;
639 p_sys->p_format->chroma_format = SCHRO_CHROMA_422;
642 p_enc->fmt_in.i_codec = i_codec;
643 p_enc->fmt_in.video.i_bits_per_pixel = 24;
644 p_sys->p_format->chroma_format = SCHRO_CHROMA_444;
654 /*****************************************************************************
655 * OpenEncoder: probe the encoder and return score
656 *****************************************************************************/
657 static int OpenEncoder( vlc_object_t *p_this )
659 encoder_t *p_enc = (encoder_t *)p_this;
660 encoder_sys_t *p_sys = p_enc->p_sys;
666 if( p_enc->fmt_out.i_codec != VLC_CODEC_DIRAC &&
672 if( !p_enc->fmt_in.video.i_frame_rate || !p_enc->fmt_in.video.i_frame_rate_base ||
673 !p_enc->fmt_in.video.i_height || !p_enc->fmt_in.video.i_width )
675 msg_Err( p_enc, "Framerate and picture dimensions must be non-zero" );
679 /* Allocate the memory needed to store the decoder's structure */
680 if( ( p_sys = calloc( 1, sizeof( *p_sys ) ) ) == NULL )
683 p_enc->p_sys = p_sys;
684 p_enc->pf_encode_video = Encode;
685 p_enc->fmt_out.i_codec = VLC_CODEC_DIRAC;
686 p_enc->fmt_out.i_cat = VIDEO_ES;
688 if( ( p_sys->p_dts_fifo = block_FifoNew() ) == NULL )
690 CloseEncoder( p_this );
694 ResetPTStlb( p_enc );
696 /* guess the video format based upon number of lines and picture height */
698 SchroVideoFormatEnum guessed_video_fmt = SCHRO_VIDEO_FORMAT_CUSTOM;
699 /* Pick the dirac_video_format in this order of preference:
700 * 1. an exact match in frame height and an approximate fps match
701 * 2. the previous preset with a smaller number of lines.
705 if( schro_format_guess[i].i_height > p_enc->fmt_in.video.i_height )
707 guessed_video_fmt = schro_format_guess[i-1].i_vf;
710 if( schro_format_guess[i].i_height != p_enc->fmt_in.video.i_height )
712 int src_fps = p_enc->fmt_in.video.i_frame_rate / p_enc->fmt_in.video.i_frame_rate_base;
713 int delta_fps = abs( schro_format_guess[i].i_approx_fps - src_fps );
717 guessed_video_fmt = schro_format_guess[i].i_vf;
719 } while( schro_format_guess[++i].i_height );
722 p_sys->p_schro = schro_encoder_new();
723 if( !p_sys->p_schro ) {
724 msg_Err( p_enc, "Failed to initialize libschroedinger encoder" );
727 schro_encoder_set_packet_assembly( p_sys->p_schro, true );
729 if( !( p_sys->p_format = schro_encoder_get_video_format( p_sys->p_schro ) ) ) {
730 msg_Err( p_enc, "Failed to get Schroedigner video format" );
731 schro_encoder_free( p_sys->p_schro );
735 /* initialise the video format parameters to the guessed format */
736 schro_video_format_set_std_video_format( p_sys->p_format, guessed_video_fmt );
738 /* constants set from the input video format */
739 p_sys->p_format->width = p_enc->fmt_in.video.i_width;
740 p_sys->p_format->height = p_enc->fmt_in.video.i_height;
741 p_sys->p_format->frame_rate_numerator = p_enc->fmt_in.video.i_frame_rate;
742 p_sys->p_format->frame_rate_denominator = p_enc->fmt_in.video.i_frame_rate_base;
743 unsigned u_asr_num, u_asr_den;
744 vlc_ureduce( &u_asr_num, &u_asr_den,
745 p_enc->fmt_in.video.i_sar_num,
746 p_enc->fmt_in.video.i_sar_den, 0 );
747 p_sys->p_format->aspect_ratio_numerator = u_asr_num;
748 p_sys->p_format->aspect_ratio_denominator = u_asr_den;
750 config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
752 int i_numopts = schro_encoder_get_n_settings();
754 for( int i = 0; i < i_numopts; ++i ) {
755 const SchroEncoderSetting *p_setting = schro_encoder_get_setting_info( i );
756 char *p_cfg_setting_name = malloc( strlen( ENC_CFG_PREFIX ) + strlen( p_setting->name ) + 1 );
757 if( unlikely( p_cfg_setting_name == NULL ) )
760 strcpy( p_cfg_setting_name, ENC_CFG_PREFIX );
761 strcat( p_cfg_setting_name, p_setting->name );
763 switch( p_setting->type ) {
764 case SCHRO_ENCODER_SETTING_TYPE_BOOLEAN:
765 schro_encoder_setting_set_double ( p_sys->p_schro, p_setting->name, var_GetBool( p_enc, p_cfg_setting_name ) );
767 case SCHRO_ENCODER_SETTING_TYPE_INT:
768 i_tmp = var_GetInteger( p_enc, p_cfg_setting_name );
769 schro_encoder_setting_set_double( p_sys->p_schro, p_setting->name, i_tmp );
770 /* A kludge to set bitrate to the value in sout-transcode-vb */
771 if( !strcmp( p_setting->name, "bitrate" ) ) {
772 if( i_tmp == p_setting->default_value )
773 schro_encoder_setting_set_double( p_sys->p_schro, p_setting->name, p_enc->fmt_out.i_bitrate );
774 p_enc->fmt_out.i_bitrate = schro_encoder_setting_get_double( p_sys->p_schro, p_setting->name );
777 case SCHRO_ENCODER_SETTING_TYPE_DOUBLE:
778 f_tmp = var_GetFloat( p_enc, p_cfg_setting_name );
780 schro_encoder_setting_set_double( p_sys->p_schro, p_setting->name, f_tmp );
782 case SCHRO_ENCODER_SETTING_TYPE_ENUM:
783 psz_tmp = var_GetString( p_enc, p_cfg_setting_name );
786 else if( *psz_tmp != '\0' ) {
787 if( !SchroSetEnum( p_enc, p_setting, psz_tmp ) ) {
797 free( p_cfg_setting_name );
800 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CHROMAFMT );
805 if( !strcmp( psz_tmp, "420" ) ) {
806 i_codec = VLC_CODEC_I420;
808 else if( !strcmp( psz_tmp, "422" ) ) {
809 i_codec = VLC_CODEC_I422;
811 else if( !strcmp( psz_tmp, "444" ) ) {
812 i_codec = VLC_CODEC_I444;
815 msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
819 SetEncChromaFormat( p_enc, i_codec );
824 b_tmp = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_CODINGMODE );
826 p_sys->b_auto_field_coding = true;
828 p_sys->b_auto_field_coding = false;
834 CloseEncoder( p_this );
839 struct enc_picture_free_t
845 /*****************************************************************************
846 * EncSchroFrameFree: schro_frame callback to release the associated picture_t
847 * When schro_encoder_reset() is called there will be pictures in the
848 * encoding pipeline that need to be released rather than displayed.
849 *****************************************************************************/
850 static void EncSchroFrameFree( SchroFrame *frame, void *priv )
852 struct enc_picture_free_t *p_free = priv;
857 picture_Release( p_free->p_pic );
862 /*****************************************************************************
863 * CreateSchroFrameFromPic: wrap a picture_t in a SchroFrame
864 *****************************************************************************/
865 static SchroFrame *CreateSchroFrameFromInputPic( encoder_t *p_enc, picture_t *p_pic )
867 encoder_sys_t *p_sys = p_enc->p_sys;
868 SchroFrame *p_schroframe = schro_frame_new();
869 struct enc_picture_free_t *p_free;
877 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_420;
878 if( p_sys->p_format->chroma_format == SCHRO_CHROMA_422 )
880 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_422;
882 else if( p_sys->p_format->chroma_format == SCHRO_CHROMA_444 )
884 p_schroframe->format = SCHRO_FRAME_FORMAT_U8_444;
887 p_schroframe->width = p_sys->p_format->width;
888 p_schroframe->height = p_sys->p_format->height;
890 p_free = malloc( sizeof( *p_free ) );
891 if( unlikely( p_free == NULL ) ) {
892 schro_frame_unref( p_schroframe );
896 p_free->p_pic = p_pic;
897 p_free->p_enc = p_enc;
898 schro_frame_set_free_callback( p_schroframe, EncSchroFrameFree, p_free );
900 for( int i=0; i<3; i++ )
902 p_schroframe->components[i].width = p_pic->p[i].i_visible_pitch;
903 p_schroframe->components[i].stride = p_pic->p[i].i_pitch;
904 p_schroframe->components[i].height = p_pic->p[i].i_visible_lines;
905 p_schroframe->components[i].length =
906 p_pic->p[i].i_pitch * p_pic->p[i].i_lines;
907 p_schroframe->components[i].data = p_pic->p[i].p_pixels;
911 p_schroframe->components[i].v_shift =
912 SCHRO_FRAME_FORMAT_V_SHIFT( p_schroframe->format );
913 p_schroframe->components[i].h_shift =
914 SCHRO_FRAME_FORMAT_H_SHIFT( p_schroframe->format );
921 /* Attempt to find dirac picture number in an encapsulation unit */
922 static int ReadDiracPictureNumber( uint32_t *p_picnum, block_t *p_block )
925 /* protect against falling off the edge */
926 while( u_pos + 13 < p_block->i_buffer )
928 /* find the picture startcode */
929 if( p_block->p_buffer[u_pos] & 0x08 )
931 *p_picnum = GetDWBE( p_block->p_buffer + u_pos + 9 );
934 /* skip to the next dirac data unit */
935 uint32_t u_npo = GetDWBE( p_block->p_buffer + u_pos + 1 );
936 assert( u_npo <= UINT32_MAX - u_pos );
945 static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
947 encoder_sys_t *p_sys = p_enc->p_sys;
948 block_t *p_block, *p_output_chain = NULL;
953 if( !p_sys->started || p_sys->b_eos_pulled )
956 if( !p_sys->b_eos_signalled ) {
957 p_sys->b_eos_signalled = 1;
958 schro_encoder_end_of_stream( p_sys->p_schro );
961 /* we only know if the sequence is interlaced when the first
962 * picture arrives, so final setup is done here */
963 /* XXX todo, detect change of interlace */
964 p_sys->p_format->interlaced = !p_pic->b_progressive;
965 p_sys->p_format->top_field_first = p_pic->b_top_field_first;
967 if( p_sys->b_auto_field_coding )
968 schro_encoder_setting_set_double( p_sys->p_schro, "interlaced_coding", !p_pic->b_progressive );
971 if( !p_sys->started ) {
974 if( p_pic->format.i_chroma != p_enc->fmt_in.i_codec ) {
975 char chroma_in[5], chroma_out[5];
976 vlc_fourcc_to_char( p_pic->format.i_chroma, chroma_in );
978 chroma_out[4] = '\0';
979 vlc_fourcc_to_char( p_enc->fmt_in.i_codec, chroma_out );
980 msg_Warn( p_enc, "Resetting chroma from %s to %s", chroma_out, chroma_in );
981 if( !SetEncChromaFormat( p_enc, p_pic->format.i_chroma ) ) {
982 msg_Err( p_enc, "Could not reset chroma format to %s", chroma_in );
987 date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base );
988 /* FIXME - Unlike dirac-research codec Schro doesn't have a function that returns the delay in pics yet.
991 date_Increment( &date, 1 );
992 p_sys->i_pts_offset = date_Get( &date );
993 if( schro_encoder_setting_get_double( p_sys->p_schro, "interlaced_coding" ) > 0.0 ) {
994 date_Set( &date, 0 );
995 date_Increment( &date, 1);
996 p_sys->i_field_time = date_Get( &date ) / 2;
999 schro_video_format_set_std_signal_range( p_sys->p_format, SCHRO_SIGNAL_RANGE_8BIT_VIDEO );
1000 schro_encoder_set_video_format( p_sys->p_schro, p_sys->p_format );
1001 schro_encoder_start( p_sys->p_schro );
1005 if( !p_sys->b_eos_signalled ) {
1006 /* create a schro frame from the input pic and load */
1007 /* Increase ref count by 1 so that the picture is not freed until
1008 Schro finishes with it */
1009 picture_Hold( p_pic );
1011 p_frame = CreateSchroFrameFromInputPic( p_enc, p_pic );
1014 schro_encoder_push_frame( p_sys->p_schro, p_frame );
1017 /* store pts in a lookaside buffer, so that the same pts may
1018 * be used for the picture in coded order */
1019 StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date );
1020 p_sys->i_input_picnum++;
1022 /* store dts in a queue, so that they appear in order in
1024 p_block = block_New( p_enc, 1 );
1027 p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
1028 block_FifoPut( p_sys->p_dts_fifo, p_block );
1031 /* for field coding mode, insert an extra value into both the
1032 * pts lookaside buffer and dts queue, offset to correspond
1033 * to a one field delay. */
1034 if( schro_encoder_setting_get_double( p_sys->p_schro, "interlaced_coding" ) > 0.0 ) {
1035 StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time );
1036 p_sys->i_input_picnum++;
1038 p_block = block_New( p_enc, 1 );
1041 p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time;
1042 block_FifoPut( p_sys->p_dts_fifo, p_block );
1049 SchroStateEnum state;
1050 state = schro_encoder_wait( p_sys->p_schro );
1053 case SCHRO_STATE_NEED_FRAME:
1056 case SCHRO_STATE_AGAIN:
1058 case SCHRO_STATE_END_OF_STREAM:
1059 p_sys->b_eos_pulled = 1;
1062 case SCHRO_STATE_HAVE_BUFFER:
1064 SchroBuffer *p_enc_buf;
1066 int i_presentation_frame;
1067 p_enc_buf = schro_encoder_pull( p_sys->p_schro, &i_presentation_frame );
1068 p_block = block_New( p_enc, p_enc_buf->length );
1072 memcpy( p_block->p_buffer, p_enc_buf->data, p_enc_buf->length );
1073 schro_buffer_unref( p_enc_buf );
1075 /* Presence of a Sequence header indicates a seek point */
1076 if( 0 == p_block->p_buffer[4] )
1078 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
1080 if( !p_enc->fmt_out.p_extra ) {
1081 const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
1082 uint32_t len = GetDWBE( p_block->p_buffer + 5 );
1083 /* if it hasn't been done so far, stash a copy of the
1084 * sequence header for muxers such as ogg */
1085 /* The OggDirac spec advises that a Dirac EOS DataUnit
1086 * is appended to the sequence header to allow guard
1087 * against poor streaming servers */
1088 /* XXX, should this be done using the packetizer ? */
1089 p_enc->fmt_out.p_extra = malloc( len + sizeof( eos ) );
1090 if( !p_enc->fmt_out.p_extra )
1092 memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len );
1093 memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof( eos ) );
1094 SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len );
1095 p_enc->fmt_out.i_extra = len + sizeof( eos );
1099 if( ReadDiracPictureNumber( &u_pic_num, p_block ) ) {
1100 block_t *p_dts_block = block_FifoGet( p_sys->p_dts_fifo );
1101 p_block->i_dts = p_dts_block->i_dts;
1102 p_block->i_pts = GetPicturePTS( p_enc, u_pic_num );
1103 block_Release( p_dts_block );
1104 block_ChainAppend( &p_output_chain, p_block );
1106 /* End of sequence */
1107 block_ChainAppend( &p_output_chain, p_block );
1116 return p_output_chain;
1119 /*****************************************************************************
1120 * CloseEncoder: Schro encoder destruction
1121 *****************************************************************************/
1122 static void CloseEncoder( vlc_object_t *p_this )
1124 encoder_t *p_enc = (encoder_t *)p_this;
1125 encoder_sys_t *p_sys = p_enc->p_sys;
1127 /* Free the encoder resources */
1128 if( p_sys->p_schro )
1129 schro_encoder_free( p_sys->p_schro );
1131 free( p_sys->p_format );
1133 if( p_sys->p_dts_fifo )
1134 block_FifoRelease( p_sys->p_dts_fifo );
1136 block_ChainRelease( p_sys->p_chain );