dirac.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:37k
源码类别:

midi

开发平台:

Unix_Linux

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