[vlc-devel] [PATCH 1/2] daala: add encoder
Tristan Matthews
le.businessman at gmail.com
Sun Sep 21 15:21:42 CEST 2014
On Sun, Sep 21, 2014 at 7:50 AM, Rafaël Carré <funman at videolan.org> wrote:
> On 21 septembre 2014 12:00:48 GMT+01:00, Tristan Matthews <le.businessman at gmail.com> wrote:
>>Fixed an issue with the keyint option.
>>
>>---
>> configure.ac | 2 +-
>>modules/codec/daala.c | 211
>>++++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 212 insertions(+), 1 deletion(-)
>>
>>diff --git a/configure.ac b/configure.ac
>>index 2b2a815..eff4995 100644
>>--- a/configure.ac
>>+++ b/configure.ac
>>@@ -2745,7 +2745,7 @@ PKG_ENABLE_MODULES_VLC([THEORA], [], [ogg
>>theoradec >= 1.0 theoraenc], [experime
>> dnl
>> dnl Daala decoder plugin
>> dnl
>>-PKG_ENABLE_MODULES_VLC([DAALA], [], [ogg daaladec], [experimental
>>daala codec], [disabled])
>>+PKG_ENABLE_MODULES_VLC([DAALA], [], [ogg daaladec daalaenc],
>>[experimental daala codec], [disabled])
>>
>> dnl
>> dnl schroedinger decoder plugin (for dirac format video)
>>diff --git a/modules/codec/daala.c b/modules/codec/daala.c
>>index 6a7851d..815eaa1 100644
>>--- a/modules/codec/daala.c
>>+++ b/modules/codec/daala.c
>>@@ -38,6 +38,9 @@
>>
>> #include <daala/codec.h>
>> #include <daala/daaladec.h>
>>+#ifdef ENABLE_SOUT
>>+#include <daala/daalaenc.h>
>>+#endif
>>
>> #include <limits.h>
>>
>>@@ -88,6 +91,22 @@ static picture_t *DecodePacket( decoder_t *,
>>ogg_packet * );
>> static void ParseDaalaComments( decoder_t * );
>> static void daala_CopyPicture( picture_t *, od_img * );
>>
>>+#ifdef ENABLE_SOUT
>>+static int OpenEncoder( vlc_object_t *p_this );
>>+static void CloseEncoder( vlc_object_t *p_this );
>>+static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
>>+#endif
>>+
>>+/*****************************************************************************
>>+ * Module descriptor
>>+
>>*****************************************************************************/
>>+#define ENC_QUALITY_TEXT N_("Encoding quality")
>>+#define ENC_QUALITY_LONGTEXT N_( \
>>+ "Enforce a quality between 0 (lossless) and 511 (worst)." )
>>+#define ENC_KEYINT_TEXT N_("Keyframe interval")
>>+#define ENC_KEYINT_LONGTEXT N_( \
>>+ "Enforce a keyframe interval between 1 and 1000." )
>>+
>> vlc_module_begin ()
>> set_category( CAT_INPUT )
>> set_subcategory( SUBCAT_INPUT_VCODEC )
>>@@ -102,8 +121,25 @@ vlc_module_begin ()
>> set_callbacks( OpenPacketizer, CloseDecoder )
>> add_shortcut( "daala" )
>>
>>+#ifdef ENABLE_SOUT
>>+ add_submodule ()
>>+ set_description( N_("Daala video encoder") )
>>+ set_capability( "encoder", 150 )
>>+ set_callbacks( OpenEncoder, CloseEncoder )
>>+ add_shortcut( "daala" )
>>+
>>+# define ENC_CFG_PREFIX "sout-daala-"
>>+ add_integer( ENC_CFG_PREFIX "quality", 30, ENC_QUALITY_TEXT,
>>+ ENC_QUALITY_LONGTEXT, false )
>
> I would use add_integer_with_range
Ah yes.
>
>>+ add_integer( ENC_CFG_PREFIX "keyint", 256, ENC_KEYINT_TEXT,
>>+ ENC_KEYINT_LONGTEXT, false )
>>+#endif
>> vlc_module_end ()
>>
>>+static const char *const ppsz_enc_options[] = {
>>+ "quality", "keyint", NULL
>>+};
>>+
>>/*****************************************************************************
>> * OpenDecoder: probe the decoder and return score
>>*****************************************************************************/
>>@@ -506,3 +542,178 @@ static void daala_CopyPicture( picture_t *p_pic,
>> }
>> }
>> }
>>+
>>+#ifdef ENABLE_SOUT
>>+struct encoder_sys_t
>>+{
>>+ daala_info di; /* daala bitstream
>>settings */
>>+ daala_comment dc; /* daala comment header */
>>+ daala_enc_ctx *dcx; /* daala context */
>>+};
>>+
>>+static int OpenEncoder( vlc_object_t *p_this )
>>+{
>>+ encoder_t *p_enc = (encoder_t *)p_this;
>>+ encoder_sys_t *p_sys;
>>+ int i_quality;
>>+ ogg_packet header;
>>+ int status;
>>+
>>+ if( p_enc->fmt_out.i_codec != VLC_CODEC_DAALA &&
>>+ !p_enc->b_force )
>>+ {
>>+ return VLC_EGENERIC;
>>+ }
>>+
>>+ /* Allocate the memory needed to store the encoder's structure */
>>+ p_sys = malloc( sizeof( encoder_sys_t ) );
>>+ if( !p_sys )
>>+ return VLC_ENOMEM;
>>+ p_enc->p_sys = p_sys;
>>+
>>+ p_enc->pf_encode_video = Encode;
>>+ p_enc->fmt_in.i_codec = VLC_CODEC_I420;
>>+ p_enc->fmt_out.i_codec = VLC_CODEC_DAALA;
>>+
>>+ config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options,
>>p_enc->p_cfg );
>>+
>>+ i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
>>+ i_quality = VLC_CLIP(i_quality, 0, 511);
>>+
>>+ daala_info_init( &p_sys->di );
>>+
>>+ p_sys->di.pic_width = p_enc->fmt_in.video.i_visible_width;
>>+ p_sys->di.pic_height = p_enc->fmt_in.video.i_visible_height;
>>+
>>+ /* 420 */
>>+ p_sys->di.nplanes = 3;
>>+ for (int i = 0; i < p_sys->di.nplanes; i++)
>>+ {
>>+ p_sys->di.plane_info[i].ydec =
>>+ p_sys->di.plane_info[i].xdec = i > 0;
>>+ }
>>+ p_sys->di.frame_duration = 1;
>>+
>>+ if( !p_enc->fmt_in.video.i_frame_rate ||
>>+ !p_enc->fmt_in.video.i_frame_rate_base )
>>+ {
>>+ p_sys->di.timebase_numerator = 25;
>>+ p_sys->di.timebase_denominator = 1;
>>+ }
>>+ else
>>+ {
>>+ p_sys->di.timebase_numerator =
>>p_enc->fmt_in.video.i_frame_rate;
>>+ p_sys->di.timebase_denominator =
>>p_enc->fmt_in.video.i_frame_rate_base;
>>+ }
>>+
>>+ if( p_enc->fmt_in.video.i_sar_num > 0 &&
>>p_enc->fmt_in.video.i_sar_den > 0 )
>>+ {
>>+ unsigned i_dst_num, i_dst_den;
>>+ vlc_ureduce( &i_dst_num, &i_dst_den,
>>+ p_enc->fmt_in.video.i_sar_num,
>>+ p_enc->fmt_in.video.i_sar_den, 0 );
>>+ p_sys->di.pixel_aspect_numerator = i_dst_num;
>>+ p_sys->di.pixel_aspect_denominator = i_dst_den;
>>+ }
>>+ else
>>+ {
>>+ p_sys->di.pixel_aspect_numerator = 4;
>>+ p_sys->di.pixel_aspect_denominator = 3;
>>+ }
>>+
>>+ const int i_rate = var_GetInteger( p_enc, ENC_CFG_PREFIX "keyint"
>>);
>>+ p_sys->di.keyframe_rate = VLC_CLIP(i_rate, 1, 1000);
>>+
>>+ daala_enc_ctx *dcx;
>>+ p_sys->dcx = dcx = daala_encode_create( &p_sys->di );
>>+ if( !dcx )
>>+ return VLC_ENOMEM;
>
> Leaking p_sys
ok
>
>>+
>>+ daala_comment_init( &p_sys->dc );
>>+
>>+ daala_encode_ctl( dcx, OD_SET_QUANT, &i_quality, sizeof(i_quality)
>>);
>>+
>>+ /* Create and store headers */
>>+ while( ( status = daala_encode_flush_header( dcx, &p_sys->dc,
>>&header ) ) )
>>+ {
>>+ if ( status < 0 ) return VLC_EGENERIC;
>
> Leaking as well
ok
>
>>+ if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra,
>>+ &p_enc->fmt_out.p_extra, header.bytes,
>>+ header.packet ) )
>>+ {
>>+ p_enc->fmt_out.i_extra = 0;
>>+ p_enc->fmt_out.p_extra = NULL;
>>+ }
>>+ }
>>+ return VLC_SUCCESS;
>>+}
>>+
>>+static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
>>+{
>>+ encoder_sys_t *p_sys = p_enc->p_sys;
>>+ ogg_packet oggpacket;
>>+ block_t *p_block;
>>+ od_img img;
>>+
>>+ if( !p_pict ) return NULL;
>>+
>>+ const int i_width = p_sys->di.pic_width;
>>+ const int i_height = p_sys->di.pic_height;
>>+
>>+ /* Sanity check */
>>+ if( p_pict->p[0].i_pitch < i_width ||
>>+ p_pict->p[0].i_lines < i_height )
>>+ {
>>+ msg_Err( p_enc, "frame is smaller than encoding size"
>>+ "(%ix%i->%ix%i) -> dropping frame",
>>+ p_pict->p[0].i_pitch, p_pict->p[0].i_lines,
>>+ i_width, i_height );
>>+ return NULL;
>>+ }
>>+
>>+ /* Daala is a one-frame-in, one-frame-out system. Submit a frame
>>+ * for compression and pull out the packet. */
>>+
>>+ img.nplanes = p_sys->di.nplanes;
>>+ img.width = i_width;
>>+ img.height = i_height;
>>+ for( int i = 0; i < img.nplanes; i++ )
>>+ {
>>+ img.planes[i].data = p_pict->p[i].p_pixels;
>>+ img.planes[i].xdec = p_sys->di.plane_info[i].xdec;
>>+ img.planes[i].ydec = p_sys->di.plane_info[i].ydec;
>>+ img.planes[i].xstride = 1;
>>+ img.planes[i].ystride = (img.width
>>+ + (1 << img.planes[i].xdec) - 1) >> img.planes[i].xdec;
>>+ }
>>+
>>+ if( daala_encode_img_in( p_sys->dcx, &img, 0 ) < 0 )
>>+ {
>>+ msg_Warn( p_enc, "failed encoding a frame" );
>>+ return NULL;
>>+ }
>>+
>>+ daala_encode_packet_out( p_sys->dcx, 0, &oggpacket );
>>+
>>+ /* Ogg packet to block */
>>+ p_block = block_Alloc( oggpacket.bytes );
>>+ memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
>>+ p_block->i_dts = p_block->i_pts = p_pict->date;
>
> No frame reordering is going on?
No, Daala does no frame reordering currently.
>>+ if( daala_packet_iskeyframe( oggpacket.packet, oggpacket.bytes ) )
>>+ p_block->i_flags |= BLOCK_FLAG_TYPE_I;
>>+
>>+ return p_block;
>>+}
>>+
>>+static void CloseEncoder( vlc_object_t *p_this )
>>+{
>>+ encoder_t *p_enc = (encoder_t *)p_this;
>>+ encoder_sys_t *p_sys = p_enc->p_sys;
>>+
>>+ daala_info_clear(&p_sys->di);
>>+ daala_comment_clear(&p_sys->dc);
>>+ daala_encode_free(p_sys->dcx);
>>+ free( p_sys );
>>+}
>>+#endif
>
Thanks for quick review, will resend pronto.
Best,
Tristan
More information about the vlc-devel
mailing list