1 /*****************************************************************************
2 * dirac.c: Dirac encoder module making use of libdirac (dirac-research).
3 * (http://www.bbc.co.uk/rd/projects/dirac/index.shtml)
5 * ## NB, this is a temporary encoder only module until schroedinger
6 * ## offers superior encoding quality than dirac-research
8 *****************************************************************************
9 * Copyright (C) 2004-2008 the VideoLAN team
12 * Authors: Gildas Bazin <gbazin@videolan.org>
13 * Rewritten: David Flynn <davidf at rd.bbc.co.uk>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
28 *****************************************************************************/
30 /*****************************************************************************
32 *****************************************************************************/
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_codec.h>
45 #include <libdirac_encoder/dirac_encoder.h>
47 #ifndef DIRAC_RESEARCH_VERSION_ATLEAST
48 # define DIRAC_RESEARCH_VERSION_ATLEAST(x,y,z) 0
51 /*****************************************************************************
53 *****************************************************************************/
54 static int OpenEncoder( vlc_object_t
*p_this
);
55 static void CloseEncoder( vlc_object_t
*p_this
);
56 static block_t
*Encode( encoder_t
*p_enc
, picture_t
*p_pict
);
58 #define ENC_CFG_PREFIX "sout-dirac-"
60 #define ENC_QUALITY_FACTOR "quality"
61 #define ENC_QUALITY_FACTOR_TEXT N_("Constant quality factor")
62 #define ENC_QUALITY_FACTOR_LONGTEXT N_("If bitrate=0, use this value for constant quality")
64 #define ENC_TARGETRATE "bitrate"
65 #define ENC_TARGETRATE_TEXT N_("CBR bitrate (kbps)")
66 #define ENC_TARGETRATE_LONGTEXT N_("A value > 0 enables constant bitrate mode")
68 #define ENC_LOSSLESS "lossless"
69 #define ENC_LOSSLESS_TEXT N_("Enable lossless coding")
70 #define ENC_LOSSLESS_LONGTEXT N_("Lossless coding ignores bitrate and quality settings, " \
71 "allowing for perfect reproduction of the original")
73 #define ENC_PREFILTER "prefilter"
74 #define ENC_PREFILTER_TEXT N_("Prefilter")
75 #define ENC_PREFILTER_LONGTEXT N_("Enable adaptive prefiltering")
76 static const char *const enc_prefilter_list
[] =
77 { "none", "cwm", "rectlp", "diaglp" };
78 static const char *const enc_prefilter_list_text
[] =
79 { N_("none"), N_("Centre Weighted Median"),
80 N_("Rectangular Linear Phase"), N_("Diagonal Linear Phase") };
82 #define ENC_PREFILTER_STRENGTH "prefilter-strength"
83 #define ENC_PREFILTER_STRENGTH_TEXT N_("Amount of prefiltering")
84 #define ENC_PREFILTER_STRENGTH_LONGTEXT N_("Higher value implies more prefiltering")
86 #define ENC_CHROMAFMT "chroma-fmt"
87 #define ENC_CHROMAFMT_TEXT N_("Chroma format")
88 #define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
89 "conversion of the video into that format")
90 static const char *const enc_chromafmt_list
[] =
91 { "420", "422", "444" };
92 static const char *const enc_chromafmt_list_text
[] =
93 { N_("4:2:0"), N_("4:2:2"), N_("4:4:4") };
95 #define ENC_L1SEP "l1-sep"
96 #define ENC_L1SEP_TEXT N_("Distance between 'P' frames")
97 #define ENC_L1SEP_LONGTEXT ENC_L1SEP_TEXT
99 #define ENC_L1NUM "num-l1"
100 #define ENC_L1NUM_TEXT N_("Number of 'P' frames per GOP")
101 #define ENC_L1NUM_LONGTEXT ENC_L1NUM_TEXT
103 #define ENC_CODINGMODE "coding-mode"
104 #define ENC_CODINGMODE_TEXT N_("Picture coding mode")
105 #define ENC_CODINGMODE_LONGTEXT N_("Field coding is where interlaced fields are coded" \
106 " separately as opposed to a pseudo-progressive frame")
107 static const char *const enc_codingmode_list
[] =
108 { "auto", "progressive", "field" };
109 static const char *const enc_codingmode_list_text
[] =
110 { N_("auto - let encoder decide based upon input (Best)"),
111 N_("force coding frame as single picture"),
112 N_("force coding frame as separate interlaced fields"),
115 #define ENC_MCBLK_WIDTH "mc-blk-width"
116 #define ENC_MCBLK_WIDTH_TEXT N_("Width of motion compensation blocks")
117 #define ENC_MCBLK_WIDTH_LONGTEXT ""
119 #define ENC_MCBLK_HEIGHT "mc-blk-height"
120 #define ENC_MCBLK_HEIGHT_TEXT N_("Height of motion compensation blocks")
121 #define ENC_MCBLK_HEIGHT_LONGTEXT ""
123 /* also known as XBSEP and YBSEP */
124 #define ENC_MCBLK_OVERLAP "mc-blk-overlap"
125 #define ENC_MCBLK_OVERLAP_TEXT N_("Block overlap (%)")
126 #define ENC_MCBLK_OVERLAP_LONGTEXT N_("Amount that each motion block should " \
127 "be overlapped by its neighbours")
129 /* advanced option only */
130 #define ENC_MCBLK_XBLEN "mc-blk-xblen"
131 #define ENC_MCBLK_XBLEN_TEXT N_("xblen")
132 #define ENC_MCBLK_XBLEN_LONGTEXT N_("Total horizontal block length including overlaps")
134 /* advanded option only */
135 #define ENC_MCBLK_YBLEN "mc-blk-yblen"
136 #define ENC_MCBLK_YBLEN_TEXT N_("yblen")
137 #define ENC_MCBLK_YBLEN_LONGTEXT N_("Total vertical block length including overlaps")
139 #define ENC_MVPREC "mv-prec"
140 #define ENC_MVPREC_TEXT N_("Motion vector precision")
141 #define ENC_MVPREC_LONGTEXT N_("Motion vector precision in pels.")
142 static const char *const enc_mvprec_list
[] =
143 { "1", "1/2", "1/4", "1/8" };
145 #define ENC_ME_SIMPLESEARCH "me-simple-search"
146 #define ENC_ME_SIMPLESEARCH_TEXT N_("Simple ME search area x:y")
147 #define ENC_ME_SIMPLESEARCH_LONGTEXT N_("(Not recommended) Perform a simple (non hierarchical " \
148 "block matching motion vector search with search range " \
151 #define ENC_ME_COMBINED "me-combined"
152 #define ENC_ME_COMBINED_TEXT N_("Three component motion estimation")
153 #define ENC_ME_COMBINED_LONGTEXT N_("Use chroma as part of the motion estimation process")
155 #define ENC_DWTINTRA "dwt-intra"
156 #define ENC_DWTINTRA_TEXT N_("Intra picture DWT filter")
157 #define ENC_DWTINTRA_LONGTEXT ENC_DWTINTRA_TEXT
159 #define ENC_DWTINTER "dwt-inter"
160 #define ENC_DWTINTER_TEXT N_("Inter picture DWT filter")
161 #define ENC_DWTINTER_LONGTEXT ENC_DWTINTER_TEXT
163 #define ENC_DWTDEPTH "dwt-depth"
164 #define ENC_DWTDEPTH_TEXT N_("Number of DWT iterations")
165 #define ENC_DWTDEPTH_LONGTEXT N_("Also known as DWT levels")
167 /* advanced option only */
168 #define ENC_MULTIQUANT "multi-quant"
169 #define ENC_MULTIQUANT_TEXT N_("Enable multiple quantizers")
170 #define ENC_MULTIQUANT_LONGTEXT N_("Enable multiple quantizers per subband (one per codeblock)")
172 /* advanced option only */
173 #define ENC_SPARTITION "spartition"
174 #define ENC_SPARTITION_TEXT N_("Enable spatial partitioning")
175 #define ENC_SPARTITION_LONGTEXT ENC_SPARTITION_TEXT
177 #define ENC_NOAC "noac"
178 #define ENC_NOAC_TEXT N_("Disable arithmetic coding")
179 #define ENC_NOAC_LONGTEXT N_("Use variable length codes instead, useful for very high bitrates")
181 /* visual modelling */
182 /* advanced option only */
183 #define ENC_CPD "cpd"
184 #define ENC_CPD_TEXT N_("cycles per degree")
185 #define ENC_CPD_LONGTEXT ENC_CPD_TEXT
187 static const char *const ppsz_enc_options
[] = {
188 ENC_QUALITY_FACTOR
, ENC_TARGETRATE
, ENC_LOSSLESS
, ENC_PREFILTER
, ENC_PREFILTER_STRENGTH
,
189 ENC_CHROMAFMT
, ENC_L1SEP
, ENC_L1NUM
, ENC_CODINGMODE
,
190 ENC_MCBLK_WIDTH
, ENC_MCBLK_HEIGHT
, ENC_MCBLK_OVERLAP
,
191 ENC_MVPREC
, ENC_ME_SIMPLESEARCH
, ENC_ME_COMBINED
,
192 ENC_DWTINTRA
, ENC_DWTINTER
, ENC_DWTDEPTH
,
193 ENC_MULTIQUANT
, ENC_SPARTITION
, ENC_NOAC
,
199 /*****************************************************************************
201 *****************************************************************************/
204 set_category( CAT_INPUT
)
205 set_subcategory( SUBCAT_INPUT_VCODEC
)
206 set_description( N_("Dirac video encoder using dirac-research library") )
207 set_shortname( "Dirac" )
208 set_capability( "encoder", 100 )
209 set_callbacks( OpenEncoder
, CloseEncoder
)
211 add_float( ENC_CFG_PREFIX ENC_QUALITY_FACTOR
, 5.5,
212 ENC_QUALITY_FACTOR_TEXT
, ENC_QUALITY_FACTOR_LONGTEXT
, false )
213 change_float_range(0., 10.);
215 add_integer( ENC_CFG_PREFIX ENC_TARGETRATE
, -1,
216 ENC_TARGETRATE_TEXT
, ENC_TARGETRATE_LONGTEXT
, false )
217 change_integer_range(-1, INT_MAX
);
219 add_bool( ENC_CFG_PREFIX ENC_LOSSLESS
, false,
220 ENC_LOSSLESS_TEXT
, ENC_LOSSLESS_LONGTEXT
, false )
222 add_string( ENC_CFG_PREFIX ENC_PREFILTER
, "diaglp",
223 ENC_PREFILTER_TEXT
, ENC_PREFILTER_LONGTEXT
, false )
224 change_string_list( enc_prefilter_list
, enc_prefilter_list_text
, 0 );
226 add_integer( ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH
, 1,
227 ENC_PREFILTER_STRENGTH_TEXT
, ENC_PREFILTER_STRENGTH_LONGTEXT
, false )
228 change_integer_range(0, 10);
230 add_string( ENC_CFG_PREFIX ENC_CHROMAFMT
, "420",
231 ENC_CHROMAFMT_TEXT
, ENC_CHROMAFMT_LONGTEXT
, false )
232 change_string_list( enc_chromafmt_list
, enc_chromafmt_list_text
, 0 );
234 add_integer( ENC_CFG_PREFIX ENC_L1SEP
, -1,
235 ENC_L1SEP_TEXT
, ENC_L1SEP_LONGTEXT
, false )
236 change_integer_range(-1, INT_MAX
);
238 add_integer( ENC_CFG_PREFIX ENC_L1NUM
, -1,
239 ENC_L1NUM_TEXT
, ENC_L1NUM_LONGTEXT
, false )
240 change_integer_range(-1, INT_MAX
);
242 add_string( ENC_CFG_PREFIX ENC_CODINGMODE
, "auto",
243 ENC_CODINGMODE_TEXT
, ENC_CODINGMODE_LONGTEXT
, false )
244 change_string_list( enc_codingmode_list
, enc_codingmode_list_text
, 0 );
246 add_string( ENC_CFG_PREFIX ENC_MVPREC
, "1/2",
247 ENC_MVPREC_TEXT
, ENC_MVPREC_LONGTEXT
, false )
248 change_string_list( enc_mvprec_list
, enc_mvprec_list
, 0 );
250 add_integer( ENC_CFG_PREFIX ENC_MCBLK_WIDTH
, -1,
251 ENC_MCBLK_WIDTH_TEXT
, ENC_MCBLK_WIDTH_LONGTEXT
, false )
252 change_integer_range(-1, INT_MAX
);
254 add_integer( ENC_CFG_PREFIX ENC_MCBLK_HEIGHT
, -1,
255 ENC_MCBLK_HEIGHT
, ENC_MCBLK_HEIGHT_LONGTEXT
, false )
256 change_integer_range(-1, INT_MAX
);
258 add_integer( ENC_CFG_PREFIX ENC_MCBLK_OVERLAP
, -1,
259 ENC_MCBLK_OVERLAP_TEXT
, ENC_MCBLK_OVERLAP_LONGTEXT
, false )
260 change_integer_range(-1, 100);
262 /* advanced option only */
263 add_integer( ENC_CFG_PREFIX ENC_MCBLK_XBLEN
, -1,
264 ENC_MCBLK_XBLEN_TEXT
, ENC_MCBLK_XBLEN_LONGTEXT
, true )
265 change_integer_range(-1, INT_MAX
);
266 /* advanced option only */
267 add_integer( ENC_CFG_PREFIX ENC_MCBLK_YBLEN
, -1,
268 ENC_MCBLK_YBLEN_TEXT
, ENC_MCBLK_YBLEN_LONGTEXT
, true )
269 change_integer_range(-1, INT_MAX
);
271 add_string( ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH
, "",
272 ENC_ME_SIMPLESEARCH_TEXT
, ENC_ME_SIMPLESEARCH_LONGTEXT
, false )
274 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
275 add_bool( ENC_CFG_PREFIX ENC_ME_COMBINED
, true,
276 ENC_ME_COMBINED_TEXT
, ENC_ME_COMBINED_LONGTEXT
, false )
279 add_integer( ENC_CFG_PREFIX ENC_DWTINTRA
, -1,
280 ENC_DWTINTRA_TEXT
, ENC_DWTINTRA_LONGTEXT
, false )
281 change_integer_range(-1, 6);
283 add_integer( ENC_CFG_PREFIX ENC_DWTINTER
, -1,
284 ENC_DWTINTER_TEXT
, ENC_DWTINTER_LONGTEXT
, false )
285 change_integer_range(-1, 6);
287 add_integer( ENC_CFG_PREFIX ENC_DWTDEPTH
, -1,
288 ENC_DWTDEPTH_TEXT
, ENC_DWTDEPTH_LONGTEXT
, false )
289 change_integer_range(-1, 4);
291 /* advanced option only */
292 /* NB, unforunately vlc doesn't have a concept of 'dont care' */
293 add_integer( ENC_CFG_PREFIX ENC_MULTIQUANT
, -1,
294 ENC_MULTIQUANT_TEXT
, ENC_MULTIQUANT_LONGTEXT
, true )
295 change_integer_range(-1, 1);
297 /* advanced option only */
298 /* NB, unforunately vlc doesn't have a concept of 'dont care' */
299 add_integer( ENC_CFG_PREFIX ENC_SPARTITION
, -1,
300 ENC_SPARTITION_TEXT
, ENC_SPARTITION_LONGTEXT
, true )
301 change_integer_range(-1, 1);
303 add_bool( ENC_CFG_PREFIX ENC_NOAC
, false,
304 ENC_NOAC_TEXT
, ENC_NOAC_LONGTEXT
, false )
306 /* advanced option only */
307 add_float( ENC_CFG_PREFIX ENC_CPD
, -1,
308 ENC_CPD_TEXT
, ENC_CPD_LONGTEXT
, true )
309 change_integer_range(-1, INT_MAX
);
312 /*****************************************************************************
313 * picture_pts_t : store pts alongside picture number, not carried through
315 *****************************************************************************/
318 bool b_empty
; /* entry is invalid */
319 uint32_t u_pnum
; /* dirac picture number */
320 mtime_t i_pts
; /* associated pts */
323 /*****************************************************************************
324 * encoder_sys_t : dirac encoder descriptor
325 *****************************************************************************/
326 #define PTS_TLB_SIZE 256
329 dirac_encoder_t
*p_dirac
;
330 dirac_encoder_context_t ctx
;
331 bool b_auto_field_coding
;
333 uint8_t *p_buffer_in
;
335 uint32_t i_input_picnum
;
336 block_fifo_t
*p_dts_fifo
;
339 uint8_t *p_buffer_out
;
342 struct picture_pts_t pts_tlb
[PTS_TLB_SIZE
];
343 mtime_t i_pts_offset
;
344 mtime_t i_field_time
;
349 unsigned int i_height
;
352 } dirac_format_guess
[] = {
353 /* Important: Keep this list ordered in ascending picture height */
354 {1, 0, VIDEO_FORMAT_CUSTOM
},
355 {120, 15, VIDEO_FORMAT_QSIF525
},
356 {144, 12, VIDEO_FORMAT_QCIF
},
357 {240, 15, VIDEO_FORMAT_SIF525
},
358 {288, 12, VIDEO_FORMAT_CIF
},
359 {480, 30, VIDEO_FORMAT_SD_480I60
},
360 {480, 15, VIDEO_FORMAT_4SIF525
},
361 {576, 12, VIDEO_FORMAT_4CIF
},
362 {576, 25, VIDEO_FORMAT_SD_576I50
},
363 {720, 50, VIDEO_FORMAT_HD_720P50
},
364 {720, 60, VIDEO_FORMAT_HD_720P60
},
365 {1080, 24, VIDEO_FORMAT_DIGI_CINEMA_2K24
},
366 {1080, 25, VIDEO_FORMAT_HD_1080I50
},
367 {1080, 30, VIDEO_FORMAT_HD_1080I60
},
368 {1080, 50, VIDEO_FORMAT_HD_1080P50
},
369 {1080, 60, VIDEO_FORMAT_HD_1080P60
},
370 {2160, 24, VIDEO_FORMAT_DIGI_CINEMA_4K24
},
371 {2160, 50, VIDEO_FORMAT_UHDTV_4K50
},
372 {2160, 60, VIDEO_FORMAT_UHDTV_4K60
},
373 {3840, 50, VIDEO_FORMAT_UHDTV_8K50
},
374 {3840, 60, VIDEO_FORMAT_UHDTV_8K60
},
378 /*****************************************************************************
379 * ResetPTStlb: Purge all entries in @p_dec@'s PTS-tlb
380 *****************************************************************************/
381 static void ResetPTStlb( encoder_t
*p_enc
)
383 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
384 for( int i
=0; i
<PTS_TLB_SIZE
; i
++)
386 p_sys
->pts_tlb
[i
].b_empty
= true;
390 /*****************************************************************************
391 * StorePicturePTS: Store the PTS value for a particular picture number
392 *****************************************************************************/
393 static void StorePicturePTS( encoder_t
*p_enc
, uint32_t u_pnum
, mtime_t i_pts
)
395 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
397 for( int i
=0; i
<PTS_TLB_SIZE
; i
++ )
399 if( p_sys
->pts_tlb
[i
].b_empty
)
401 p_sys
->pts_tlb
[i
].u_pnum
= u_pnum
;
402 p_sys
->pts_tlb
[i
].i_pts
= i_pts
;
403 p_sys
->pts_tlb
[i
].b_empty
= false;
409 msg_Err( p_enc
, "Could not store PTS %"PRId64
" for frame %u", i_pts
, u_pnum
);
412 /*****************************************************************************
413 * GetPicturePTS: Retrieve the PTS value for a particular picture number
414 *****************************************************************************/
415 static mtime_t
GetPicturePTS( encoder_t
*p_enc
, uint32_t u_pnum
)
417 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
419 for( int i
=0; i
<PTS_TLB_SIZE
; i
++ )
421 if( !p_sys
->pts_tlb
[i
].b_empty
&&
422 p_sys
->pts_tlb
[i
].u_pnum
== u_pnum
)
424 p_sys
->pts_tlb
[i
].b_empty
= true;
425 return p_sys
->pts_tlb
[i
].i_pts
;
429 msg_Err( p_enc
, "Could not retrieve PTS for picture %u", u_pnum
);
433 /*****************************************************************************
434 * OpenEncoder: probe the encoder and return score
435 *****************************************************************************/
436 static int OpenEncoder( vlc_object_t
*p_this
)
438 encoder_t
*p_enc
= (encoder_t
*)p_this
;
439 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
444 if( p_enc
->fmt_out
.i_codec
!= VLC_CODEC_DIRAC
&&
450 if( !p_enc
->fmt_in
.video
.i_frame_rate
|| !p_enc
->fmt_in
.video
.i_frame_rate_base
||
451 !p_enc
->fmt_in
.video
.i_height
|| !p_enc
->fmt_in
.video
.i_width
)
453 msg_Err( p_enc
, "Framerate and picture dimensions must be non-zero" );
457 /* Allocate the memory needed to store the decoder's structure */
458 if( ( p_sys
= calloc( 1, sizeof(*p_sys
) ) ) == NULL
)
461 p_enc
->p_sys
= p_sys
;
462 p_enc
->pf_encode_video
= Encode
;
463 p_enc
->fmt_out
.i_codec
= VLC_CODEC_DIRAC
;
464 p_enc
->fmt_out
.i_cat
= VIDEO_ES
;
466 if( ( p_sys
->p_dts_fifo
= block_FifoNew() ) == NULL
)
468 CloseEncoder( p_this
);
472 ResetPTStlb( p_enc
);
474 /* guess the video format based upon number of lines and picture height */
476 VideoFormat guessed_video_fmt
= VIDEO_FORMAT_CUSTOM
;
477 /* Pick the dirac_video_format in this order of preference:
478 * 1. an exact match in frame height and an approximate fps match
479 * 2. the previous preset with a smaller number of lines.
483 if( dirac_format_guess
[i
].i_height
> p_enc
->fmt_in
.video
.i_height
)
485 guessed_video_fmt
= dirac_format_guess
[i
-1].i_vf
;
488 if( dirac_format_guess
[i
].i_height
!= p_enc
->fmt_in
.video
.i_height
)
490 int src_fps
= p_enc
->fmt_in
.video
.i_frame_rate
/ p_enc
->fmt_in
.video
.i_frame_rate_base
;
491 int delta_fps
= abs( dirac_format_guess
[i
].i_approx_fps
- src_fps
);
495 guessed_video_fmt
= dirac_format_guess
[i
].i_vf
;
497 } while( dirac_format_guess
[++i
].i_height
);
499 dirac_encoder_context_init( &p_sys
->ctx
, guessed_video_fmt
);
501 /* constants set from the input video format */
502 p_sys
->ctx
.src_params
.width
= p_enc
->fmt_in
.video
.i_width
;
503 p_sys
->ctx
.src_params
.height
= p_enc
->fmt_in
.video
.i_height
;
504 p_sys
->ctx
.src_params
.frame_rate
.numerator
= p_enc
->fmt_in
.video
.i_frame_rate
;
505 p_sys
->ctx
.src_params
.frame_rate
.denominator
= p_enc
->fmt_in
.video
.i_frame_rate_base
;
506 unsigned u_asr_num
, u_asr_den
;
507 vlc_ureduce( &u_asr_num
, &u_asr_den
,
508 p_enc
->fmt_in
.video
.i_sar_num
,
509 p_enc
->fmt_in
.video
.i_sar_den
, 0 );
510 p_sys
->ctx
.src_params
.pix_asr
.numerator
= u_asr_num
;
511 p_sys
->ctx
.src_params
.pix_asr
.denominator
= u_asr_den
;
513 config_ChainParse( p_enc
, ENC_CFG_PREFIX
, ppsz_enc_options
, p_enc
->p_cfg
);
515 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_CHROMAFMT
);
518 else if( !strcmp( psz_tmp
, "420" ) ) {
519 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I420
;
520 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 12;
521 p_sys
->ctx
.src_params
.chroma
= format420
;
522 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 3 / 2;
524 else if( !strcmp( psz_tmp
, "422" ) ) {
525 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I422
;
526 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 16;
527 p_sys
->ctx
.src_params
.chroma
= format422
;
528 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 2;
530 else if( !strcmp( psz_tmp
, "444" ) ) {
531 p_enc
->fmt_in
.i_codec
= VLC_CODEC_I444
;
532 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 24;
533 p_sys
->ctx
.src_params
.chroma
= format444
;
534 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 3;
537 msg_Err( p_enc
, "Invalid chroma format: %s", psz_tmp
);
543 p_sys
->ctx
.enc_params
.qf
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_QUALITY_FACTOR
);
545 /* use bitrate from sout-transcode-vb in kbps */
546 p_sys
->ctx
.enc_params
.trate
= p_enc
->fmt_out
.i_bitrate
/ 1000;
547 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_TARGETRATE
);
549 p_sys
->ctx
.enc_params
.trate
= i_tmp
;
550 p_enc
->fmt_out
.i_bitrate
= p_sys
->ctx
.enc_params
.trate
* 1000;
552 p_sys
->ctx
.enc_params
.lossless
= var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_LOSSLESS
);
554 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_PREFILTER
);
557 else if( !strcmp( psz_tmp
, "none" ) ) {
558 p_sys
->ctx
.enc_params
.prefilter
= NO_PF
;
560 else if( !strcmp( psz_tmp
, "cwm" ) ) {
561 p_sys
->ctx
.enc_params
.prefilter
= CWM
;
563 else if( !strcmp( psz_tmp
, "rectlp" ) ) {
564 p_sys
->ctx
.enc_params
.prefilter
= RECTLP
;
566 else if( !strcmp( psz_tmp
, "diaglp" ) ) {
567 p_sys
->ctx
.enc_params
.prefilter
= DIAGLP
;
570 msg_Err( p_enc
, "Invalid prefilter: %s", psz_tmp
);
576 p_sys
->ctx
.enc_params
.prefilter_strength
=
577 var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH
);
579 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_L1SEP
);
581 p_sys
->ctx
.enc_params
.L1_sep
= i_tmp
;
583 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_L1NUM
);
585 p_sys
->ctx
.enc_params
.num_L1
= i_tmp
;
587 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_CODINGMODE
);
590 else if( !strcmp( psz_tmp
, "auto" ) ) {
591 p_sys
->b_auto_field_coding
= true;
593 else if( !strcmp( psz_tmp
, "progressive" ) ) {
594 p_sys
->b_auto_field_coding
= false;
595 p_sys
->ctx
.enc_params
.picture_coding_mode
= 0;
597 else if( !strcmp( psz_tmp
, "field" ) ) {
598 p_sys
->b_auto_field_coding
= false;
599 p_sys
->ctx
.enc_params
.picture_coding_mode
= 1;
602 msg_Err( p_enc
, "Invalid codingmode: %s", psz_tmp
);
608 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_MVPREC
);
611 else if( !strcmp( psz_tmp
, "1" ) ) {
612 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_PIXEL
;
614 else if( !strcmp( psz_tmp
, "1/2" ) ) {
615 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_HALF_PIXEL
;
617 else if( !strcmp( psz_tmp
, "1/4" ) ) {
618 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_QUARTER_PIXEL
;
620 else if( !strcmp( psz_tmp
, "1/8" ) ) {
621 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_EIGHTH_PIXEL
;
624 msg_Err( p_enc
, "Invalid mv-prec: %s", psz_tmp
);
631 * {x,y}b{len,sep} must be multiples of 4
633 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_WIDTH
);
635 p_sys
->ctx
.enc_params
.xbsep
= i_tmp
/ 4 * 4;
637 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_HEIGHT
);
639 p_sys
->ctx
.enc_params
.ybsep
= i_tmp
/ 4 * 4;
641 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP
);
643 p_sys
->ctx
.enc_params
.xblen
= p_sys
->ctx
.enc_params
.xbsep
* (100 + i_tmp
) / 400 * 4;
644 p_sys
->ctx
.enc_params
.yblen
= p_sys
->ctx
.enc_params
.ybsep
* (100 + i_tmp
) / 400 * 4;
648 * {x,y}blen >= {x,y}bsep
649 * {x,y}blen <= 2* {x,y}bsep
651 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_XBLEN
);
653 int xblen
= __MAX( i_tmp
, p_sys
->ctx
.enc_params
.xbsep
);
654 xblen
= __MIN( xblen
, 2 * p_sys
->ctx
.enc_params
.xbsep
);
655 p_sys
->ctx
.enc_params
.xblen
= xblen
;
658 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_YBLEN
);
660 int yblen
= __MAX( i_tmp
, p_sys
->ctx
.enc_params
.ybsep
);
661 yblen
= __MIN( yblen
, 2 * p_sys
->ctx
.enc_params
.ybsep
);
662 p_sys
->ctx
.enc_params
.yblen
= yblen
;
665 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH
);
668 if( *psz_tmp
!= '\0' ) {
669 /* of the form [0-9]+:[0-9]+ */
670 char *psz_start
= psz_tmp
;
671 char *psz_end
= psz_tmp
;
672 p_sys
->ctx
.enc_params
.x_range_me
= strtol(psz_start
, &psz_end
, 10);
673 if( *psz_end
!= ':' || psz_end
== psz_start
) {
674 msg_Err( p_enc
, "Invalid simple search range: %s", psz_tmp
);
678 psz_start
= ++psz_end
;
679 p_sys
->ctx
.enc_params
.y_range_me
= strtol(psz_start
, &psz_end
, 10);
680 if( *psz_end
!= '\0' || psz_end
== psz_start
) {
681 msg_Err( p_enc
, "Invalid simple search range: %s", psz_tmp
);
685 if( p_sys
->ctx
.enc_params
.x_range_me
< 0 ||
686 p_sys
->ctx
.enc_params
.y_range_me
< 0 )
688 msg_Err( p_enc
, "Invalid negative simple search range: %s", psz_tmp
);
692 p_sys
->ctx
.enc_params
.full_search
= 1;
696 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
697 p_sys
->ctx
.enc_params
.combined_me
= var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_ME_COMBINED
);
700 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTINTRA
);
702 p_sys
->ctx
.enc_params
.intra_wlt_filter
= i_tmp
;
704 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTINTER
);
706 p_sys
->ctx
.enc_params
.inter_wlt_filter
= i_tmp
;
708 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTDEPTH
);
710 p_sys
->ctx
.enc_params
.wlt_depth
= i_tmp
;
712 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MULTIQUANT
);
714 p_sys
->ctx
.enc_params
.multi_quants
= i_tmp
;
716 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_SPARTITION
);
718 p_sys
->ctx
.enc_params
.spatial_partition
= i_tmp
;
720 p_sys
->ctx
.enc_params
.using_ac
= !var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_NOAC
);
722 f_tmp
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_CPD
);
724 p_sys
->ctx
.enc_params
.cpd
= f_tmp
;
726 /* Allocate the buffer for inputing frames into the encoder */
727 if( ( p_sys
->p_buffer_in
= malloc( p_sys
->i_buffer_in
) ) == NULL
)
729 CloseEncoder( p_this
);
733 /* Set up output buffer */
734 /* Unfortunately it isn't possible to determine if the buffer
735 * is too small (and then reallocate it) */
736 p_sys
->i_buffer_out
= 4096 + p_sys
->i_buffer_in
;
737 if( ( p_sys
->p_buffer_out
= malloc( p_sys
->i_buffer_out
) ) == NULL
)
739 CloseEncoder( p_this
);
745 CloseEncoder( p_this
);
749 /* Attempt to find dirac picture number in an encapsulation unit */
750 static int ReadDiracPictureNumber( uint32_t *p_picnum
, block_t
*p_block
)
753 /* protect against falling off the edge */
754 while( u_pos
+ 13 < p_block
->i_buffer
)
756 /* find the picture startcode */
757 if( p_block
->p_buffer
[u_pos
] & 0x08 )
759 *p_picnum
= GetDWBE( p_block
->p_buffer
+ u_pos
+ 9 );
762 /* skip to the next dirac data unit */
763 uint32_t u_npo
= GetDWBE( p_block
->p_buffer
+ u_pos
+ 1 );
764 assert( u_npo
<= UINT32_MAX
- u_pos
);
772 /****************************************************************************
773 * Encode: the whole thing
774 ****************************************************************************
775 * This function spits out encapsulation units.
776 ****************************************************************************/
777 static block_t
*Encode( encoder_t
*p_enc
, picture_t
*p_pic
)
779 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
780 block_t
*p_block
, *p_output_chain
= NULL
;
781 int i_plane
, i_line
, i_width
, i_src_stride
;
784 if( !p_pic
) return NULL
;
785 /* we only know if the sequence is interlaced when the first
786 * picture arrives, so final setup is done here */
787 /* XXX todo, detect change of interlace */
788 p_sys
->ctx
.src_params
.topfieldfirst
= p_pic
->b_top_field_first
;
789 p_sys
->ctx
.src_params
.source_sampling
= !p_pic
->b_progressive
;
791 if( p_sys
->b_auto_field_coding
)
792 p_sys
->ctx
.enc_params
.picture_coding_mode
= !p_pic
->b_progressive
;
794 if( !p_sys
->p_dirac
)
797 /* Initialise the encoder with the encoder context */
798 p_sys
->p_dirac
= dirac_encoder_init( &p_sys
->ctx
, 0 );
799 if( !p_sys
->p_dirac
)
801 msg_Err( p_enc
, "Failed to initialize dirac encoder" );
804 date_Init( &date
, p_enc
->fmt_in
.video
.i_frame_rate
, p_enc
->fmt_in
.video
.i_frame_rate_base
);
805 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
806 int i_delayinpics
= dirac_encoder_pts_offset( p_sys
->p_dirac
);
807 i_delayinpics
/= p_sys
->ctx
.enc_params
.picture_coding_mode
+ 1;
808 date_Increment( &date
, i_delayinpics
);
810 date_Increment( &date
, 1 );
812 p_sys
->i_pts_offset
= date_Get( &date
);
814 /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
815 * for each frame input. Calculate time between fields for offsetting
816 * the second field later. */
817 if( 1 == p_sys
->ctx
.enc_params
.picture_coding_mode
)
819 date_Set( &date
, 0 );
820 date_Increment( &date
, 1 );
821 p_sys
->i_field_time
= date_Get( &date
) / 2;
825 /* Copy input picture into encoder input buffer (stride by stride) */
826 /* Would be lovely to just pass the picture in, but there is noway for the
827 * library to free it */
828 p_dst
= p_sys
->p_buffer_in
;
829 for( i_plane
= 0; i_plane
< p_pic
->i_planes
; i_plane
++ )
831 uint8_t *p_src
= p_pic
->p
[i_plane
].p_pixels
;
832 i_width
= p_pic
->p
[i_plane
].i_visible_pitch
;
833 i_src_stride
= p_pic
->p
[i_plane
].i_pitch
;
835 for( i_line
= 0; i_line
< p_pic
->p
[i_plane
].i_visible_lines
; i_line
++ )
837 vlc_memcpy( p_dst
, p_src
, i_width
);
839 p_src
+= i_src_stride
;
843 /* Load one frame of data into encoder */
844 if( dirac_encoder_load( p_sys
->p_dirac
, p_sys
->p_buffer_in
,
845 p_sys
->i_buffer_in
) < 0 )
847 msg_Dbg( p_enc
, "dirac_encoder_load() error" );
851 /* store pts in a lookaside buffer, so that the same pts may
852 * be used for the picture in coded order */
853 StorePicturePTS( p_enc
, p_sys
->i_input_picnum
, p_pic
->date
);
854 p_sys
->i_input_picnum
++;
856 /* store dts in a queue, so that they appear in order in
858 p_block
= block_New( p_enc
, 1 );
861 p_block
->i_dts
= p_pic
->date
- p_sys
->i_pts_offset
;
862 block_FifoPut( p_sys
->p_dts_fifo
, p_block
);
865 /* for field coding mode, insert an extra value into both the
866 * pts lookaside buffer and dts queue, offset to correspond
867 * to a one field delay. */
868 if( 1 == p_sys
->ctx
.enc_params
.picture_coding_mode
)
870 StorePicturePTS( p_enc
, p_sys
->i_input_picnum
, p_pic
->date
+ p_sys
->i_field_time
);
871 p_sys
->i_input_picnum
++;
873 p_block
= block_New( p_enc
, 1 );
876 p_block
->i_dts
= p_pic
->date
- p_sys
->i_pts_offset
+ p_sys
->i_field_time
;
877 block_FifoPut( p_sys
->p_dts_fifo
, p_block
);
881 dirac_encoder_state_t state
;
882 /* Retrieve encoded frames from encoder */
885 p_sys
->p_dirac
->enc_buf
.buffer
= p_sys
->p_buffer_out
;
886 p_sys
->p_dirac
->enc_buf
.size
= p_sys
->i_buffer_out
;
887 state
= dirac_encoder_output( p_sys
->p_dirac
);
890 case ENC_STATE_AVAIL
: {
893 /* extract data from encoder temporary buffer. */
894 p_block
= block_New( p_enc
, p_sys
->p_dirac
->enc_buf
.size
);
897 memcpy( p_block
->p_buffer
, p_sys
->p_dirac
->enc_buf
.buffer
,
898 p_sys
->p_dirac
->enc_buf
.size
);
900 /* if some flags were set for a previous block, prevent
901 * them from getting lost */
903 p_block
->i_flags
|= p_sys
->p_chain
->i_flags
;
905 /* store all extracted blocks in a chain and gather up when an
906 * entire encapsulation unit is avaliable (ends with a picture) */
907 block_ChainAppend( &p_sys
->p_chain
, p_block
);
909 /* Presence of a Sequence header indicates a seek point */
910 if( 0 == p_block
->p_buffer
[4] )
912 p_block
->i_flags
|= BLOCK_FLAG_TYPE_I
;
914 if( !p_enc
->fmt_out
.p_extra
) {
915 const uint8_t eos
[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
916 uint32_t len
= GetDWBE( p_block
->p_buffer
+ 5 );
917 /* if it hasn't been done so far, stash a copy of the
918 * sequence header for muxers such as ogg */
919 /* The OggDirac spec advises that a Dirac EOS DataUnit
920 * is appended to the sequence header to allow guard
921 * against poor streaming servers */
922 /* XXX, should this be done using the packetizer ? */
923 p_enc
->fmt_out
.p_extra
= malloc( len
+ sizeof(eos
) );
924 if( !p_enc
->fmt_out
.p_extra
)
926 memcpy( p_enc
->fmt_out
.p_extra
, p_block
->p_buffer
, len
);
927 memcpy( (uint8_t*)p_enc
->fmt_out
.p_extra
+ len
, eos
, sizeof(eos
) );
928 SetDWBE( (uint8_t*)p_enc
->fmt_out
.p_extra
+ len
+ 10, len
);
929 p_enc
->fmt_out
.i_extra
= len
+ sizeof(eos
);
933 if( ReadDiracPictureNumber( &pic_num
, p_block
) )
935 /* Finding a picture terminates an ecapsulation unit, gather
936 * all data and output; use the next dts value queued up
937 * and find correct pts in the tlb */
938 p_block
= block_FifoGet( p_sys
->p_dts_fifo
);
939 p_sys
->p_chain
->i_dts
= p_block
->i_dts
;
940 p_sys
->p_chain
->i_pts
= GetPicturePTS( p_enc
, pic_num
);
941 block_Release( p_block
);
942 block_ChainAppend( &p_output_chain
, block_ChainGather( p_sys
->p_chain
) );
943 p_sys
->p_chain
= NULL
;
950 case ENC_STATE_BUFFER
:
952 case ENC_STATE_INVALID
:
956 } while( state
== ENC_STATE_AVAIL
);
958 return p_output_chain
;
961 /*****************************************************************************
962 * CloseEncoder: dirac encoder destruction
963 *****************************************************************************/
964 static void CloseEncoder( vlc_object_t
*p_this
)
966 encoder_t
*p_enc
= (encoder_t
*)p_this
;
967 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
969 /* Free the encoder resources */
971 dirac_encoder_close( p_sys
->p_dirac
);
973 free( p_sys
->p_buffer_in
);
974 free( p_sys
->p_buffer_out
);
976 if( p_sys
->p_dts_fifo
)
977 block_FifoRelease( p_sys
->p_dts_fifo
);
978 block_ChainRelease( p_sys
->p_chain
);