remove unndeed variables
[vlc/asuraparaju-public.git] / modules / codec / dirac.c
blobb7a300e4a985d0292f8e1b962b270f95312491f3
1 /*****************************************************************************
2 * dirac.c: Dirac encoder module making use of libdirac (dirac-research).
3 * (http://www.bbc.co.uk/rd/projects/dirac/index.shtml)
4 * ##
5 * ## NB, this is a temporary encoder only module until schroedinger
6 * ## offers superior encoding quality than dirac-research
7 * ##
8 *****************************************************************************
9 * Copyright (C) 2004-2008 the VideoLAN team
10 * $Id$
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 /*****************************************************************************
31 * Preamble
32 *****************************************************************************/
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
37 #include <limits.h>
39 #include <vlc_common.h>
40 #include <vlc_plugin.h>
41 #include <vlc_codec.h>
42 #include <vlc_sout.h>
43 #include <vlc_vout.h>
45 #include <libdirac_encoder/dirac_encoder.h>
47 #ifndef DIRAC_RESEARCH_VERSION_ATLEAST
48 # define DIRAC_RESEARCH_VERSION_ATLEAST(x,y,z) 0
49 #endif
51 /*****************************************************************************
52 * Local prototypes
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 " \
149 "of +/-x, +/-y")
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,
194 ENC_CPD,
195 NULL
199 /*****************************************************************************
200 * Module descriptor
201 *****************************************************************************/
203 vlc_module_begin()
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 );
278 #endif
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);
311 vlc_module_end()
313 /*****************************************************************************
314 * picture_pts_t : store pts alongside picture number, not carried through
315 * encoder
316 *****************************************************************************/
317 struct picture_pts_t
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
328 struct encoder_sys_t
330 dirac_encoder_t *p_dirac;
331 dirac_encoder_context_t ctx;
332 bool b_auto_field_coding;
334 uint8_t *p_buffer_in;
335 int i_buffer_in;
336 uint32_t i_input_picnum;
337 block_fifo_t *p_dts_fifo;
339 int i_buffer_out;
340 uint8_t *p_buffer_out;
341 block_t *p_chain;
343 struct picture_pts_t pts_tlb[PTS_TLB_SIZE];
344 mtime_t i_pts_offset;
345 mtime_t i_field_time;
348 static struct
350 unsigned int i_height;
351 int i_approx_fps;
352 VideoFormat i_vf;
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},
376 {0, 0, 0},
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;
406 return;
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 );
431 return 0;
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;
441 int i_tmp;
442 float f_tmp;
443 char *psz_tmp;
445 if( p_enc->fmt_out.i_codec != VLC_FOURCC('d','r','a','c') &&
446 !p_enc->b_force )
448 return VLC_EGENERIC;
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" );
455 return VLC_EGENERIC;
458 /* Allocate the memory needed to store the decoder's structure */
459 if( ( p_sys = calloc( 1, sizeof(*p_sys) ) ) == NULL )
460 return VLC_ENOMEM;
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 );
470 return VLC_ENOMEM;
473 ResetPTStlb( p_enc );
475 /* guess the video format based upon number of lines and picture height */
476 int i = 0;
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;
487 break;
489 if( dirac_format_guess[i].i_height != p_enc->fmt_in.video.i_height )
490 continue;
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 );
493 if( delta_fps > 2 )
494 continue;
496 guessed_video_fmt = dirac_format_guess[i].i_vf;
497 break;
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,
511 0 );
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 );
518 if( !psz_tmp )
519 goto error;
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;
538 else {
539 msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
540 free( psz_tmp );
541 goto error;
543 free( 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 );
550 if( i_tmp > -1 )
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 );
557 if( !psz_tmp )
558 goto error;
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;
571 else {
572 msg_Err( p_enc, "Invalid prefilter: %s", psz_tmp );
573 free( psz_tmp );
574 goto error;
576 free( 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 );
582 if( i_tmp > -1 )
583 p_sys->ctx.enc_params.L1_sep = i_tmp;
585 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1NUM );
586 if( i_tmp > -1 )
587 p_sys->ctx.enc_params.num_L1 = i_tmp;
589 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CODINGMODE );
590 if( !psz_tmp )
591 goto error;
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;
603 else {
604 msg_Err( p_enc, "Invalid codingmode: %s", psz_tmp );
605 free( psz_tmp );
606 goto error;
608 free( psz_tmp );
610 psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MVPREC );
611 if( !psz_tmp )
612 goto error;
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;
625 else {
626 msg_Err( p_enc, "Invalid mv-prec: %s", psz_tmp );
627 free( psz_tmp );
628 goto error;
630 free( 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 );
636 if( i_tmp > -1 )
637 p_sys->ctx.enc_params.xbsep = i_tmp / 4 * 4;
639 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_HEIGHT );
640 if( i_tmp > -1 )
641 p_sys->ctx.enc_params.ybsep = i_tmp / 4 * 4;
643 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP );
644 if( i_tmp > -1 ) {
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 );
654 if( i_tmp > -1 ) {
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 );
661 if( i_tmp > -1 ) {
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 );
668 if( !psz_tmp )
669 goto error;
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 );
677 free( psz_tmp );
678 goto error;
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 );
684 free( psz_tmp );
685 goto error;
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 );
691 free( psz_tmp );
692 goto error;
694 p_sys->ctx.enc_params.full_search = 1;
696 free( psz_tmp );
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 );
700 #endif
702 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTRA );
703 if( i_tmp > -1 )
704 p_sys->ctx.enc_params.intra_wlt_filter = i_tmp;
706 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTER );
707 if( i_tmp > -1 )
708 p_sys->ctx.enc_params.inter_wlt_filter = i_tmp;
710 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTDEPTH );
711 if( i_tmp > -1 )
712 p_sys->ctx.enc_params.wlt_depth = i_tmp;
714 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MULTIQUANT );
715 if( i_tmp > -1 )
716 p_sys->ctx.enc_params.multi_quants = i_tmp;
718 i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_SPARTITION );
719 if( i_tmp > -1 )
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 );
725 if( f_tmp > -1 )
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 );
732 return VLC_ENOMEM;
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 );
742 return VLC_ENOMEM;
745 return VLC_SUCCESS;
746 error:
747 CloseEncoder( p_this );
748 return VLC_EGENERIC;
751 /* Attempt to find dirac picture number in an encapsulation unit */
752 static int ReadDiracPictureNumber( uint32_t *p_picnum, block_t *p_block )
754 uint32_t u_pos = 4;
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 );
762 return 1;
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 );
767 if( u_npo == 0 )
768 u_npo = 13;
769 u_pos += u_npo;
771 return 0;
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;
784 uint8_t *p_dst;
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 )
797 date_t date;
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" );
803 p_enc->b_error = 1;
804 return NULL;
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 );
811 #else
812 date_Increment( &date, 1 );
813 #endif
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 );
840 p_dst += 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" );
850 return NULL;
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
859 * coded order */
860 p_block = block_New( p_enc, 1 );
861 if( !p_block )
863 p_enc->b_error = 1;
864 return NULL;
866 p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
867 block_FifoPut( p_sys->p_dts_fifo, p_block );
868 p_block = NULL;
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 );
879 if( !p_block )
881 p_enc->b_error = 1;
882 return NULL;
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 );
886 p_block = NULL;
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 );
896 switch( state )
898 case ENC_STATE_AVAIL: {
899 uint32_t pic_num;
901 /* extract data from encoder temporary buffer. */
902 p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
903 if( !p_block )
905 p_enc->b_error = 1;
906 return NULL;
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 */
913 if( p_sys->p_chain )
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 )
937 p_enc->b_error = 1;
938 return NULL;
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;
958 } else {
959 p_block = NULL;
961 break;
964 case ENC_STATE_BUFFER:
965 break;
966 case ENC_STATE_INVALID:
967 default:
968 break;
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 */
984 if( p_sys->p_dirac )
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 );
994 free( p_sys );