]> git.sesse.net Git - vlc/blob - modules/codec/dirac.c
macosx: fixed menubar appearance in fullscreen mode by partially reverting [46c93c9cc...
[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 #include <vlc_vout.h>
45
46 #include <libdirac_encoder/dirac_encoder.h>
47
48 #ifndef DIRAC_RESEARCH_VERSION_ATLEAST
49 # define DIRAC_RESEARCH_VERSION_ATLEAST(x,y,z) 0
50 #endif
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 static int  OpenEncoder( vlc_object_t *p_this );
56 static void CloseEncoder( vlc_object_t *p_this );
57 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
58
59 #define ENC_CFG_PREFIX "sout-dirac-"
60
61 #define ENC_QUALITY_FACTOR "quality"
62 #define ENC_QUALITY_FACTOR_TEXT N_("Constant quality factor")
63 #define ENC_QUALITY_FACTOR_LONGTEXT N_("If bitrate=0, use this value for constant quality")
64
65 #define ENC_TARGETRATE "bitrate"
66 #define ENC_TARGETRATE_TEXT N_("CBR bitrate (kbps)")
67 #define ENC_TARGETRATE_LONGTEXT N_("A value > 0 enables constant bitrate mode")
68
69 #define ENC_LOSSLESS "lossless"
70 #define ENC_LOSSLESS_TEXT N_("Enable lossless coding")
71 #define ENC_LOSSLESS_LONGTEXT N_("Lossless coding ignores bitrate and quality settings, " \
72                                  "allowing for perfect reproduction of the original")
73
74 #define ENC_PREFILTER "prefilter"
75 #define ENC_PREFILTER_TEXT N_("Prefilter")
76 #define ENC_PREFILTER_LONGTEXT N_("Enable adaptive prefiltering")
77 static const char *const enc_prefilter_list[] =
78   { "none", "cwm", "rectlp", "diaglp" };
79 static const char *const enc_prefilter_list_text[] =
80   { N_("none"), N_("Centre Weighted Median"),
81     N_("Rectangular Linear Phase"), N_("Diagonal Linear Phase") };
82
83 #define ENC_PREFILTER_STRENGTH "prefilter-strength"
84 #define ENC_PREFILTER_STRENGTH_TEXT N_("Amount of prefiltering")
85 #define ENC_PREFILTER_STRENGTH_LONGTEXT N_("Higher value implies more prefiltering")
86
87 #define ENC_CHROMAFMT "chroma-fmt"
88 #define ENC_CHROMAFMT_TEXT N_("Chroma format")
89 #define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
90                                   "conversion of the video into that format")
91 static const char *const enc_chromafmt_list[] =
92   { "420", "422", "444" };
93 static const char *const enc_chromafmt_list_text[] =
94   { N_("4:2:0"), N_("4:2:2"), N_("4:4:4") };
95
96 #define ENC_L1SEP "l1-sep"
97 #define ENC_L1SEP_TEXT N_("Distance between 'P' frames")
98 #define ENC_L1SEP_LONGTEXT ENC_L1SEP_TEXT
99
100 #define ENC_L1NUM "num-l1"
101 #define ENC_L1NUM_TEXT N_("Number of 'P' frames per GOP")
102 #define ENC_L1NUM_LONGTEXT ENC_L1NUM_TEXT
103
104 #define ENC_CODINGMODE "coding-mode"
105 #define ENC_CODINGMODE_TEXT N_("Picture coding mode")
106 #define ENC_CODINGMODE_LONGTEXT N_("Field coding is where interlaced fields are coded" \
107                                    " seperately as opposed to a pseudo-progressive frame")
108 static const char *const enc_codingmode_list[] =
109   { "auto", "progressive", "field" };
110 static const char *const enc_codingmode_list_text[] =
111   { N_("auto - let encoder decide based upon input (Best)"),
112     N_("force coding frame as single picture"),
113     N_("force coding frame as seperate interlaced fields"),
114   };
115
116 #define ENC_MCBLK_WIDTH "mc-blk-width"
117 #define ENC_MCBLK_WIDTH_TEXT N_("Width of motion compensation blocks")
118 #define ENC_MCBLK_WIDTH_LONGTEXT ""
119
120 #define ENC_MCBLK_HEIGHT "mc-blk-height"
121 #define ENC_MCBLK_HEIGHT_TEXT N_("Height of motion compensation blocks")
122 #define ENC_MCBLK_HEIGHT_LONGTEXT ""
123
124 /* also known as XBSEP and YBSEP */
125 #define ENC_MCBLK_OVERLAP "mc-blk-overlap"
126 #define ENC_MCBLK_OVERLAP_TEXT N_("Block overlap (%)")
127 #define ENC_MCBLK_OVERLAP_LONGTEXT N_("Amount that each motion block should " \
128                                        "be overlapped by its neighbours")
129
130 /* advanced option only */
131 #define ENC_MCBLK_XBLEN "mc-blk-xblen"
132 #define ENC_MCBLK_XBLEN_TEXT N_("xblen")
133 #define ENC_MCBLK_XBLEN_LONGTEXT N_("Total horizontal block length including overlaps")
134
135 /* advanded option only */
136 #define ENC_MCBLK_YBLEN "mc-blk-yblen"
137 #define ENC_MCBLK_YBLEN_TEXT N_("yblen")
138 #define ENC_MCBLK_YBLEN_LONGTEXT N_("Total vertical block length including overlaps")
139
140 #define ENC_MVPREC "mv-prec"
141 #define ENC_MVPREC_TEXT N_("Motion vector precision")
142 #define ENC_MVPREC_LONGTEXT N_("Motion vector precision in pels.")
143 static const char *const enc_mvprec_list[] =
144   { "1", "1/2", "1/4", "1/8" };
145
146 #define ENC_ME_SIMPLESEARCH "me-simple-search"
147 #define ENC_ME_SIMPLESEARCH_TEXT N_("Simple ME search area x:y")
148 #define ENC_ME_SIMPLESEARCH_LONGTEXT N_("(Not recommended) Perform a simple (non hierarchical " \
149                                         "block matching motion vector search with search range " \
150                                         "of +/-x, +/-y")
151
152 #define ENC_ME_COMBINED "me-combined"
153 #define ENC_ME_COMBINED_TEXT N_("Three component motion estimation")
154 #define ENC_ME_COMBINED_LONGTEXT N_("Use chroma as part of the motion estimation process")
155
156 #define ENC_DWTINTRA "dwt-intra"
157 #define ENC_DWTINTRA_TEXT N_("Intra picture DWT filter")
158 #define ENC_DWTINTRA_LONGTEXT ENC_DWTINTRA_TEXT
159
160 #define ENC_DWTINTER "dwt-inter"
161 #define ENC_DWTINTER_TEXT N_("Inter picture DWT filter")
162 #define ENC_DWTINTER_LONGTEXT ENC_DWTINTER_TEXT
163
164 #define ENC_DWTDEPTH "dwt-depth"
165 #define ENC_DWTDEPTH_TEXT N_("Number of DWT iterations")
166 #define ENC_DWTDEPTH_LONGTEXT N_("Also known as DWT levels")
167
168 /* advanced option only */
169 #define ENC_MULTIQUANT "multi-quant"
170 #define ENC_MULTIQUANT_TEXT N_("Enable multiple quantizers")
171 #define ENC_MULTIQUANT_LONGTEXT N_("Enable multiple quantizers per subband (one per codeblock)")
172
173 /* advanced option only */
174 #define ENC_SPARTITION "spartition"
175 #define ENC_SPARTITION_TEXT N_("Enable spatial partitioning")
176 #define ENC_SPARTITION_LONGTEXT ENC_SPARTITION_TEXT
177
178 #define ENC_NOAC "noac"
179 #define ENC_NOAC_TEXT N_("Disable arithmetic coding")
180 #define ENC_NOAC_LONGTEXT N_("Use variable length codes instead, useful for very high bitrates")
181
182 /* visual modelling */
183 /* advanced option only */
184 #define ENC_CPD "cpd"
185 #define ENC_CPD_TEXT N_("cycles per degree")
186 #define ENC_CPD_LONGTEXT ENC_CPD_TEXT
187
188 static const char *const ppsz_enc_options[] = {
189     ENC_QUALITY_FACTOR, ENC_TARGETRATE, ENC_LOSSLESS, ENC_PREFILTER, ENC_PREFILTER_STRENGTH,
190     ENC_CHROMAFMT, ENC_L1SEP, ENC_L1NUM, ENC_CODINGMODE,
191     ENC_MCBLK_WIDTH, ENC_MCBLK_HEIGHT, ENC_MCBLK_OVERLAP,
192     ENC_MVPREC, ENC_ME_SIMPLESEARCH, ENC_ME_COMBINED,
193     ENC_DWTINTRA, ENC_DWTINTER, ENC_DWTDEPTH,
194     ENC_MULTIQUANT, ENC_SPARTITION, ENC_NOAC,
195     ENC_CPD,
196     NULL
197 };
198
199
200 /*****************************************************************************
201  * Module descriptor
202  *****************************************************************************/
203
204 vlc_module_begin()
205     set_category( CAT_INPUT )
206     set_subcategory( SUBCAT_INPUT_VCODEC )
207     set_description( N_("Dirac video encoder using dirac-research library") )
208     set_capability( "encoder", 100 )
209     set_callbacks( OpenEncoder, CloseEncoder )
210
211     add_float( ENC_CFG_PREFIX ENC_QUALITY_FACTOR, 5.5, NULL,
212                ENC_QUALITY_FACTOR_TEXT, ENC_QUALITY_FACTOR_LONGTEXT, false )
213     change_float_range(0., 10.);
214
215     add_integer( ENC_CFG_PREFIX ENC_TARGETRATE, -1, NULL,
216                  ENC_TARGETRATE_TEXT, ENC_TARGETRATE_LONGTEXT, false )
217     change_integer_range(-1, INT_MAX);
218
219     add_bool( ENC_CFG_PREFIX ENC_LOSSLESS, false, NULL,
220               ENC_LOSSLESS_TEXT, ENC_LOSSLESS_LONGTEXT, false )
221
222     add_string( ENC_CFG_PREFIX ENC_PREFILTER, "diaglp", NULL,
223                 ENC_PREFILTER_TEXT, ENC_PREFILTER_LONGTEXT, false )
224     change_string_list( enc_prefilter_list, enc_prefilter_list_text, 0 );
225
226     add_integer( ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH, 1, NULL,
227                  ENC_PREFILTER_STRENGTH_TEXT, ENC_PREFILTER_STRENGTH_LONGTEXT, false )
228     change_integer_range(0, 10);
229
230     add_string( ENC_CFG_PREFIX ENC_CHROMAFMT, "420", NULL,
231                 ENC_CHROMAFMT_TEXT, ENC_CHROMAFMT_LONGTEXT, false )
232     change_string_list( enc_chromafmt_list, enc_chromafmt_list_text, 0 );
233
234     add_integer( ENC_CFG_PREFIX ENC_L1SEP, -1, NULL,
235                  ENC_L1SEP_TEXT, ENC_L1SEP_LONGTEXT, false )
236     change_integer_range(-1, INT_MAX);
237
238     add_integer( ENC_CFG_PREFIX ENC_L1NUM, -1, NULL,
239                  ENC_L1NUM_TEXT, ENC_L1NUM_LONGTEXT, false )
240     change_integer_range(-1, INT_MAX);
241
242     add_string( ENC_CFG_PREFIX ENC_CODINGMODE, "auto", NULL,
243                 ENC_CODINGMODE_TEXT, ENC_CODINGMODE_LONGTEXT, false )
244     change_string_list( enc_codingmode_list, enc_codingmode_list_text, 0 );
245
246     add_string( ENC_CFG_PREFIX ENC_MVPREC, "1/2", NULL,
247                 ENC_MVPREC_TEXT, ENC_MVPREC_LONGTEXT, false )
248     change_string_list( enc_mvprec_list, enc_mvprec_list, 0 );
249
250     add_integer( ENC_CFG_PREFIX ENC_MCBLK_WIDTH, -1, NULL,
251                  ENC_MCBLK_WIDTH_TEXT, ENC_MCBLK_WIDTH_LONGTEXT, false )
252     add_deprecated_alias( ENC_CFG_PREFIX ENC_MCBLK_XBLEN );
253     change_integer_range(-1, INT_MAX);
254
255     add_integer( ENC_CFG_PREFIX ENC_MCBLK_HEIGHT, -1, NULL,
256                  ENC_MCBLK_HEIGHT, ENC_MCBLK_HEIGHT_LONGTEXT, false )
257     add_deprecated_alias( ENC_CFG_PREFIX ENC_MCBLK_YBLEN );
258     change_integer_range(-1, INT_MAX);
259
260     add_integer( ENC_CFG_PREFIX ENC_MCBLK_OVERLAP, -1, NULL,
261                  ENC_MCBLK_OVERLAP_TEXT, ENC_MCBLK_OVERLAP_LONGTEXT, false )
262     change_integer_range(-1, 100);
263
264     /* advanced option only */
265     add_integer( ENC_CFG_PREFIX ENC_MCBLK_XBLEN, -1, NULL,
266                  ENC_MCBLK_XBLEN_TEXT, ENC_MCBLK_XBLEN_LONGTEXT, true )
267     change_integer_range(-1, INT_MAX);
268     /* advanced option only */
269     add_integer( ENC_CFG_PREFIX ENC_MCBLK_YBLEN, -1, NULL,
270                  ENC_MCBLK_YBLEN_TEXT, ENC_MCBLK_YBLEN_LONGTEXT, true )
271     change_integer_range(-1, INT_MAX);
272
273     add_string( ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH, "", NULL,
274               ENC_ME_SIMPLESEARCH_TEXT, ENC_ME_SIMPLESEARCH_LONGTEXT, false )
275
276 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
277     add_bool( ENC_CFG_PREFIX ENC_ME_COMBINED, true, NULL,
278               ENC_ME_COMBINED_TEXT, ENC_ME_COMBINED_LONGTEXT, false )
279 #endif
280
281     add_integer( ENC_CFG_PREFIX ENC_DWTINTRA, -1, NULL,
282                  ENC_DWTINTRA_TEXT, ENC_DWTINTRA_LONGTEXT, false )
283     change_integer_range(-1, 6);
284
285     add_integer( ENC_CFG_PREFIX ENC_DWTINTER, -1, NULL,
286                  ENC_DWTINTER_TEXT, ENC_DWTINTER_LONGTEXT, false )
287     change_integer_range(-1, 6);
288
289     add_integer( ENC_CFG_PREFIX ENC_DWTDEPTH, -1, NULL,
290                  ENC_DWTDEPTH_TEXT, ENC_DWTDEPTH_LONGTEXT, false )
291     change_integer_range(-1, 4);
292
293     /* advanced option only */
294     /* NB, unforunately vlc doesn't have a concept of 'dont care' */
295     add_integer( ENC_CFG_PREFIX ENC_MULTIQUANT, -1, NULL,
296                  ENC_MULTIQUANT_TEXT, ENC_MULTIQUANT_LONGTEXT, true )
297     change_integer_range(-1, 1);
298
299     /* advanced option only */
300     /* NB, unforunately vlc doesn't have a concept of 'dont care' */
301     add_integer( ENC_CFG_PREFIX ENC_SPARTITION, -1, NULL,
302                  ENC_SPARTITION_TEXT, ENC_SPARTITION_LONGTEXT, true )
303     change_integer_range(-1, 1);
304
305     add_bool( ENC_CFG_PREFIX ENC_NOAC, false, NULL,
306               ENC_NOAC_TEXT, ENC_NOAC_LONGTEXT, false )
307
308     /* advanced option only */
309     add_float( ENC_CFG_PREFIX ENC_CPD, -1, NULL,
310                ENC_CPD_TEXT, ENC_CPD_LONGTEXT, true )
311     change_integer_range(-1, INT_MAX);
312 vlc_module_end()
313
314 /*****************************************************************************
315  * picture_pts_t : store pts alongside picture number, not carried through
316  * encoder
317  *****************************************************************************/
318 struct picture_pts_t
319 {
320    bool b_empty;      /* entry is invalid */
321    uint32_t u_pnum;  /* dirac picture number */
322    mtime_t i_pts;    /* associated pts */
323 };
324
325 /*****************************************************************************
326  * encoder_sys_t : dirac encoder descriptor
327  *****************************************************************************/
328 #define PTS_TLB_SIZE 256
329 struct encoder_sys_t
330 {
331     dirac_encoder_t *p_dirac;
332     dirac_encoder_context_t ctx;
333     bool b_auto_field_coding;
334
335     uint8_t *p_buffer_in;
336     int i_buffer_in;
337     uint32_t i_input_picnum;
338     block_fifo_t *p_dts_fifo;
339
340     int i_buffer_out;
341     uint8_t *p_buffer_out;
342     block_t *p_chain;
343
344     struct picture_pts_t pts_tlb[PTS_TLB_SIZE];
345     mtime_t i_pts_offset;
346     mtime_t i_field_time;
347 };
348
349 static struct
350 {
351     unsigned int i_height;
352     int i_approx_fps;
353     VideoFormat i_vf;
354 } dirac_format_guess[] = {
355     /* Important: Keep this list ordered in ascending picture height */
356     {1, 0, VIDEO_FORMAT_CUSTOM},
357     {120, 15, VIDEO_FORMAT_QSIF525},
358     {144, 12, VIDEO_FORMAT_QCIF},
359     {240, 15, VIDEO_FORMAT_SIF525},
360     {288, 12, VIDEO_FORMAT_CIF},
361     {480, 30, VIDEO_FORMAT_SD_480I60},
362     {480, 15, VIDEO_FORMAT_4SIF525},
363     {576, 12, VIDEO_FORMAT_4CIF},
364     {576, 25, VIDEO_FORMAT_SD_576I50},
365     {720, 50, VIDEO_FORMAT_HD_720P50},
366     {720, 60, VIDEO_FORMAT_HD_720P60},
367     {1080, 24, VIDEO_FORMAT_DIGI_CINEMA_2K24},
368     {1080, 25, VIDEO_FORMAT_HD_1080I50},
369     {1080, 30, VIDEO_FORMAT_HD_1080I60},
370     {1080, 50, VIDEO_FORMAT_HD_1080P50},
371     {1080, 60, VIDEO_FORMAT_HD_1080P60},
372     {2160, 24, VIDEO_FORMAT_DIGI_CINEMA_4K24},
373     {2160, 50, VIDEO_FORMAT_UHDTV_4K50},
374     {2160, 60, VIDEO_FORMAT_UHDTV_4K60},
375     {3840, 50, VIDEO_FORMAT_UHDTV_8K50},
376     {3840, 60, VIDEO_FORMAT_UHDTV_8K60},
377     {0, 0, 0},
378 };
379
380 /*****************************************************************************
381  * ResetPTStlb: Purge all entries in @p_dec@'s PTS-tlb
382  *****************************************************************************/
383 static void ResetPTStlb( encoder_t *p_enc )
384 {
385     encoder_sys_t *p_sys = p_enc->p_sys;
386     for( int i=0; i<PTS_TLB_SIZE; i++)
387     {
388         p_sys->pts_tlb[i].b_empty = true;
389     }
390 }
391
392 /*****************************************************************************
393  * StorePicturePTS: Store the PTS value for a particular picture number
394  *****************************************************************************/
395 static void StorePicturePTS( encoder_t *p_enc, uint32_t u_pnum, mtime_t i_pts )
396 {
397     encoder_sys_t *p_sys = p_enc->p_sys;
398
399     for( int i=0; i<PTS_TLB_SIZE; i++ )
400     {
401         if( p_sys->pts_tlb[i].b_empty )
402         {
403             p_sys->pts_tlb[i].u_pnum = u_pnum;
404             p_sys->pts_tlb[i].i_pts = i_pts;
405             p_sys->pts_tlb[i].b_empty = false;
406
407             return;
408         }
409     }
410
411     msg_Err( p_enc, "Could not store PTS %"PRId64" for frame %u", i_pts, u_pnum );
412 }
413
414 /*****************************************************************************
415  * GetPicturePTS: Retrieve the PTS value for a particular picture number
416  *****************************************************************************/
417 static mtime_t GetPicturePTS( encoder_t *p_enc, uint32_t u_pnum )
418 {
419     encoder_sys_t *p_sys = p_enc->p_sys;
420
421     for( int i=0; i<PTS_TLB_SIZE; i++ )
422     {
423         if( !p_sys->pts_tlb[i].b_empty &&
424             p_sys->pts_tlb[i].u_pnum == u_pnum )
425         {
426              p_sys->pts_tlb[i].b_empty = true;
427              return p_sys->pts_tlb[i].i_pts;
428         }
429     }
430
431     msg_Err( p_enc, "Could not retrieve PTS for picture %u", u_pnum );
432     return 0;
433 }
434
435 /*****************************************************************************
436  * OpenEncoder: probe the encoder and return score
437  *****************************************************************************/
438 static int OpenEncoder( vlc_object_t *p_this )
439 {
440     encoder_t *p_enc = (encoder_t *)p_this;
441     encoder_sys_t *p_sys = p_enc->p_sys;
442     int i_tmp;
443     float f_tmp;
444     char *psz_tmp;
445
446     if( p_enc->fmt_out.i_codec != VLC_FOURCC('d','r','a','c') &&
447         !p_enc->b_force )
448     {
449         return VLC_EGENERIC;
450     }
451
452     if( !p_enc->fmt_in.video.i_frame_rate || !p_enc->fmt_in.video.i_frame_rate_base ||
453         !p_enc->fmt_in.video.i_height || !p_enc->fmt_in.video.i_width )
454     {
455         msg_Err( p_enc, "Framerate and picture dimensions must be non-zero" );
456         return VLC_EGENERIC;
457     }
458
459     /* Allocate the memory needed to store the decoder's structure */
460     if( ( p_sys = calloc( 1, sizeof(*p_sys) ) ) == NULL )
461         return VLC_ENOMEM;
462
463     p_enc->p_sys = p_sys;
464     p_enc->pf_encode_video = Encode;
465     p_enc->fmt_out.i_codec = VLC_FOURCC('d','r','a','c');
466     p_enc->fmt_out.i_cat = VIDEO_ES;
467
468     if( ( p_sys->p_dts_fifo = block_FifoNew() ) == NULL )
469     {
470         CloseEncoder( p_this );
471         return VLC_ENOMEM;
472     }
473
474     ResetPTStlb( p_enc );
475
476     /* guess the video format based upon number of lines and picture height */
477     int i = 0;
478     VideoFormat guessed_video_fmt = VIDEO_FORMAT_CUSTOM;
479     /* Pick the dirac_video_format in this order of preference:
480      *  1. an exact match in frame height and an approximate fps match
481      *  2. the previous preset with a smaller number of lines.
482      */
483     do
484     {
485         if( dirac_format_guess[i].i_height > p_enc->fmt_in.video.i_height )
486         {
487             guessed_video_fmt = dirac_format_guess[i-1].i_vf;
488             break;
489         }
490         if( dirac_format_guess[i].i_height != p_enc->fmt_in.video.i_height )
491             continue;
492         int src_fps = p_enc->fmt_in.video.i_frame_rate / p_enc->fmt_in.video.i_frame_rate_base;
493         int delta_fps = abs( dirac_format_guess[i].i_approx_fps - src_fps );
494         if( delta_fps > 2 )
495             continue;
496
497         guessed_video_fmt = dirac_format_guess[i].i_vf;
498         break;
499     } while( dirac_format_guess[++i].i_height );
500
501     dirac_encoder_context_init( &p_sys->ctx, guessed_video_fmt );
502
503     /* constants set from the input video format */
504     p_sys->ctx.src_params.width = p_enc->fmt_in.video.i_width;
505     p_sys->ctx.src_params.height = p_enc->fmt_in.video.i_height;
506     p_sys->ctx.src_params.frame_rate.numerator = p_enc->fmt_in.video.i_frame_rate;
507     p_sys->ctx.src_params.frame_rate.denominator = p_enc->fmt_in.video.i_frame_rate_base;
508     unsigned u_asr_num, u_asr_den;
509     vlc_ureduce( &u_asr_num, &u_asr_den,
510                  p_enc->fmt_in.video.i_height * p_enc->fmt_in.video.i_aspect,
511                  p_enc->fmt_in.video.i_width * VOUT_ASPECT_FACTOR,
512                  0 );
513     p_sys->ctx.src_params.pix_asr.numerator = u_asr_num;
514     p_sys->ctx.src_params.pix_asr.denominator = u_asr_den;
515
516     config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
517
518     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CHROMAFMT );
519     if( !psz_tmp )
520         goto error;
521     else if( !strcmp( psz_tmp, "420" ) ) {
522         p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
523         p_enc->fmt_in.video.i_bits_per_pixel = 12;
524         p_sys->ctx.src_params.chroma = format420;
525         p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 3 / 2;
526     }
527     else if( !strcmp( psz_tmp, "422" ) ) {
528         p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','2');
529         p_enc->fmt_in.video.i_bits_per_pixel = 16;
530         p_sys->ctx.src_params.chroma = format422;
531         p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 2;
532     }
533     else if( !strcmp( psz_tmp, "444" ) ) {
534         p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','4','4');
535         p_enc->fmt_in.video.i_bits_per_pixel = 24;
536         p_sys->ctx.src_params.chroma = format444;
537         p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 3;
538     }
539     else {
540         msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
541         free( psz_tmp );
542         goto error;
543     }
544     free( psz_tmp );
545
546     p_sys->ctx.enc_params.qf = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_QUALITY_FACTOR );
547
548     /* use bitrate from sout-transcode-vb in kbps */
549     p_sys->ctx.enc_params.trate = p_enc->fmt_out.i_bitrate / 1000;
550     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_TARGETRATE );
551     if( i_tmp > -1 )
552         p_sys->ctx.enc_params.trate = i_tmp;
553     p_enc->fmt_out.i_bitrate = p_sys->ctx.enc_params.trate * 1000;
554
555     p_sys->ctx.enc_params.lossless = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_LOSSLESS );
556
557     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_PREFILTER );
558     if( !psz_tmp )
559         goto error;
560     else if( !strcmp( psz_tmp, "none" ) ) {
561         p_sys->ctx.enc_params.prefilter = NO_PF;
562     }
563     else if( !strcmp( psz_tmp, "cwm" ) ) {
564         p_sys->ctx.enc_params.prefilter = CWM;
565     }
566     else if( !strcmp( psz_tmp, "rectlp" ) ) {
567         p_sys->ctx.enc_params.prefilter = RECTLP;
568     }
569     else if( !strcmp( psz_tmp, "diaglp" ) ) {
570         p_sys->ctx.enc_params.prefilter = DIAGLP;
571     }
572     else {
573         msg_Err( p_enc, "Invalid prefilter: %s", psz_tmp );
574         free( psz_tmp );
575         goto error;
576     }
577     free( psz_tmp );
578
579     p_sys->ctx.enc_params.prefilter_strength =
580         var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH );
581
582     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1SEP );
583     if( i_tmp > -1 )
584         p_sys->ctx.enc_params.L1_sep = i_tmp;
585
586     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1NUM );
587     if( i_tmp > -1 )
588         p_sys->ctx.enc_params.num_L1 = i_tmp;
589
590     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CODINGMODE );
591     if( !psz_tmp )
592         goto error;
593     else if( !strcmp( psz_tmp, "auto" ) ) {
594         p_sys->b_auto_field_coding = true;
595     }
596     else if( !strcmp( psz_tmp, "progressive" ) ) {
597         p_sys->b_auto_field_coding = false;
598         p_sys->ctx.enc_params.picture_coding_mode = 0;
599     }
600     else if( !strcmp( psz_tmp, "field" ) ) {
601         p_sys->b_auto_field_coding = false;
602         p_sys->ctx.enc_params.picture_coding_mode = 1;
603     }
604     else {
605         msg_Err( p_enc, "Invalid codingmode: %s", psz_tmp );
606         free( psz_tmp );
607         goto error;
608     }
609     free( psz_tmp );
610
611     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MVPREC );
612     if( !psz_tmp )
613         goto error;
614     else if( !strcmp( psz_tmp, "1" ) ) {
615         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_PIXEL;
616     }
617     else if( !strcmp( psz_tmp, "1/2" ) ) {
618         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_HALF_PIXEL;
619     }
620     else if( !strcmp( psz_tmp, "1/4" ) ) {
621         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_QUARTER_PIXEL;
622     }
623     else if( !strcmp( psz_tmp, "1/8" ) ) {
624         p_sys->ctx.enc_params.mv_precision = MV_PRECISION_EIGHTH_PIXEL;
625     }
626     else {
627         msg_Err( p_enc, "Invalid mv-prec: %s", psz_tmp );
628         free( psz_tmp );
629         goto error;
630     }
631     free( psz_tmp );
632
633     /*
634      * {x,y}b{len,sep} must be multiples of 4
635      */
636     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_WIDTH );
637     if( i_tmp > -1 )
638         p_sys->ctx.enc_params.xbsep = i_tmp / 4 * 4;
639
640     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_HEIGHT );
641     if( i_tmp > -1 )
642         p_sys->ctx.enc_params.ybsep = i_tmp / 4 * 4;
643
644     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP );
645     if( i_tmp > -1 ) {
646         p_sys->ctx.enc_params.xblen = p_sys->ctx.enc_params.xbsep * (100 + i_tmp) / 400 * 4;
647         p_sys->ctx.enc_params.yblen = p_sys->ctx.enc_params.ybsep * (100 + i_tmp) / 400 * 4;
648     }
649
650     /*
651      * {x,y}blen >= {x,y}bsep
652      * {x,y}blen <= 2* {x,y}bsep
653      */
654     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_XBLEN );
655     if( i_tmp > -1 ) {
656         int xblen = __MAX( i_tmp, p_sys->ctx.enc_params.xbsep );
657         xblen = __MIN( xblen, 2 * p_sys->ctx.enc_params.xbsep );
658         p_sys->ctx.enc_params.xblen = xblen;
659     }
660
661     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_YBLEN );
662     if( i_tmp > -1 ) {
663         int yblen = __MAX( i_tmp, p_sys->ctx.enc_params.ybsep );
664         yblen = __MIN( yblen, 2 * p_sys->ctx.enc_params.ybsep );
665         p_sys->ctx.enc_params.yblen = yblen;
666     }
667
668     psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH );
669     if( !psz_tmp )
670         goto error;
671     if( *psz_tmp != '\0' ) {
672         /* of the form [0-9]+:[0-9]+ */
673         char *psz_start = psz_tmp;
674         char *psz_end = psz_tmp;
675         p_sys->ctx.enc_params.x_range_me = strtol(psz_start, &psz_end, 10);
676         if( *psz_end != ':'  || psz_end == psz_start ) {
677             msg_Err( p_enc, "Invalid simple search range: %s", psz_tmp );
678             free( psz_tmp );
679             goto error;
680         }
681         psz_start = ++psz_end;
682         p_sys->ctx.enc_params.y_range_me = strtol(psz_start, &psz_end, 10);
683         if( *psz_end != '\0'  || psz_end == psz_start ) {
684             msg_Err( p_enc, "Invalid simple search range: %s", psz_tmp );
685             free( psz_tmp );
686             goto error;
687         }
688         if( p_sys->ctx.enc_params.x_range_me < 0 ||
689             p_sys->ctx.enc_params.y_range_me < 0 )
690         {
691             msg_Err( p_enc, "Invalid negative simple search range: %s", psz_tmp );
692             free( psz_tmp );
693             goto error;
694         }
695         p_sys->ctx.enc_params.full_search = 1;
696     }
697     free( psz_tmp );
698
699 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1)
700     p_sys->ctx.enc_params.combined_me = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_ME_COMBINED );
701 #endif
702
703     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTRA );
704     if( i_tmp > -1 )
705         p_sys->ctx.enc_params.intra_wlt_filter = i_tmp;
706
707     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTER );
708     if( i_tmp > -1 )
709         p_sys->ctx.enc_params.inter_wlt_filter = i_tmp;
710
711     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTDEPTH );
712     if( i_tmp > -1 )
713         p_sys->ctx.enc_params.wlt_depth = i_tmp;
714
715     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MULTIQUANT );
716     if( i_tmp > -1 )
717         p_sys->ctx.enc_params.multi_quants = i_tmp;
718
719     i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_SPARTITION );
720     if( i_tmp > -1 )
721         p_sys->ctx.enc_params.spatial_partition = i_tmp;
722
723     p_sys->ctx.enc_params.using_ac = !var_GetBool( p_enc, ENC_CFG_PREFIX ENC_NOAC );
724
725     f_tmp = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_CPD );
726     if( f_tmp > -1 )
727         p_sys->ctx.enc_params.cpd = f_tmp;
728
729     /* Allocate the buffer for inputing frames into the encoder */
730     if( ( p_sys->p_buffer_in = malloc( p_sys->i_buffer_in ) ) == NULL )
731     {
732         CloseEncoder( p_this );
733         return VLC_ENOMEM;
734     }
735
736     /* Set up output buffer */
737     /* Unfortunately it isn't possible to determine if the buffer
738      * is too small (and then reallocate it) */
739     p_sys->i_buffer_out = 4096 + p_sys->i_buffer_in;
740     if( ( p_sys->p_buffer_out = malloc( p_sys->i_buffer_out ) ) == NULL )
741     {
742         CloseEncoder( p_this );
743         return VLC_ENOMEM;
744     }
745
746     return VLC_SUCCESS;
747 error:
748     CloseEncoder( p_this );
749     return VLC_EGENERIC;
750 }
751
752 /* Attempt to find dirac picture number in an encapsulation unit */
753 static int ReadDiracPictureNumber( uint32_t *p_picnum, block_t *p_block )
754 {
755     uint32_t u_pos = 4;
756     /* protect against falling off the edge */
757     while( u_pos + 13 < p_block->i_buffer )
758     {
759         /* find the picture startcode */
760         if( p_block->p_buffer[u_pos] & 0x08 )
761         {
762             *p_picnum = GetDWBE( p_block->p_buffer + u_pos + 9 );
763             return 1;
764         }
765         /* skip to the next dirac data unit */
766         uint32_t u_npo = GetDWBE( p_block->p_buffer + u_pos + 1 );
767         assert( u_npo <= UINT32_MAX - u_pos );
768         if( u_npo == 0 )
769             u_npo = 13;
770         u_pos += u_npo;
771     }
772     return 0;
773 }
774
775 /****************************************************************************
776  * Encode: the whole thing
777  ****************************************************************************
778  * This function spits out encapsulation units.
779  ****************************************************************************/
780 static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
781 {
782     encoder_sys_t *p_sys = p_enc->p_sys;
783     block_t *p_block, *p_output_chain = NULL;
784     int i_plane, i_line, i_width, i_src_stride;
785     uint8_t *p_dst;
786
787     /* we only know if the sequence is interlaced when the first
788      * picture arrives, so final setup is done here */
789     /* XXX todo, detect change of interlace */
790     p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first;
791     p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive;
792
793     if( p_sys->b_auto_field_coding )
794         p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive;
795
796     if( !p_sys->p_dirac )
797     {
798         date_t date;
799         /* Initialise the encoder with the encoder context */
800         p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 );
801         if( !p_sys->p_dirac )
802         {
803             msg_Err( p_enc, "Failed to initialize dirac encoder" );
804             p_enc->b_error = 1;
805             return NULL;
806         }
807         date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base );
808 #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
809         int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac );
810         i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1;
811         date_Increment( &date, i_delayinpics );
812 #else
813         date_Increment( &date, 1 );
814 #endif
815         p_sys->i_pts_offset = date_Get( &date );
816
817         /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
818          * for each frame input. Calculate time between fields for offsetting
819          * the second field later. */
820         if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
821         {
822             date_Set( &date, 0 );
823             date_Increment( &date, 1 );
824             p_sys->i_field_time = date_Get( &date ) / 2;
825         }
826     }
827
828     /* Copy input picture into encoder input buffer (stride by stride) */
829     /* Would be lovely to just pass the picture in, but there is noway for the
830      * library to free it */
831     p_dst = p_sys->p_buffer_in;
832     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
833     {
834         uint8_t *p_src = p_pic->p[i_plane].p_pixels;
835         i_width = p_pic->p[i_plane].i_visible_pitch;
836         i_src_stride = p_pic->p[i_plane].i_pitch;
837
838         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
839         {
840             vlc_memcpy( p_dst, p_src, i_width );
841             p_dst += i_width;
842             p_src += i_src_stride;
843         }
844     }
845
846     /* Load one frame of data into encoder */
847     if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in,
848                             p_sys->i_buffer_in ) < 0 )
849     {
850         msg_Dbg( p_enc, "dirac_encoder_load() error" );
851         return NULL;
852     }
853
854     /* store pts in a lookaside buffer, so that the same pts may
855      * be used for the picture in coded order */
856     StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date );
857     p_sys->i_input_picnum++;
858
859     /* store dts in a queue, so that they appear in order in
860      * coded order */
861     p_block = block_New( p_enc, 1 );
862     if( !p_block )
863     {
864         p_enc->b_error = 1;
865         return NULL;
866     }
867     p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
868     block_FifoPut( p_sys->p_dts_fifo, p_block );
869     p_block = NULL;
870
871     /* for field coding mode, insert an extra value into both the
872      * pts lookaside buffer and dts queue, offset to correspond
873      * to a one field delay. */
874     if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
875     {
876         StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time );
877         p_sys->i_input_picnum++;
878
879         p_block = block_New( p_enc, 1 );
880         if( !p_block )
881         {
882             p_enc->b_error = 1;
883             return NULL;
884         }
885         p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time;
886         block_FifoPut( p_sys->p_dts_fifo, p_block );
887         p_block = NULL;
888     }
889
890     dirac_encoder_state_t state;
891     /* Retrieve encoded frames from encoder */
892     do
893     {
894         p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out;
895         p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out;
896         state = dirac_encoder_output( p_sys->p_dirac );
897         switch( state )
898         {
899         case ENC_STATE_AVAIL: {
900             uint32_t pic_num;
901
902             /* extract data from encoder temporary buffer. */
903             p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
904             if( !p_block )
905             {
906                 p_enc->b_error = 1;
907                 return NULL;
908             }
909             memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer,
910                     p_sys->p_dirac->enc_buf.size );
911
912             /* if some flags were set for a previous block, prevent
913              * them from getting lost */
914             if( p_sys->p_chain )
915                 p_block->i_flags |= p_sys->p_chain->i_flags;
916
917             /* store all extracted blocks in a chain and gather up when an
918              * entire encapsulation unit is avaliable (ends with a picture) */
919             block_ChainAppend( &p_sys->p_chain, p_block );
920
921             /* Presence of a Sequence header indicates a seek point */
922             if( 0 == p_block->p_buffer[4] )
923             {
924                 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
925
926                 if( !p_enc->fmt_out.p_extra ) {
927                     const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
928                     uint32_t len = GetDWBE( p_block->p_buffer + 5 );
929                     /* if it hasn't been done so far, stash a copy of the
930                      * sequence header for muxers such as ogg */
931                     /* The OggDirac spec advises that a Dirac EOS DataUnit
932                      * is appended to the sequence header to allow guard
933                      * against poor streaming servers */
934                     /* XXX, should this be done using the packetizer ? */
935                     p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) );
936                     if( !p_enc->fmt_out.p_extra )
937                     {
938                         p_enc->b_error = 1;
939                         return NULL;
940                     }
941                     memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len);
942                     memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) );
943                     SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len );
944                     p_enc->fmt_out.i_extra = len + sizeof(eos);
945                 }
946             }
947
948             if( ReadDiracPictureNumber( &pic_num, p_block ) )
949             {
950                 /* Finding a picture terminates an ecapsulation unit, gather
951                  * all data and output; use the next dts value queued up
952                  * and find correct pts in the tlb */
953                 p_block = block_FifoGet( p_sys->p_dts_fifo );
954                 p_sys->p_chain->i_dts = p_block->i_dts;
955                 p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num );
956                 block_Release( p_block );
957                 block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) );
958                 p_sys->p_chain = NULL;
959             } else {
960                 p_block = NULL;
961             }
962             break;
963             }
964
965         case ENC_STATE_BUFFER:
966             break;
967         case ENC_STATE_INVALID:
968         default:
969             break;
970         }
971     } while( state == ENC_STATE_AVAIL );
972
973     return p_output_chain;
974 }
975
976 /*****************************************************************************
977  * CloseEncoder: dirac encoder destruction
978  *****************************************************************************/
979 static void CloseEncoder( vlc_object_t *p_this )
980 {
981     encoder_t *p_enc = (encoder_t *)p_this;
982     encoder_sys_t *p_sys = p_enc->p_sys;
983
984     /* Free the encoder resources */
985     if( p_sys->p_dirac )
986         dirac_encoder_close( p_sys->p_dirac );
987
988     free( p_sys->p_buffer_in );
989     free( p_sys->p_buffer_out );
990
991     if( p_sys->p_dts_fifo )
992         block_FifoRelease( p_sys->p_dts_fifo );
993     block_ChainRelease( p_sys->p_chain );
994
995     free( p_sys );
996 }