]> git.sesse.net Git - vlc/blob - modules/codec/dirac.c
projectm: add missing return.
[vlc] / modules / codec / dirac.c
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$
11  *
12  * Authors: Gildas Bazin <gbazin@videolan.org>
13  * Rewritten: David Flynn <davidf at rd.bbc.co.uk>
14  *
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.
19  *
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.
24  *
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  *****************************************************************************/
29
30 /*****************************************************************************
31  * Preamble
32  *****************************************************************************/
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <limits.h>
38 #include <assert.h>
39
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_codec.h>
43 #include <vlc_sout.h>
44
45 #include <libdirac_encoder/dirac_encoder.h>
46
47 #ifndef DIRAC_RESEARCH_VERSION_ATLEAST
48 # define DIRAC_RESEARCH_VERSION_ATLEAST(x,y,z) 0
49 #endif
50
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 );
57
58 #define ENC_CFG_PREFIX "sout-dirac-"
59
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")
63
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")
67
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")
72
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") };
81
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")
85
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") };
94
95 #define ENC_L1SEP "l1-sep"
96 #define ENC_L1SEP_TEXT N_("Distance between 'P' frames")
97 #define ENC_L1SEP_LONGTEXT ENC_L1SEP_TEXT
98
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
102
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"),
113   };
114
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 ""
118
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 ""
122
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")
128
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")
133
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")
138
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" };
144
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")
150
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")
154
155 #define ENC_DWTINTRA "dwt-intra"
156 #define ENC_DWTINTRA_TEXT N_("Intra picture DWT filter")
157 #define ENC_DWTINTRA_LONGTEXT ENC_DWTINTRA_TEXT
158
159 #define ENC_DWTINTER "dwt-inter"
160 #define ENC_DWTINTER_TEXT N_("Inter picture DWT filter")
161 #define ENC_DWTINTER_LONGTEXT ENC_DWTINTER_TEXT
162
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")
166
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)")
171
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
176
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")
180
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
186
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
196 };
197
198
199 /*****************************************************************************
200  * Module descriptor
201  *****************************************************************************/
202
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 )
209
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.);
213
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);
217
218     add_bool( ENC_CFG_PREFIX ENC_LOSSLESS, false, NULL,
219               ENC_LOSSLESS_TEXT, ENC_LOSSLESS_LONGTEXT, false )
220
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 );
224
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);
228
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 );
232
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);
236
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);
240
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 );
244
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 );
248
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);
253
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);
258
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);
262
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);
271
272     add_string( ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH, "", NULL,
273               ENC_ME_SIMPLESEARCH_TEXT, ENC_ME_SIMPLESEARCH_LONGTEXT, false )
274
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
279
280     add_integer( ENC_CFG_PREFIX ENC_DWTINTRA, -1, NULL,
281                  ENC_DWTINTRA_TEXT, ENC_DWTINTRA_LONGTEXT, false )
282     change_integer_range(-1, 6);
283
284     add_integer( ENC_CFG_PREFIX ENC_DWTINTER, -1, NULL,
285                  ENC_DWTINTER_TEXT, ENC_DWTINTER_LONGTEXT, false )
286     change_integer_range(-1, 6);
287
288     add_integer( ENC_CFG_PREFIX ENC_DWTDEPTH, -1, NULL,
289                  ENC_DWTDEPTH_TEXT, ENC_DWTDEPTH_LONGTEXT, false )
290     change_integer_range(-1, 4);
291
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);
297
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);
303
304     add_bool( ENC_CFG_PREFIX ENC_NOAC, false, NULL,
305               ENC_NOAC_TEXT, ENC_NOAC_LONGTEXT, false )
306
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()
312
313 /*****************************************************************************
314  * picture_pts_t : store pts alongside picture number, not carried through
315  * encoder
316  *****************************************************************************/
317 struct picture_pts_t
318 {
319    bool b_empty;      /* entry is invalid */
320    uint32_t u_pnum;  /* dirac picture number */
321    mtime_t i_pts;    /* associated pts */
322 };
323
324 /*****************************************************************************
325  * encoder_sys_t : dirac encoder descriptor
326  *****************************************************************************/
327 #define PTS_TLB_SIZE 256
328 struct encoder_sys_t
329 {
330     dirac_encoder_t *p_dirac;
331     dirac_encoder_context_t ctx;
332     bool b_auto_field_coding;
333
334     uint8_t *p_buffer_in;
335     int i_buffer_in;
336     uint32_t i_input_picnum;
337     block_fifo_t *p_dts_fifo;
338
339     int i_buffer_out;
340     uint8_t *p_buffer_out;
341     block_t *p_chain;
342
343     struct picture_pts_t pts_tlb[PTS_TLB_SIZE];
344     mtime_t i_pts_offset;
345     mtime_t i_field_time;
346 };
347
348 static struct
349 {
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},
377 };
378
379 /*****************************************************************************
380  * ResetPTStlb: Purge all entries in @p_dec@'s PTS-tlb
381  *****************************************************************************/
382 static void ResetPTStlb( encoder_t *p_enc )
383 {
384     encoder_sys_t *p_sys = p_enc->p_sys;
385     for( int i=0; i<PTS_TLB_SIZE; i++)
386     {
387         p_sys->pts_tlb[i].b_empty = true;
388     }
389 }
390
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 )
395 {
396     encoder_sys_t *p_sys = p_enc->p_sys;
397
398     for( int i=0; i<PTS_TLB_SIZE; i++ )
399     {
400         if( p_sys->pts_tlb[i].b_empty )
401         {
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;
405
406             return;
407         }
408     }
409
410     msg_Err( p_enc, "Could not store PTS %"PRId64" for frame %u", i_pts, u_pnum );
411 }
412
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 )
417 {
418     encoder_sys_t *p_sys = p_enc->p_sys;
419
420     for( int i=0; i<PTS_TLB_SIZE; i++ )
421     {
422         if( !p_sys->pts_tlb[i].b_empty &&
423             p_sys->pts_tlb[i].u_pnum == u_pnum )
424         {
425              p_sys->pts_tlb[i].b_empty = true;
426              return p_sys->pts_tlb[i].i_pts;
427         }
428     }
429
430     msg_Err( p_enc, "Could not retrieve PTS for picture %u", u_pnum );
431     return 0;
432 }
433
434 /*****************************************************************************
435  * OpenEncoder: probe the encoder and return score
436  *****************************************************************************/
437 static int OpenEncoder( vlc_object_t *p_this )
438 {
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;
444
445     if( p_enc->fmt_out.i_codec != VLC_CODEC_DIRAC &&
446         !p_enc->b_force )
447     {
448         return VLC_EGENERIC;
449     }
450
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 )
453     {
454         msg_Err( p_enc, "Framerate and picture dimensions must be non-zero" );
455         return VLC_EGENERIC;
456     }
457
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;
461
462     p_enc->p_sys = p_sys;
463     p_enc->pf_encode_video = Encode;
464     p_enc->fmt_out.i_codec = VLC_CODEC_DIRAC;
465     p_enc->fmt_out.i_cat = VIDEO_ES;
466
467     if( ( p_sys->p_dts_fifo = block_FifoNew() ) == NULL )
468     {
469         CloseEncoder( p_this );
470         return VLC_ENOMEM;
471     }
472
473     ResetPTStlb( p_enc );
474
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.
481      */
482     do
483     {
484         if( dirac_format_guess[i].i_height > p_enc->fmt_in.video.i_height )
485         {
486             guessed_video_fmt = dirac_format_guess[i-1].i_vf;
487             break;
488         }
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;
495
496         guessed_video_fmt = dirac_format_guess[i].i_vf;
497         break;
498     } while( dirac_format_guess[++i].i_height );
499
500     dirac_encoder_context_init( &p_sys->ctx, guessed_video_fmt );
501
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_sar_num,
510                  p_enc->fmt_in.video.i_sar_den, 0 );
511     p_sys->ctx.src_params.pix_asr.numerator = u_asr_num;
512     p_sys->ctx.src_params.pix_asr.denominator = u_asr_den;
513
514     config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
515
516     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CHROMAFMT );
517     if( !psz_tmp )
518         goto error;
519     else if( !strcmp( psz_tmp, "420" ) ) {
520         p_enc->fmt_in.i_codec = VLC_CODEC_I420;
521         p_enc->fmt_in.video.i_bits_per_pixel = 12;
522         p_sys->ctx.src_params.chroma = format420;
523         p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 3 / 2;
524     }
525     else if( !strcmp( psz_tmp, "422" ) ) {
526         p_enc->fmt_in.i_codec = VLC_CODEC_I422;
527         p_enc->fmt_in.video.i_bits_per_pixel = 16;
528         p_sys->ctx.src_params.chroma = format422;
529         p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 2;
530     }
531     else if( !strcmp( psz_tmp, "444" ) ) {
532         p_enc->fmt_in.i_codec = VLC_CODEC_I444;
533         p_enc->fmt_in.video.i_bits_per_pixel = 24;
534         p_sys->ctx.src_params.chroma = format444;
535         p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 3;
536     }
537     else {
538         msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
539         free( psz_tmp );
540         goto error;
541     }
542     free( psz_tmp );
543
544     p_sys->ctx.enc_params.qf = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_QUALITY_FACTOR );
545
546     /* use bitrate from sout-transcode-vb in kbps */
547     p_sys->ctx.enc_params.trate = p_enc->fmt_out.i_bitrate / 1000;
548     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_TARGETRATE );
549     if( i_tmp > -1 )
550         p_sys->ctx.enc_params.trate = i_tmp;
551     p_enc->fmt_out.i_bitrate = p_sys->ctx.enc_params.trate * 1000;
552
553     p_sys->ctx.enc_params.lossless = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_LOSSLESS );
554
555     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_PREFILTER );
556     if( !psz_tmp )
557         goto error;
558     else if( !strcmp( psz_tmp, "none" ) ) {
559         p_sys->ctx.enc_params.prefilter = NO_PF;
560     }
561     else if( !strcmp( psz_tmp, "cwm" ) ) {
562         p_sys->ctx.enc_params.prefilter = CWM;
563     }
564     else if( !strcmp( psz_tmp, "rectlp" ) ) {
565         p_sys->ctx.enc_params.prefilter = RECTLP;
566     }
567     else if( !strcmp( psz_tmp, "diaglp" ) ) {
568         p_sys->ctx.enc_params.prefilter = DIAGLP;
569     }
570     else {
571         msg_Err( p_enc, "Invalid prefilter: %s", psz_tmp );
572         free( psz_tmp );
573         goto error;
574     }
575     free( psz_tmp );
576
577     p_sys->ctx.enc_params.prefilter_strength =
578         var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH );
579
580     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1SEP );
581     if( i_tmp > -1 )
582         p_sys->ctx.enc_params.L1_sep = i_tmp;
583
584     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1NUM );
585     if( i_tmp > -1 )
586         p_sys->ctx.enc_params.num_L1 = i_tmp;
587
588     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CODINGMODE );
589     if( !psz_tmp )
590         goto error;
591     else if( !strcmp( psz_tmp, "auto" ) ) {
592         p_sys->b_auto_field_coding = true;
593     }
594     else if( !strcmp( psz_tmp, "progressive" ) ) {
595         p_sys->b_auto_field_coding = false;
596         p_sys->ctx.enc_params.picture_coding_mode = 0;
597     }
598     else if( !strcmp( psz_tmp, "field" ) ) {
599         p_sys->b_auto_field_coding = false;
600         p_sys->ctx.enc_params.picture_coding_mode = 1;
601     }
602     else {
603         msg_Err( p_enc, "Invalid codingmode: %s", psz_tmp );
604         free( psz_tmp );
605         goto error;
606     }
607     free( psz_tmp );
608
609     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MVPREC );
610     if( !psz_tmp )
611         goto error;
612     else if( !strcmp( psz_tmp, "1" ) ) {
613         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_PIXEL;
614     }
615     else if( !strcmp( psz_tmp, "1/2" ) ) {
616         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_HALF_PIXEL;
617     }
618     else if( !strcmp( psz_tmp, "1/4" ) ) {
619         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_QUARTER_PIXEL;
620     }
621     else if( !strcmp( psz_tmp, "1/8" ) ) {
622         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_EIGHTH_PIXEL;
623     }
624     else {
625         msg_Err( p_enc, "Invalid mv-prec: %s", psz_tmp );
626         free( psz_tmp );
627         goto error;
628     }
629     free( psz_tmp );
630
631     /*
632      * {x,y}b{len,sep} must be multiples of 4
633      */
634     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_WIDTH );
635     if( i_tmp > -1 )
636         p_sys->ctx.enc_params.xbsep = i_tmp / 4 * 4;
637
638     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_HEIGHT );
639     if( i_tmp > -1 )
640         p_sys->ctx.enc_params.ybsep = i_tmp / 4 * 4;
641
642     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP );
643     if( i_tmp > -1 ) {
644         p_sys->ctx.enc_params.xblen = p_sys->ctx.enc_params.xbsep * (100 + i_tmp) / 400 * 4;
645         p_sys->ctx.enc_params.yblen = p_sys->ctx.enc_params.ybsep * (100 + i_tmp) / 400 * 4;
646     }
647
648     /*
649      * {x,y}blen >= {x,y}bsep
650      * {x,y}blen <= 2* {x,y}bsep
651      */
652     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_XBLEN );
653     if( i_tmp > -1 ) {
654         int xblen = __MAX( i_tmp, p_sys->ctx.enc_params.xbsep );
655         xblen = __MIN( xblen, 2 * p_sys->ctx.enc_params.xbsep );
656         p_sys->ctx.enc_params.xblen = xblen;
657     }
658
659     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_YBLEN );
660     if( i_tmp > -1 ) {
661         int yblen = __MAX( i_tmp, p_sys->ctx.enc_params.ybsep );
662         yblen = __MIN( yblen, 2 * p_sys->ctx.enc_params.ybsep );
663         p_sys->ctx.enc_params.yblen = yblen;
664     }
665
666     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH );
667     if( !psz_tmp )
668         goto error;
669     if( *psz_tmp != '\0' ) {
670         /* of the form [0-9]+:[0-9]+ */
671         char *psz_start = psz_tmp;
672         char *psz_end = psz_tmp;
673         p_sys->ctx.enc_params.x_range_me = strtol(psz_start, &psz_end, 10);
674         if( *psz_end != ':'  || psz_end == psz_start ) {
675             msg_Err( p_enc, "Invalid simple search range: %s", psz_tmp );
676             free( psz_tmp );
677             goto error;
678         }
679         psz_start = ++psz_end;
680         p_sys->ctx.enc_params.y_range_me = strtol(psz_start, &psz_end, 10);
681         if( *psz_end != '\0'  || psz_end == psz_start ) {
682             msg_Err( p_enc, "Invalid simple search range: %s", psz_tmp );
683             free( psz_tmp );
684             goto error;
685         }
686         if( p_sys->ctx.enc_params.x_range_me < 0 ||
687             p_sys->ctx.enc_params.y_range_me < 0 )
688         {
689             msg_Err( p_enc, "Invalid negative simple search range: %s", psz_tmp );
690             free( psz_tmp );
691             goto error;
692         }
693         p_sys->ctx.enc_params.full_search = 1;
694     }
695     free( psz_tmp );
696
697 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
698     p_sys->ctx.enc_params.combined_me = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_ME_COMBINED );
699 #endif
700
701     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTRA );
702     if( i_tmp > -1 )
703         p_sys->ctx.enc_params.intra_wlt_filter = i_tmp;
704
705     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTER );
706     if( i_tmp > -1 )
707         p_sys->ctx.enc_params.inter_wlt_filter = i_tmp;
708
709     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTDEPTH );
710     if( i_tmp > -1 )
711         p_sys->ctx.enc_params.wlt_depth = i_tmp;
712
713     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MULTIQUANT );
714     if( i_tmp > -1 )
715         p_sys->ctx.enc_params.multi_quants = i_tmp;
716
717     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_SPARTITION );
718     if( i_tmp > -1 )
719         p_sys->ctx.enc_params.spatial_partition = i_tmp;
720
721     p_sys->ctx.enc_params.using_ac = !var_GetBool( p_enc, ENC_CFG_PREFIX ENC_NOAC );
722
723     f_tmp = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_CPD );
724     if( f_tmp > -1 )
725         p_sys->ctx.enc_params.cpd = f_tmp;
726
727     /* Allocate the buffer for inputing frames into the encoder */
728     if( ( p_sys->p_buffer_in = malloc( p_sys->i_buffer_in ) ) == NULL )
729     {
730         CloseEncoder( p_this );
731         return VLC_ENOMEM;
732     }
733
734     /* Set up output buffer */
735     /* Unfortunately it isn't possible to determine if the buffer
736      * is too small (and then reallocate it) */
737     p_sys->i_buffer_out = 4096 + p_sys->i_buffer_in;
738     if( ( p_sys->p_buffer_out = malloc( p_sys->i_buffer_out ) ) == NULL )
739     {
740         CloseEncoder( p_this );
741         return VLC_ENOMEM;
742     }
743
744     return VLC_SUCCESS;
745 error:
746     CloseEncoder( p_this );
747     return VLC_EGENERIC;
748 }
749
750 /* Attempt to find dirac picture number in an encapsulation unit */
751 static int ReadDiracPictureNumber( uint32_t *p_picnum, block_t *p_block )
752 {
753     uint32_t u_pos = 4;
754     /* protect against falling off the edge */
755     while( u_pos + 13 < p_block->i_buffer )
756     {
757         /* find the picture startcode */
758         if( p_block->p_buffer[u_pos] & 0x08 )
759         {
760             *p_picnum = GetDWBE( p_block->p_buffer + u_pos + 9 );
761             return 1;
762         }
763         /* skip to the next dirac data unit */
764         uint32_t u_npo = GetDWBE( p_block->p_buffer + u_pos + 1 );
765         assert( u_npo <= UINT32_MAX - u_pos );
766         if( u_npo == 0 )
767             u_npo = 13;
768         u_pos += u_npo;
769     }
770     return 0;
771 }
772
773 /****************************************************************************
774  * Encode: the whole thing
775  ****************************************************************************
776  * This function spits out encapsulation units.
777  ****************************************************************************/
778 static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
779 {
780     encoder_sys_t *p_sys = p_enc->p_sys;
781     block_t *p_block, *p_output_chain = NULL;
782     int i_plane, i_line, i_width, i_src_stride;
783     uint8_t *p_dst;
784
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;
790
791     if( p_sys->b_auto_field_coding )
792         p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive;
793
794     if( !p_sys->p_dirac )
795     {
796         date_t date;
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 )
800         {
801             msg_Err( p_enc, "Failed to initialize dirac encoder" );
802             p_enc->b_error = 1;
803             return NULL;
804         }
805         date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base );
806 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
807         int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac );
808         i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1;
809         date_Increment( &date, i_delayinpics );
810 #else
811         date_Increment( &date, 1 );
812 #endif
813         p_sys->i_pts_offset = date_Get( &date );
814
815         /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
816          * for each frame input. Calculate time between fields for offsetting
817          * the second field later. */
818         if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
819         {
820             date_Set( &date, 0 );
821             date_Increment( &date, 1 );
822             p_sys->i_field_time = date_Get( &date ) / 2;
823         }
824     }
825
826     /* Copy input picture into encoder input buffer (stride by stride) */
827     /* Would be lovely to just pass the picture in, but there is noway for the
828      * library to free it */
829     p_dst = p_sys->p_buffer_in;
830     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
831     {
832         uint8_t *p_src = p_pic->p[i_plane].p_pixels;
833         i_width = p_pic->p[i_plane].i_visible_pitch;
834         i_src_stride = p_pic->p[i_plane].i_pitch;
835
836         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
837         {
838             vlc_memcpy( p_dst, p_src, i_width );
839             p_dst += i_width;
840             p_src += i_src_stride;
841         }
842     }
843
844     /* Load one frame of data into encoder */
845     if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in,
846                             p_sys->i_buffer_in ) < 0 )
847     {
848         msg_Dbg( p_enc, "dirac_encoder_load() error" );
849         return NULL;
850     }
851
852     /* store pts in a lookaside buffer, so that the same pts may
853      * be used for the picture in coded order */
854     StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date );
855     p_sys->i_input_picnum++;
856
857     /* store dts in a queue, so that they appear in order in
858      * coded order */
859     p_block = block_New( p_enc, 1 );
860     if( !p_block )
861     {
862         p_enc->b_error = 1;
863         return NULL;
864     }
865     p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
866     block_FifoPut( p_sys->p_dts_fifo, p_block );
867     p_block = NULL;
868
869     /* for field coding mode, insert an extra value into both the
870      * pts lookaside buffer and dts queue, offset to correspond
871      * to a one field delay. */
872     if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
873     {
874         StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time );
875         p_sys->i_input_picnum++;
876
877         p_block = block_New( p_enc, 1 );
878         if( !p_block )
879         {
880             p_enc->b_error = 1;
881             return NULL;
882         }
883         p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time;
884         block_FifoPut( p_sys->p_dts_fifo, p_block );
885         p_block = NULL;
886     }
887
888     dirac_encoder_state_t state;
889     /* Retrieve encoded frames from encoder */
890     do
891     {
892         p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out;
893         p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out;
894         state = dirac_encoder_output( p_sys->p_dirac );
895         switch( state )
896         {
897         case ENC_STATE_AVAIL: {
898             uint32_t pic_num;
899
900             /* extract data from encoder temporary buffer. */
901             p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
902             if( !p_block )
903             {
904                 p_enc->b_error = 1;
905                 return NULL;
906             }
907             memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer,
908                     p_sys->p_dirac->enc_buf.size );
909
910             /* if some flags were set for a previous block, prevent
911              * them from getting lost */
912             if( p_sys->p_chain )
913                 p_block->i_flags |= p_sys->p_chain->i_flags;
914
915             /* store all extracted blocks in a chain and gather up when an
916              * entire encapsulation unit is avaliable (ends with a picture) */
917             block_ChainAppend( &p_sys->p_chain, p_block );
918
919             /* Presence of a Sequence header indicates a seek point */
920             if( 0 == p_block->p_buffer[4] )
921             {
922                 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
923
924                 if( !p_enc->fmt_out.p_extra ) {
925                     const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
926                     uint32_t len = GetDWBE( p_block->p_buffer + 5 );
927                     /* if it hasn't been done so far, stash a copy of the
928                      * sequence header for muxers such as ogg */
929                     /* The OggDirac spec advises that a Dirac EOS DataUnit
930                      * is appended to the sequence header to allow guard
931                      * against poor streaming servers */
932                     /* XXX, should this be done using the packetizer ? */
933                     p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) );
934                     if( !p_enc->fmt_out.p_extra )
935                     {
936                         p_enc->b_error = 1;
937                         return NULL;
938                     }
939                     memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len);
940                     memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) );
941                     SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len );
942                     p_enc->fmt_out.i_extra = len + sizeof(eos);
943                 }
944             }
945
946             if( ReadDiracPictureNumber( &pic_num, p_block ) )
947             {
948                 /* Finding a picture terminates an ecapsulation unit, gather
949                  * all data and output; use the next dts value queued up
950                  * and find correct pts in the tlb */
951                 p_block = block_FifoGet( p_sys->p_dts_fifo );
952                 p_sys->p_chain->i_dts = p_block->i_dts;
953                 p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num );
954                 block_Release( p_block );
955                 block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) );
956                 p_sys->p_chain = NULL;
957             } else {
958                 p_block = NULL;
959             }
960             break;
961             }
962
963         case ENC_STATE_BUFFER:
964             break;
965         case ENC_STATE_INVALID:
966         default:
967             break;
968         }
969     } while( state == ENC_STATE_AVAIL );
970
971     return p_output_chain;
972 }
973
974 /*****************************************************************************
975  * CloseEncoder: dirac encoder destruction
976  *****************************************************************************/
977 static void CloseEncoder( vlc_object_t *p_this )
978 {
979     encoder_t *p_enc = (encoder_t *)p_this;
980     encoder_sys_t *p_sys = p_enc->p_sys;
981
982     /* Free the encoder resources */
983     if( p_sys->p_dirac )
984         dirac_encoder_close( p_sys->p_dirac );
985
986     free( p_sys->p_buffer_in );
987     free( p_sys->p_buffer_out );
988
989     if( p_sys->p_dts_fifo )
990         block_FifoRelease( p_sys->p_dts_fifo );
991     block_ChainRelease( p_sys->p_chain );
992
993     free( p_sys );
994 }