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 *****************************************************************************/
39 #include <vlc_common.h>
40 #include <vlc_plugin.h>
41 #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 " seperately 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 seperate 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_capability( "encoder", 100 )
208 set_callbacks( OpenEncoder
, CloseEncoder
)
210 add_float( ENC_CFG_PREFIX ENC_QUALITY_FACTOR
, 5.5, NULL
,
211 ENC_QUALITY_FACTOR_TEXT
, ENC_QUALITY_FACTOR_LONGTEXT
, false );
212 change_float_range(0., 10.);
214 add_integer( ENC_CFG_PREFIX ENC_TARGETRATE
, -1, NULL
,
215 ENC_TARGETRATE_TEXT
, ENC_TARGETRATE_LONGTEXT
, false );
216 change_integer_range(-1, INT_MAX
);
218 add_bool( ENC_CFG_PREFIX ENC_LOSSLESS
, false, NULL
,
219 ENC_LOSSLESS_TEXT
, ENC_LOSSLESS_LONGTEXT
, false );
221 add_string( ENC_CFG_PREFIX ENC_PREFILTER
, "diaglp", NULL
,
222 ENC_PREFILTER_TEXT
, ENC_PREFILTER_LONGTEXT
, false );
223 change_string_list( enc_prefilter_list
, enc_prefilter_list_text
, 0 );
225 add_integer( ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH
, 1, NULL
,
226 ENC_PREFILTER_STRENGTH_TEXT
, ENC_PREFILTER_STRENGTH_LONGTEXT
, false );
227 change_integer_range(0, 10);
229 add_string( ENC_CFG_PREFIX ENC_CHROMAFMT
, "420", NULL
,
230 ENC_CHROMAFMT_TEXT
, ENC_CHROMAFMT_LONGTEXT
, false );
231 change_string_list( enc_chromafmt_list
, enc_chromafmt_list_text
, 0 );
233 add_integer( ENC_CFG_PREFIX ENC_L1SEP
, -1, NULL
,
234 ENC_L1SEP_TEXT
, ENC_L1SEP_LONGTEXT
, false );
235 change_integer_range(-1, INT_MAX
);
237 add_integer( ENC_CFG_PREFIX ENC_L1NUM
, -1, NULL
,
238 ENC_L1NUM_TEXT
, ENC_L1NUM_LONGTEXT
, false );
239 change_integer_range(-1, INT_MAX
);
241 add_string( ENC_CFG_PREFIX ENC_CODINGMODE
, "auto", NULL
,
242 ENC_CODINGMODE_TEXT
, ENC_CODINGMODE_LONGTEXT
, false );
243 change_string_list( enc_codingmode_list
, enc_codingmode_list_text
, 0 );
245 add_string( ENC_CFG_PREFIX ENC_MVPREC
, "1/2", NULL
,
246 ENC_MVPREC_TEXT
, ENC_MVPREC_LONGTEXT
, false );
247 change_string_list( enc_mvprec_list
, enc_mvprec_list
, 0 );
249 add_integer( ENC_CFG_PREFIX ENC_MCBLK_WIDTH
, -1, NULL
,
250 ENC_MCBLK_WIDTH_TEXT
, ENC_MCBLK_WIDTH_LONGTEXT
, false );
251 add_deprecated_alias( ENC_CFG_PREFIX ENC_MCBLK_XBLEN
);
252 change_integer_range(-1, INT_MAX
);
254 add_integer( ENC_CFG_PREFIX ENC_MCBLK_HEIGHT
, -1, NULL
,
255 ENC_MCBLK_HEIGHT
, ENC_MCBLK_HEIGHT_LONGTEXT
, false );
256 add_deprecated_alias( ENC_CFG_PREFIX ENC_MCBLK_YBLEN
);
257 change_integer_range(-1, INT_MAX
);
259 add_integer( ENC_CFG_PREFIX ENC_MCBLK_OVERLAP
, -1, NULL
,
260 ENC_MCBLK_OVERLAP_TEXT
, ENC_MCBLK_OVERLAP_LONGTEXT
, false );
261 change_integer_range(-1, 100);
263 /* advanced option only */
264 add_integer( ENC_CFG_PREFIX ENC_MCBLK_XBLEN
, -1, NULL
,
265 ENC_MCBLK_XBLEN_TEXT
, ENC_MCBLK_XBLEN_LONGTEXT
, true );
266 change_integer_range(-1, INT_MAX
);
267 /* advanced option only */
268 add_integer( ENC_CFG_PREFIX ENC_MCBLK_YBLEN
, -1, NULL
,
269 ENC_MCBLK_YBLEN_TEXT
, ENC_MCBLK_YBLEN_LONGTEXT
, true );
270 change_integer_range(-1, INT_MAX
);
272 add_string( ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH
, "", NULL
,
273 ENC_ME_SIMPLESEARCH_TEXT
, ENC_ME_SIMPLESEARCH_LONGTEXT
, false );
275 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
276 add_bool( ENC_CFG_PREFIX ENC_ME_COMBINED
, true, NULL
,
277 ENC_ME_COMBINED_TEXT
, ENC_ME_COMBINED_LONGTEXT
, false );
280 add_integer( ENC_CFG_PREFIX ENC_DWTINTRA
, -1, NULL
,
281 ENC_DWTINTRA_TEXT
, ENC_DWTINTRA_LONGTEXT
, false );
282 change_integer_range(-1, 6);
284 add_integer( ENC_CFG_PREFIX ENC_DWTINTER
, -1, NULL
,
285 ENC_DWTINTER_TEXT
, ENC_DWTINTER_LONGTEXT
, false );
286 change_integer_range(-1, 6);
288 add_integer( ENC_CFG_PREFIX ENC_DWTDEPTH
, -1, NULL
,
289 ENC_DWTDEPTH_TEXT
, ENC_DWTDEPTH_LONGTEXT
, false );
290 change_integer_range(-1, 4);
292 /* advanced option only */
293 /* NB, unforunately vlc doesn't have a concept of 'dont care' */
294 add_integer( ENC_CFG_PREFIX ENC_MULTIQUANT
, -1, NULL
,
295 ENC_MULTIQUANT_TEXT
, ENC_MULTIQUANT_LONGTEXT
, true );
296 change_integer_range(-1, 1);
298 /* advanced option only */
299 /* NB, unforunately vlc doesn't have a concept of 'dont care' */
300 add_integer( ENC_CFG_PREFIX ENC_SPARTITION
, -1, NULL
,
301 ENC_SPARTITION_TEXT
, ENC_SPARTITION_LONGTEXT
, true );
302 change_integer_range(-1, 1);
304 add_bool( ENC_CFG_PREFIX ENC_NOAC
, false, NULL
,
305 ENC_NOAC_TEXT
, ENC_NOAC_LONGTEXT
, false );
307 /* advanced option only */
308 add_float( ENC_CFG_PREFIX ENC_CPD
, -1, NULL
,
309 ENC_CPD_TEXT
, ENC_CPD_LONGTEXT
, true );
310 change_integer_range(-1, INT_MAX
);
313 /*****************************************************************************
314 * picture_pts_t : store pts alongside picture number, not carried through
316 *****************************************************************************/
319 bool b_empty
; /* entry is invalid */
320 uint32_t u_pnum
; /* dirac picture number */
321 mtime_t i_pts
; /* associated pts */
324 /*****************************************************************************
325 * encoder_sys_t : dirac encoder descriptor
326 *****************************************************************************/
327 #define PTS_TLB_SIZE 256
330 dirac_encoder_t
*p_dirac
;
331 dirac_encoder_context_t ctx
;
332 bool b_auto_field_coding
;
334 uint8_t *p_buffer_in
;
336 uint32_t i_input_picnum
;
337 block_fifo_t
*p_dts_fifo
;
340 uint8_t *p_buffer_out
;
343 struct picture_pts_t pts_tlb
[PTS_TLB_SIZE
];
344 mtime_t i_pts_offset
;
345 mtime_t i_field_time
;
350 unsigned int i_height
;
353 } dirac_format_guess
[] = {
354 /* Important: Keep this list ordered in ascending picture height */
355 {1, 0, VIDEO_FORMAT_CUSTOM
},
356 {120, 15, VIDEO_FORMAT_QSIF525
},
357 {144, 12, VIDEO_FORMAT_QCIF
},
358 {240, 15, VIDEO_FORMAT_SIF525
},
359 {288, 12, VIDEO_FORMAT_CIF
},
360 {480, 30, VIDEO_FORMAT_SD_480I60
},
361 {480, 15, VIDEO_FORMAT_4SIF525
},
362 {576, 12, VIDEO_FORMAT_4CIF
},
363 {576, 25, VIDEO_FORMAT_SD_576I50
},
364 {720, 50, VIDEO_FORMAT_HD_720P50
},
365 {720, 60, VIDEO_FORMAT_HD_720P60
},
366 {1080, 24, VIDEO_FORMAT_DIGI_CINEMA_2K24
},
367 {1080, 25, VIDEO_FORMAT_HD_1080I50
},
368 {1080, 30, VIDEO_FORMAT_HD_1080I60
},
369 {1080, 50, VIDEO_FORMAT_HD_1080P50
},
370 {1080, 60, VIDEO_FORMAT_HD_1080P60
},
371 {2160, 24, VIDEO_FORMAT_DIGI_CINEMA_4K24
},
372 {2160, 50, VIDEO_FORMAT_UHDTV_4K50
},
373 {2160, 60, VIDEO_FORMAT_UHDTV_4K60
},
374 {3840, 50, VIDEO_FORMAT_UHDTV_8K50
},
375 {3840, 60, VIDEO_FORMAT_UHDTV_8K60
},
379 /*****************************************************************************
380 * ResetPTStlb: Purge all entries in @p_dec@'s PTS-tlb
381 *****************************************************************************/
382 static void ResetPTStlb( encoder_t
*p_enc
)
384 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
385 for( int i
=0; i
<PTS_TLB_SIZE
; i
++)
387 p_sys
->pts_tlb
[i
].b_empty
= true;
391 /*****************************************************************************
392 * StorePicturePTS: Store the PTS value for a particular picture number
393 *****************************************************************************/
394 static void StorePicturePTS( encoder_t
*p_enc
, uint32_t u_pnum
, mtime_t i_pts
)
396 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
398 for( int i
=0; i
<PTS_TLB_SIZE
; i
++ )
400 if( p_sys
->pts_tlb
[i
].b_empty
)
402 p_sys
->pts_tlb
[i
].u_pnum
= u_pnum
;
403 p_sys
->pts_tlb
[i
].i_pts
= i_pts
;
404 p_sys
->pts_tlb
[i
].b_empty
= false;
410 msg_Err( p_enc
, "Could not store PTS %"PRId64
" for frame %u", i_pts
, u_pnum
);
413 /*****************************************************************************
414 * GetPicturePTS: Retrieve the PTS value for a particular picture number
415 *****************************************************************************/
416 static mtime_t
GetPicturePTS( encoder_t
*p_enc
, uint32_t u_pnum
)
418 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
420 for( int i
=0; i
<PTS_TLB_SIZE
; i
++ )
422 if( !p_sys
->pts_tlb
[i
].b_empty
&&
423 p_sys
->pts_tlb
[i
].u_pnum
== u_pnum
)
425 p_sys
->pts_tlb
[i
].b_empty
= true;
426 return p_sys
->pts_tlb
[i
].i_pts
;
430 msg_Err( p_enc
, "Could not retrieve PTS for picture %u", u_pnum
);
434 /*****************************************************************************
435 * OpenEncoder: probe the encoder and return score
436 *****************************************************************************/
437 static int OpenEncoder( vlc_object_t
*p_this
)
439 encoder_t
*p_enc
= (encoder_t
*)p_this
;
440 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
445 if( p_enc
->fmt_out
.i_codec
!= VLC_FOURCC('d','r','a','c') &&
451 if( !p_enc
->fmt_in
.video
.i_frame_rate
|| !p_enc
->fmt_in
.video
.i_frame_rate_base
||
452 !p_enc
->fmt_in
.video
.i_height
|| !p_enc
->fmt_in
.video
.i_width
)
454 msg_Err( p_enc
, "Framerate and picture dimensions must be non-zero" );
458 /* Allocate the memory needed to store the decoder's structure */
459 if( ( p_sys
= calloc( 1, sizeof(*p_sys
) ) ) == NULL
)
462 p_enc
->p_sys
= p_sys
;
463 p_enc
->pf_encode_video
= Encode
;
464 p_enc
->fmt_out
.i_codec
= VLC_FOURCC('d','r','a','c');
465 p_enc
->fmt_out
.i_cat
= VIDEO_ES
;
467 if( ( p_sys
->p_dts_fifo
= block_FifoNew() ) == NULL
)
469 CloseEncoder( p_this
);
473 ResetPTStlb( p_enc
);
475 /* guess the video format based upon number of lines and picture height */
477 VideoFormat guessed_video_fmt
= VIDEO_FORMAT_CUSTOM
;
478 /* Pick the dirac_video_format in this order of preference:
479 * 1. an exact match in frame height and an approximate fps match
480 * 2. the previous preset with a smaller number of lines.
484 if( dirac_format_guess
[i
].i_height
> p_enc
->fmt_in
.video
.i_height
)
486 guessed_video_fmt
= dirac_format_guess
[i
-1].i_vf
;
489 if( dirac_format_guess
[i
].i_height
!= p_enc
->fmt_in
.video
.i_height
)
491 int src_fps
= p_enc
->fmt_in
.video
.i_frame_rate
/ p_enc
->fmt_in
.video
.i_frame_rate_base
;
492 int delta_fps
= abs( dirac_format_guess
[i
].i_approx_fps
- src_fps
);
496 guessed_video_fmt
= dirac_format_guess
[i
].i_vf
;
498 } while( dirac_format_guess
[++i
].i_height
);
500 dirac_encoder_context_init( &p_sys
->ctx
, guessed_video_fmt
);
502 /* constants set from the input video format */
503 p_sys
->ctx
.src_params
.width
= p_enc
->fmt_in
.video
.i_width
;
504 p_sys
->ctx
.src_params
.height
= p_enc
->fmt_in
.video
.i_height
;
505 p_sys
->ctx
.src_params
.frame_rate
.numerator
= p_enc
->fmt_in
.video
.i_frame_rate
;
506 p_sys
->ctx
.src_params
.frame_rate
.denominator
= p_enc
->fmt_in
.video
.i_frame_rate_base
;
507 unsigned u_asr_num
, u_asr_den
;
508 vlc_ureduce( &u_asr_num
, &u_asr_den
,
509 p_enc
->fmt_in
.video
.i_height
* p_enc
->fmt_in
.video
.i_aspect
,
510 p_enc
->fmt_in
.video
.i_width
* VOUT_ASPECT_FACTOR
,
512 p_sys
->ctx
.src_params
.pix_asr
.numerator
= u_asr_num
;
513 p_sys
->ctx
.src_params
.pix_asr
.denominator
= u_asr_den
;
515 config_ChainParse( p_enc
, ENC_CFG_PREFIX
, ppsz_enc_options
, p_enc
->p_cfg
);
517 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_CHROMAFMT
);
520 else if( !strcmp( psz_tmp
, "420" ) ) {
521 p_enc
->fmt_in
.i_codec
= VLC_FOURCC('I','4','2','0');
522 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 12;
523 p_sys
->ctx
.src_params
.chroma
= format420
;
524 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 3 / 2;
526 else if( !strcmp( psz_tmp
, "422" ) ) {
527 p_enc
->fmt_in
.i_codec
= VLC_FOURCC('I','4','2','2');
528 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 16;
529 p_sys
->ctx
.src_params
.chroma
= format422
;
530 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 2;
532 else if( !strcmp( psz_tmp
, "444" ) ) {
533 p_enc
->fmt_in
.i_codec
= VLC_FOURCC('I','4','4','4');
534 p_enc
->fmt_in
.video
.i_bits_per_pixel
= 24;
535 p_sys
->ctx
.src_params
.chroma
= format444
;
536 p_sys
->i_buffer_in
= p_enc
->fmt_in
.video
.i_width
* p_enc
->fmt_in
.video
.i_height
* 3;
539 msg_Err( p_enc
, "Invalid chroma format: %s", psz_tmp
);
545 p_sys
->ctx
.enc_params
.qf
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_QUALITY_FACTOR
);
547 /* use bitrate from sout-transcode-vb in kbps */
548 p_sys
->ctx
.enc_params
.trate
= p_enc
->fmt_out
.i_bitrate
/ 1000;
549 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_TARGETRATE
);
551 p_sys
->ctx
.enc_params
.trate
= i_tmp
;
552 p_enc
->fmt_out
.i_bitrate
= p_sys
->ctx
.enc_params
.trate
* 1000;
554 p_sys
->ctx
.enc_params
.lossless
= var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_LOSSLESS
);
556 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_PREFILTER
);
559 else if( !strcmp( psz_tmp
, "none" ) ) {
560 p_sys
->ctx
.enc_params
.prefilter
= NO_PF
;
562 else if( !strcmp( psz_tmp
, "cwm" ) ) {
563 p_sys
->ctx
.enc_params
.prefilter
= CWM
;
565 else if( !strcmp( psz_tmp
, "rectlp" ) ) {
566 p_sys
->ctx
.enc_params
.prefilter
= RECTLP
;
568 else if( !strcmp( psz_tmp
, "diaglp" ) ) {
569 p_sys
->ctx
.enc_params
.prefilter
= DIAGLP
;
572 msg_Err( p_enc
, "Invalid prefilter: %s", psz_tmp
);
578 p_sys
->ctx
.enc_params
.prefilter_strength
=
579 var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH
);
581 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_L1SEP
);
583 p_sys
->ctx
.enc_params
.L1_sep
= i_tmp
;
585 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_L1NUM
);
587 p_sys
->ctx
.enc_params
.num_L1
= i_tmp
;
589 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_CODINGMODE
);
592 else if( !strcmp( psz_tmp
, "auto" ) ) {
593 p_sys
->b_auto_field_coding
= true;
595 else if( !strcmp( psz_tmp
, "progressive" ) ) {
596 p_sys
->b_auto_field_coding
= false;
597 p_sys
->ctx
.enc_params
.picture_coding_mode
= 0;
599 else if( !strcmp( psz_tmp
, "field" ) ) {
600 p_sys
->b_auto_field_coding
= false;
601 p_sys
->ctx
.enc_params
.picture_coding_mode
= 1;
604 msg_Err( p_enc
, "Invalid codingmode: %s", psz_tmp
);
610 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_MVPREC
);
613 else if( !strcmp( psz_tmp
, "1" ) ) {
614 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_PIXEL
;
616 else if( !strcmp( psz_tmp
, "1/2" ) ) {
617 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_HALF_PIXEL
;
619 else if( !strcmp( psz_tmp
, "1/4" ) ) {
620 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_QUARTER_PIXEL
;
622 else if( !strcmp( psz_tmp
, "1/8" ) ) {
623 p_sys
->ctx
.enc_params
.mv_precision
= MV_PRECISION_EIGHTH_PIXEL
;
626 msg_Err( p_enc
, "Invalid mv-prec: %s", psz_tmp
);
633 * {x,y}b{len,sep} must be multiples of 4
635 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_WIDTH
);
637 p_sys
->ctx
.enc_params
.xbsep
= i_tmp
/ 4 * 4;
639 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_HEIGHT
);
641 p_sys
->ctx
.enc_params
.ybsep
= i_tmp
/ 4 * 4;
643 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP
);
645 p_sys
->ctx
.enc_params
.xblen
= p_sys
->ctx
.enc_params
.xbsep
* (100 + i_tmp
) / 400 * 4;
646 p_sys
->ctx
.enc_params
.yblen
= p_sys
->ctx
.enc_params
.ybsep
* (100 + i_tmp
) / 400 * 4;
650 * {x,y}blen >= {x,y}bsep
651 * {x,y}blen <= 2* {x,y}bsep
653 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_XBLEN
);
655 int xblen
= __MAX( i_tmp
, p_sys
->ctx
.enc_params
.xbsep
);
656 xblen
= __MIN( xblen
, 2 * p_sys
->ctx
.enc_params
.xbsep
);
657 p_sys
->ctx
.enc_params
.xblen
= xblen
;
660 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MCBLK_YBLEN
);
662 int yblen
= __MAX( i_tmp
, p_sys
->ctx
.enc_params
.ybsep
);
663 yblen
= __MIN( yblen
, 2 * p_sys
->ctx
.enc_params
.ybsep
);
664 p_sys
->ctx
.enc_params
.yblen
= yblen
;
667 psz_tmp
= var_GetString( p_enc
, ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH
);
670 if( *psz_tmp
!= '\0' ) {
671 /* of the form [0-9]+:[0-9]+ */
672 char *psz_start
= psz_tmp
;
673 char *psz_end
= psz_tmp
;
674 p_sys
->ctx
.enc_params
.x_range_me
= strtol(psz_start
, &psz_end
, 10);
675 if( *psz_end
!= ':' || psz_end
== psz_start
) {
676 msg_Err( p_enc
, "Invalid simple search range: %s", psz_tmp
);
680 psz_start
= ++psz_end
;
681 p_sys
->ctx
.enc_params
.y_range_me
= strtol(psz_start
, &psz_end
, 10);
682 if( *psz_end
!= '\0' || psz_end
== psz_start
) {
683 msg_Err( p_enc
, "Invalid simple search range: %s", psz_tmp
);
687 if( p_sys
->ctx
.enc_params
.x_range_me
< 0 ||
688 p_sys
->ctx
.enc_params
.y_range_me
< 0 )
690 msg_Err( p_enc
, "Invalid negative simple search range: %s", psz_tmp
);
694 p_sys
->ctx
.enc_params
.full_search
= 1;
698 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
699 p_sys
->ctx
.enc_params
.combined_me
= var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_ME_COMBINED
);
702 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTINTRA
);
704 p_sys
->ctx
.enc_params
.intra_wlt_filter
= i_tmp
;
706 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTINTER
);
708 p_sys
->ctx
.enc_params
.inter_wlt_filter
= i_tmp
;
710 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_DWTDEPTH
);
712 p_sys
->ctx
.enc_params
.wlt_depth
= i_tmp
;
714 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_MULTIQUANT
);
716 p_sys
->ctx
.enc_params
.multi_quants
= i_tmp
;
718 i_tmp
= var_GetInteger( p_enc
, ENC_CFG_PREFIX ENC_SPARTITION
);
720 p_sys
->ctx
.enc_params
.spatial_partition
= i_tmp
;
722 p_sys
->ctx
.enc_params
.using_ac
= !var_GetBool( p_enc
, ENC_CFG_PREFIX ENC_NOAC
);
724 f_tmp
= var_GetFloat( p_enc
, ENC_CFG_PREFIX ENC_CPD
);
726 p_sys
->ctx
.enc_params
.cpd
= f_tmp
;
728 /* Allocate the buffer for inputing frames into the encoder */
729 if( ( p_sys
->p_buffer_in
= malloc( p_sys
->i_buffer_in
) ) == NULL
)
731 CloseEncoder( p_this
);
735 /* Set up output buffer */
736 /* Unfortunately it isn't possible to determine if the buffer
737 * is too small (and then reallocate it) */
738 p_sys
->i_buffer_out
= 4096 + p_sys
->i_buffer_in
;
739 if( ( p_sys
->p_buffer_out
= malloc( p_sys
->i_buffer_out
) ) == NULL
)
741 CloseEncoder( p_this
);
747 CloseEncoder( p_this
);
751 /* Attempt to find dirac picture number in an encapsulation unit */
752 static int ReadDiracPictureNumber( uint32_t *p_picnum
, block_t
*p_block
)
755 /* protect against falling off the edge */
756 while( u_pos
+ 13 < p_block
->i_buffer
)
758 /* find the picture startcode */
759 if( p_block
->p_buffer
[u_pos
] & 0x08 )
761 *p_picnum
= GetDWBE( p_block
->p_buffer
+ u_pos
+ 9 );
764 /* skip to the next dirac data unit */
765 uint32_t u_npo
= GetDWBE( p_block
->p_buffer
+ u_pos
+ 1 );
766 assert( u_npo
<= UINT32_MAX
- u_pos
);
774 /****************************************************************************
775 * Encode: the whole thing
776 ****************************************************************************
777 * This function spits out encapsulation units.
778 ****************************************************************************/
779 static block_t
*Encode( encoder_t
*p_enc
, picture_t
*p_pic
)
781 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
782 block_t
*p_block
, *p_output_chain
= NULL
;
783 int i_plane
, i_line
, i_width
, i_src_stride
;
786 /* we only know if the sequence is interlaced when the first
787 * picture arrives, so final setup is done here */
788 /* XXX todo, detect change of interlace */
789 p_sys
->ctx
.src_params
.topfieldfirst
= p_pic
->b_top_field_first
;
790 p_sys
->ctx
.src_params
.source_sampling
= !p_pic
->b_progressive
;
792 if( p_sys
->b_auto_field_coding
)
793 p_sys
->ctx
.enc_params
.picture_coding_mode
= !p_pic
->b_progressive
;
795 if( !p_sys
->p_dirac
)
798 /* Initialise the encoder with the encoder context */
799 p_sys
->p_dirac
= dirac_encoder_init( &p_sys
->ctx
, 0 );
800 if( !p_sys
->p_dirac
)
802 msg_Err( p_enc
, "Failed to initialize dirac encoder\n" );
806 date_Init( &date
, p_enc
->fmt_in
.video
.i_frame_rate
, p_enc
->fmt_in
.video
.i_frame_rate_base
);
807 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
808 int i_delayinpics
= dirac_encoder_ptsoffset( p_sys
->p_dirac
);
809 i_delayinpics
/= p_sys
->ctx
.enc_params
.picture_coding_mode
+ 1;
810 date_Increment( &date
, i_delayinpics
);
812 date_Increment( &date
, 1 );
814 p_sys
->i_pts_offset
= date_Get( &date
);
816 /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
817 * for each frame input. Calculate time between fields for offsetting
818 * the second field later. */
819 if( 1 == p_sys
->ctx
.enc_params
.picture_coding_mode
)
821 date_Set( &date
, 0 );
822 date_Increment( &date
, 1 );
823 p_sys
->i_field_time
= date_Get( &date
) / 2;
827 /* Copy input picture into encoder input buffer (stride by stride) */
828 /* Would be lovely to just pass the picture in, but there is noway for the
829 * library to free it */
830 p_dst
= p_sys
->p_buffer_in
;
831 for( i_plane
= 0; i_plane
< p_pic
->i_planes
; i_plane
++ )
833 uint8_t *p_src
= p_pic
->p
[i_plane
].p_pixels
;
834 i_width
= p_pic
->p
[i_plane
].i_visible_pitch
;
835 i_src_stride
= p_pic
->p
[i_plane
].i_pitch
;
837 for( i_line
= 0; i_line
< p_pic
->p
[i_plane
].i_visible_lines
; i_line
++ )
839 vlc_memcpy( p_dst
, p_src
, i_width
);
841 p_src
+= i_src_stride
;
845 /* Load one frame of data into encoder */
846 if( dirac_encoder_load( p_sys
->p_dirac
, p_sys
->p_buffer_in
,
847 p_sys
->i_buffer_in
) < 0 )
849 msg_Dbg( p_enc
, "dirac_encoder_load() error" );
853 /* store pts in a lookaside buffer, so that the same pts may
854 * be used for the picture in coded order */
855 StorePicturePTS( p_enc
, p_sys
->i_input_picnum
, p_pic
->date
);
856 p_sys
->i_input_picnum
++;
858 /* store dts in a queue, so that they appear in order in
860 p_block
= block_New( p_enc
, 1 );
866 p_block
->i_dts
= p_pic
->date
- p_sys
->i_pts_offset
;
867 block_FifoPut( p_sys
->p_dts_fifo
, p_block
);
870 /* for field coding mode, insert an extra value into both the
871 * pts lookaside buffer and dts queue, offset to correspond
872 * to a one field delay. */
873 if( 1 == p_sys
->ctx
.enc_params
.picture_coding_mode
)
875 StorePicturePTS( p_enc
, p_sys
->i_input_picnum
, p_pic
->date
+ p_sys
->i_field_time
);
876 p_sys
->i_input_picnum
++;
878 p_block
= block_New( p_enc
, 1 );
884 p_block
->i_dts
= p_pic
->date
- p_sys
->i_pts_offset
+ p_sys
->i_field_time
;
885 block_FifoPut( p_sys
->p_dts_fifo
, p_block
);
889 dirac_encoder_state_t state
;
890 /* Retrieve encoded frames from encoder */
893 p_sys
->p_dirac
->enc_buf
.buffer
= p_sys
->p_buffer_out
;
894 p_sys
->p_dirac
->enc_buf
.size
= p_sys
->i_buffer_out
;
895 state
= dirac_encoder_output( p_sys
->p_dirac
);
898 case ENC_STATE_AVAIL
: {
901 /* extract data from encoder temporary buffer. */
902 p_block
= block_New( p_enc
, p_sys
->p_dirac
->enc_buf
.size
);
908 memcpy( p_block
->p_buffer
, p_sys
->p_dirac
->enc_buf
.buffer
,
909 p_sys
->p_dirac
->enc_buf
.size
);
911 /* if some flags were set for a previous block, prevent
912 * them from getting lost */
914 p_block
->i_flags
|= p_sys
->p_chain
->i_flags
;
916 /* store all extracted blocks in a chain and gather up when an
917 * entire encapsulation unit is avaliable (ends with a picture) */
918 block_ChainAppend( &p_sys
->p_chain
, p_block
);
920 /* Presence of a Sequence header indicates a seek point */
921 if( 0 == p_block
->p_buffer
[4] )
923 p_block
->i_flags
|= BLOCK_FLAG_TYPE_I
;
925 if( !p_enc
->fmt_out
.p_extra
) {
926 const uint8_t eos
[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
927 uint32_t len
= GetDWBE( p_block
->p_buffer
+ 5 );
928 /* if it hasn't been done so far, stash a copy of the
929 * sequence header for muxers such as ogg */
930 /* The OggDirac spec advises that a Dirac EOS DataUnit
931 * is appended to the sequence header to allow guard
932 * against poor streaming servers */
933 /* XXX, should this be done using the packetizer ? */
934 p_enc
->fmt_out
.p_extra
= malloc( len
+ sizeof(eos
) );
935 if( !p_enc
->fmt_out
.p_extra
)
940 memcpy( p_enc
->fmt_out
.p_extra
, p_block
->p_buffer
, len
);
941 memcpy( (uint8_t*)p_enc
->fmt_out
.p_extra
+ len
, eos
, sizeof(eos
) );
942 SetDWBE( (uint8_t*)p_enc
->fmt_out
.p_extra
+ len
+ 10, len
);
943 p_enc
->fmt_out
.i_extra
= len
+ sizeof(eos
);
947 if( ReadDiracPictureNumber( &pic_num
, p_block
) )
949 /* Finding a picture terminates an ecapsulation unit, gather
950 * all data and output; use the next dts value queued up
951 * and find correct pts in the tlb */
952 p_block
= block_FifoGet( p_sys
->p_dts_fifo
);
953 p_sys
->p_chain
->i_dts
= p_block
->i_dts
;
954 p_sys
->p_chain
->i_pts
= GetPicturePTS( p_enc
, pic_num
);
955 block_Release( p_block
);
956 block_ChainAppend( &p_output_chain
, block_ChainGather( p_sys
->p_chain
) );
957 p_sys
->p_chain
= NULL
;
964 case ENC_STATE_BUFFER
:
966 case ENC_STATE_INVALID
:
970 } while( state
== ENC_STATE_AVAIL
);
972 return p_output_chain
;
975 /*****************************************************************************
976 * CloseEncoder: dirac encoder destruction
977 *****************************************************************************/
978 static void CloseEncoder( vlc_object_t
*p_this
)
980 encoder_t
*p_enc
= (encoder_t
*)p_this
;
981 encoder_sys_t
*p_sys
= p_enc
->p_sys
;
983 /* Free the encoder resources */
985 dirac_encoder_close( p_sys
->p_dirac
);
987 free( p_sys
->p_buffer_in
);
988 free( p_sys
->p_buffer_out
);
990 if( p_sys
->p_dts_fifo
)
991 block_FifoRelease( p_sys
->p_dts_fifo
);
992 block_ChainRelease( p_sys
->p_chain
);