<div dir="ltr"><div dir="ltr">On Thu, Aug 27, 2020 at 8:47 PM Tristan Matthews <<a href="mailto:tmatth@videolan.org">tmatth@videolan.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
On Thu, Aug 27, 2020 at 10:44 AM Thomas Guillem <<a href="mailto:thomas@gllm.fr" target="_blank">thomas@gllm.fr</a>> wrote:<br>
><br>
> From: Kartik Ohri <<a href="mailto:kartikohri13@gmail.com" target="_blank">kartikohri13@gmail.com</a>><br>
><br>
> Co-Authored-By: Thomas Guillem <<a href="mailto:thomas@gllm.fr" target="_blank">thomas@gllm.fr</a>><br>
> ---<br>
>  <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a>              |   5 +<br>
>  modules/codec/Makefile.am |   8 +<br>
>  modules/codec/rav1e.c     | 303 ++++++++++++++++++++++++++++++++++++++<br>
>  3 files changed, 316 insertions(+)<br>
>  create mode 100644 modules/codec/rav1e.c<br>
><br>
> diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> index 7b40650216d..99e46699424 100644<br>
> --- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> @@ -2882,6 +2882,11 @@ dnl  AOM encoder/decoder plugin<br>
>  dnl<br>
>  PKG_ENABLE_MODULES_VLC([AOM], [], [aom], [libaom AV1 encoder and decoder (default auto)])<br>
><br>
> +dnl<br>
> +dnl  Rav1e encoder plugin<br>
> +dnl<br>
> +PKG_ENABLE_MODULES_VLC([RAV1E], [], [rav1e], [rav1e encoder module codec (default auto)])<br>
> +<br>
>  dnl<br>
>  dnl  Dav1d decoder plugin<br>
>  dnl<br>
> diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am<br>
> index 0aede611336..ec6447ddf9c 100644<br>
> --- a/modules/codec/Makefile.am<br>
> +++ b/modules/codec/Makefile.am<br>
> @@ -544,6 +544,14 @@ libaom_plugin_la_LIBADD = $(AOM_LIBS)<br>
>  EXTRA_LTLIBRARIES += <a href="http://libaom_plugin.la" rel="noreferrer" target="_blank">libaom_plugin.la</a><br>
>  codec_LTLIBRARIES += $(LTLIBaom)<br>
><br>
> +librav1e_plugin_la_SOURCES = codec/rav1e.c<br>
> +librav1e_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)<br>
> +librav1e_plugin_la_CFLAGS = $(AM_CFLAGS) $(RAV1E_CFLAGS)<br>
> +librav1e_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'<br>
> +librav1e_plugin_la_LIBADD = $(RAV1E_LIBS)<br>
> +EXTRA_LTLIBRARIES += <a href="http://librav1e_plugin.la" rel="noreferrer" target="_blank">librav1e_plugin.la</a><br>
> +codec_LTLIBRARIES += $(LTLIBrav1e)<br>
> +<br>
>  libtwolame_plugin_la_SOURCES = codec/twolame.c<br>
>  libtwolame_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DLIBTWOLAME_STATIC<br>
>  libtwolame_plugin_la_CFLAGS = $(AM_CFLAGS) $(TWOLAME_CFLAGS)<br>
> diff --git a/modules/codec/rav1e.c b/modules/codec/rav1e.c<br>
> new file mode 100644<br>
> index 00000000000..fe6098d7047<br>
> --- /dev/null<br>
> +++ b/modules/codec/rav1e.c<br>
> @@ -0,0 +1,303 @@<br>
> +/*****************************************************************************<br>
> + * rav1e.c : rav1e encoder (AV1) module<br>
> + *****************************************************************************<br>
> + * Copyright (C) 2020 VLC authors and VideoLAN<br>
> + *<br>
> + * Authors: Kartik Ohri <<a href="mailto:kartikohri13@gmail.com" target="_blank">kartikohri13@gmail.com</a>><br>
> + *          Thomas Guillem <<a href="mailto:thomas@gllm.fr" target="_blank">thomas@gllm.fr</a>><br>
> + *<br>
> + * This program is free software; you can redistribute it and/or modify it<br>
> + * under the terms of the GNU Lesser General Public License as published by<br>
> + * the Free Software Foundation; either version 2.1 of the License, or<br>
> + * (at your option) any later version.<br>
> + *<br>
> + * This program is distributed in the hope that it will be useful,<br>
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
> + * GNU Lesser General Public License for more details.<br>
> + *<br>
> + * You should have received a copy of the GNU Lesser General Public License<br>
> + * along with this program; if not, write to the Free Software Foundation,<br>
> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.<br>
> + *****************************************************************************/<br>
> +<br>
> +#ifdef HAVE_CONFIG_H<br>
> +# include "config.h"<br>
> +#endif<br>
> +<br>
> +#include <vlc_common.h><br>
> +#include <vlc_plugin.h><br>
> +#include <vlc_codec.h><br>
> +#include <rav1e/rav1e.h><br>
> +<br>
> +#define SOUT_CFG_PREFIX "sout-rav1e-"<br>
> +<br>
> +typedef struct<br>
> +{<br>
> +    struct RaContext *ra_context;<br>
> +    date_t date;<br>
> +    bool date_set;<br>
> +} encoder_sys_t;<br>
> +<br>
> +static block_t *Encode(encoder_t *enc, picture_t *p_pict)<br>
> +{<br>
> +    encoder_sys_t *sys = enc->p_sys;<br>
> +    RaContext *ctx = sys->ra_context;<br>
> +    block_t *p_out = NULL;<br>
> +<br>
> +    RaFrame *frame;<br>
> +    if (p_pict != NULL)<br>
> +    {<br>
> +        if (!sys->date_set && p_pict->date != VLC_TICK_INVALID)<br>
> +        {<br>
> +            date_Set(&sys->date, p_pict->date);<br>
> +            sys->date_set = true;<br>
> +        }<br>
> +<br>
> +        frame = rav1e_frame_new(ctx);<br>
> +        if (frame == NULL) {<br>
> +            msg_Err(enc, "Unable to create new frame\n");<br>
> +            goto error;<br>
> +        }<br>
> +<br>
> +        for (int idx = 0; idx < p_pict->i_planes; idx++)<br>
> +            rav1e_frame_fill_plane(frame, idx,<br>
> +                                   p_pict->p[idx].p_pixels,<br>
> +                                   p_pict->p[idx].i_pitch * p_pict->p[idx].i_visible_lines,<br>
> +                                   p_pict->p[idx].i_pitch,<br>
> +                                   p_pict->p[idx].i_pixel_pitch);<br>
> +    }<br>
> +    else<br>
> +        frame = NULL; /* Drain with a NULL frame */<br>
> +<br>
> +    int ret = rav1e_send_frame(ctx, frame);<br>
> +    rav1e_frame_unref(frame);<br>
> +    if (ret != 0)<br>
> +    {<br>
> +        msg_Err(enc, "rav1e_send_frame failed: %d: %s", ret,<br>
> +                rav1e_status_to_str(ret));<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +    bool again;<br>
> +    do<br>
> +    {<br>
> +        RaPacket *pkt = NULL;<br>
> +        ret = rav1e_receive_packet(ctx, &pkt);<br>
> +<br>
> +        switch (ret)<br>
> +        {<br>
> +            case RA_ENCODER_STATUS_SUCCESS:<br>
> +            {<br>
> +                block_t *p_block = block_Alloc(pkt->len);<br>
> +                if (unlikely(p_block == NULL))<br>
> +                {<br>
> +                    block_ChainRelease(p_out);<br>
> +                    p_out = NULL;<br>
> +                    break;<br>
> +                }<br>
> +<br>
> +                memcpy(p_block->p_buffer, pkt->data, pkt->len);<br>
> +                p_block->i_dts = p_block->i_pts = date_Get(&sys->date);<br>
> +<br>
> +                if (pkt->frame_type == RA_FRAME_TYPE_KEY)<br>
> +                    p_block->i_flags |= BLOCK_FLAG_TYPE_I;<br>
> +                block_ChainAppend(&p_out, p_block);<br>
> +                rav1e_packet_unref(pkt);<br>
> +            }<br>
> +            /* fall-through */<br>
> +            case RA_ENCODER_STATUS_ENCODED:<br>
> +                again = true;<br>
> +                break;<br>
> +            case RA_ENCODER_STATUS_LIMIT_REACHED:<br>
> +            case RA_ENCODER_STATUS_NEED_MORE_DATA:<br>
> +                again = false;<br>
> +                break;<br>
> +            default:<br>
> +                msg_Err(enc, "rav1e_receive_packet() failed: %d: %s", ret,<br>
> +                        rav1e_status_to_str(ret));<br>
> +                goto error;<br>
> +        }<br>
> +    } while (again);<br>
> +<br>
> +    return p_out;<br>
> +<br>
> +error:<br>
> +    free(p_out);<br>
> +    return NULL;<br>
> +}<br>
> +<br>
> +static int OpenEncoder(vlc_object_t *this)<br>
> +{<br>
> +    encoder_t *enc = (encoder_t *) this;<br>
> +    encoder_sys_t *sys;<br>
> +<br>
> +    if (enc->fmt_out.i_codec != VLC_CODEC_AV1)<br>
> +        return VLC_EGENERIC;<br>
> +<br>
> +    static const char *const ppsz_rav1e_options[] = {<br>
> +        "bitdepth", "tile-rows", "tile-columns", NULL<br>
> +    };<br>
> +<br>
> +    config_ChainParse(enc, SOUT_CFG_PREFIX, ppsz_rav1e_options, enc->p_cfg);<br>
> +<br>
> +    sys = malloc(sizeof(*sys));<br>
> +    if (sys == NULL)<br>
> +        return VLC_ENOMEM;<br>
> +<br>
> +    enc->p_sys = sys;<br>
> +<br>
> +    struct RaConfig *ra_config = rav1e_config_default();<br>
> +    if (ra_config == NULL)<br>
> +    {<br>
> +        msg_Err(enc, "Unable to initialize configuration\n");<br>
> +        free(sys);<br>
> +        return VLC_EGENERIC;<br>
> +    }<br>
> +<br>
> +    int ret;<br>
> +<br>
> +    ret = rav1e_config_parse_int(ra_config, "height", enc->fmt_in.video.i_visible_height);<br>
> +    if (ret < 0)<br>
> +    {<br>
> +        msg_Err(enc, "Unable to set height\n");<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +    ret = rav1e_config_parse_int(ra_config, "width", enc->fmt_in.video.i_visible_width);<br>
> +    if (ret < 0) {<br>
> +        msg_Err(enc, "Unable to set width\n");<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +    RaRational *timebase = malloc(sizeof(RaRational));<br>
> +    if (timebase == NULL)<br>
> +    {<br>
> +        msg_Err(enc, "%s", "Unable to set width\n");<br>
<br>
Wrong error message (copy-pasted from above)...also shouldn't this<br>
return VLC_ENOMEM instead of VLC_EGENERIC?<br>
<br></blockquote><div> Yes, will fix.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +        goto error;<br>
> +    }<br>
> +<br>
> +    timebase->num = enc->fmt_in.video.i_frame_rate_base;<br>
> +    timebase->den = enc->fmt_in.video.i_frame_rate;<br>
> +    rav1e_config_set_time_base(ra_config, *timebase);<br>
> +<br>
> +    int tile_rows = var_InheritInteger(enc, SOUT_CFG_PREFIX "tile-rows");<br>
> +    int tile_columns = var_InheritInteger(enc, SOUT_CFG_PREFIX "tile-columns");<br>
> +    tile_rows = 1 << tile_rows;<br>
> +    tile_columns = 1 << tile_columns;<br>
> +<br>
> +    ret = rav1e_config_parse_int(ra_config, "tile_rows", tile_rows);<br>
> +    if (ret < 0)<br>
> +    {<br>
> +        msg_Err(enc, "Unable to set tile rows\n");<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +    ret = rav1e_config_parse_int(ra_config, "tile_cols", tile_columns);<br>
> +    if (ret < 0)<br>
> +    {<br>
> +        msg_Err(enc, "Unable to set tile columns\n");<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +    int bitdepth = var_InheritInteger(enc, SOUT_CFG_PREFIX "bitdepth");<br>
> +    int profile = var_InheritInteger(enc, SOUT_CFG_PREFIX "profile");<br>
> +<br>
> +    RaChromaSampling chroma_sampling;<br>
> +    switch (profile)<br>
> +    {<br>
> +        case 2:<br>
> +            chroma_sampling = RA_CHROMA_SAMPLING_CS422;<br>
> +            enc->fmt_in.i_codec = bitdepth == 8 ? VLC_CODEC_I422 : VLC_CODEC_I422_10L;<br>
> +            break;<br>
> +        case 1:<br>
> +            chroma_sampling = RA_CHROMA_SAMPLING_CS444;<br>
> +            enc->fmt_in.i_codec = bitdepth == 8 ? VLC_CODEC_I444 : VLC_CODEC_I444_10L;<br>
> +            break;<br>
> +        default:<br>
> +        case 0:<br>
> +            chroma_sampling = RA_CHROMA_SAMPLING_CS420;<br>
> +            enc->fmt_in.i_codec = bitdepth == 8 ? VLC_CODEC_I420 : VLC_CODEC_I420_10L;<br>
> +            break;<br>
> +    }<br>
> +<br>
> +    RaChromaSamplePosition sample_pos;<br>
> +    switch (enc->fmt_in.video.chroma_location)<br>
> +    {<br>
> +        case CHROMA_LOCATION_LEFT:<br>
> +            sample_pos = RA_CHROMA_SAMPLE_POSITION_VERTICAL;<br>
> +            break;<br>
> +        case CHROMA_LOCATION_TOP_LEFT:<br>
> +            sample_pos = RA_CHROMA_SAMPLE_POSITION_COLOCATED;<br>
> +            break;<br>
> +        default:<br>
> +            sample_pos = RA_CHROMA_SAMPLE_POSITION_UNKNOWN;<br>
> +            break;<br>
> +    }<br>
> +<br>
> +    RaPixelRange pixel_range;<br>
> +    switch (enc->fmt_in.video.color_range)<br>
> +    {<br>
> +        case COLOR_RANGE_FULL:<br>
> +            pixel_range = RA_PIXEL_RANGE_FULL;<br>
> +            break;<br>
> +        case COLOR_RANGE_LIMITED:<br>
> +        default:<br>
> +            pixel_range = RA_PIXEL_RANGE_LIMITED;<br>
> +            break;<br>
> +    }<br>
> +    ret = rav1e_config_set_pixel_format(ra_config, bitdepth, chroma_sampling,<br>
> +                                        sample_pos, pixel_range);<br>
> +    if (ret < 0)<br>
> +    {<br>
> +        msg_Err(enc, "Unable to set pixel format\n");<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +<br>
> +    sys->ra_context = rav1e_context_new(ra_config);<br>
> +    if (!sys->ra_context)<br>
> +    {<br>
> +        msg_Err(enc, "Unable to allocate a new context\n");<br>
> +        goto error;<br>
> +    }<br>
> +    rav1e_config_unref(ra_config);<br>
> +<br>
> +    date_Init(&sys->date, enc->fmt_out.video.i_frame_rate,<br>
> +              enc->fmt_out.video.i_frame_rate_base);<br>
> +    sys->date_set = false;<br>
> +<br>
> +    enc->pf_encode_video = Encode;<br>
> +    return VLC_SUCCESS;<br>
> +<br>
> +error:<br>
> +    rav1e_config_unref(ra_config);<br>
> +    free(sys);<br>
> +    return VLC_EGENERIC;<br>
> +}<br>
> +<br>
> +static void CloseEncoder(vlc_object_t* this)<br>
> +{<br>
> +    encoder_t *enc = (encoder_t *) this;<br>
> +    encoder_sys_t *sys = enc->p_sys;<br>
> +    rav1e_context_unref(sys->ra_context);<br>
> +    free(sys);<br>
> +}<br>
> +<br>
> +static const int bitdepth_values_list[] = {8, 10};<br>
> +static const char *bitdepth_values_name_list[] = {N_("8 bpp"), N_("10 bpp")};<br>
> +<br>
> +vlc_module_begin()<br>
> +    set_shortname("rav1e")<br>
> +    set_description(N_("rav1e video encoder"))<br>
> +    set_capability("encoder", 101)<br>
> +    set_callbacks(OpenEncoder, CloseEncoder)<br>
> +    add_integer(SOUT_CFG_PREFIX "profile", 0, "Profile", NULL, true)<br>
> +        change_integer_range(0, 3)<br>
> +    add_integer(SOUT_CFG_PREFIX "bitdepth", 8, "Bit Depth", NULL, true)<br>
> +        change_integer_list(bitdepth_values_list, bitdepth_values_name_list)<br>
> +    add_integer(SOUT_CFG_PREFIX "tile-rows", 0, "Tile Rows (in log2 units)", NULL, true)<br>
> +        change_integer_range(0, 6)<br>
> +    add_integer(SOUT_CFG_PREFIX "tile-columns", 0, "Tile Columns (in log2 units)", NULL, true)<br>
> +        change_integer_range(0, 6)<br>
> +vlc_module_end()<br>
> --<br>
> 2.28.0<br>
><br>
> _______________________________________________<br>
> vlc-devel mailing list<br>
> To unsubscribe or modify your subscription options:<br>
> <a href="https://mailman.videolan.org/listinfo/vlc-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/vlc-devel</a><br>
<br>
Best,<br>
-t<br>
_______________________________________________<br>
vlc-devel mailing list<br>
To unsubscribe or modify your subscription options:<br>
<a href="https://mailman.videolan.org/listinfo/vlc-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/vlc-devel</a></blockquote></div></div>