[FFmpeg-devel] [PATCH 1/2] avcodec: add av1 hardware acceleration decoder

James Almer jamrial at gmail.com
Mon Aug 24 16:10:43 EEST 2020


On 8/24/2020 3:57 AM, Wang, Fei W wrote:
> 
> 
>> -----Original Message-----
>> From: ffmpeg-devel <ffmpeg-devel-bounces at ffmpeg.org> On Behalf Of James
>> Almer
>> Sent: Friday, August 21, 2020 10:43 PM
>> To: ffmpeg-devel at ffmpeg.org
>> Subject: Re: [FFmpeg-devel] [PATCH 1/2] avcodec: add av1 hardware
>> acceleration decoder
>>
>> On 8/21/2020 2:29 AM, Fei Wang wrote:
>>> This av1 decoder is now only used for av1 hardware acceleration
>>> decoder. Consider it can be extend to a local decoder like hevc or vp9
>>> in the future, so define its name as "av1" and put it into external
>>> libraries codec list.
>>>
>>> Signed-off-by: Fei Wang <fei.w.wang at intel.com>
>>> ---
>>>  Changelog              |   1 +
>>>  configure              |   1 +
>>>  libavcodec/Makefile    |   1 +
>>>  libavcodec/allcodecs.c |   1 +
>>>  libavcodec/av1dec.c    | 746
>> +++++++++++++++++++++++++++++++++++++++++
>>>  libavcodec/av1dec.h    |  89 +++++
>>>  libavcodec/version.h   |   2 +-
>>>  7 files changed, 840 insertions(+), 1 deletion(-)  create mode 100644
>>> libavcodec/av1dec.c  create mode 100644 libavcodec/av1dec.h
>>>
>>> diff --git a/Changelog b/Changelog
>>> index 1efc768387..3ff88cc12f 100644
>>> --- a/Changelog
>>> +++ b/Changelog
>>> @@ -14,6 +14,7 @@ version <next>:
>>>  - ADPCM Argonaut Games encoder
>>>  - Argonaut Games ASF muxer
>>>  - AV1 Low overhead bitstream format demuxer
>>> +- AV1 decoder (Hardware acceleration used only)
>>>
>>>
>>>  version 4.3:
>>> diff --git a/configure b/configure
>>> index 6faff9bc7b..ef71e47c4e 100755
>>> --- a/configure
>>> +++ b/configure
>>> @@ -2685,6 +2685,7 @@ atrac3al_decoder_select="mdct"
>>>  atrac3p_decoder_select="mdct sinewin"
>>>  atrac3pal_decoder_select="mdct sinewin"
>>>  atrac9_decoder_select="mdct"
>>> +av1_decoder_select="cbs_av1"
>>>  avrn_decoder_select="exif jpegtables"
>>>  bink_decoder_select="blockdsp hpeldsp"
>>>  binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs"
>>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile index
>>> 3431ba2dca..2371039bd2 100644
>>> --- a/libavcodec/Makefile
>>> +++ b/libavcodec/Makefile
>>> @@ -764,6 +764,7 @@ OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o
>>>  OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o
>>>  OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o
>>>  OBJS-$(CONFIG_ZMBV_ENCODER)            += zmbvenc.o
>>> +OBJS-$(CONFIG_AV1_DECODER)             += av1dec.o
>>>
>>>  # (AD)PCM decoders/encoders
>>>  OBJS-$(CONFIG_PCM_ALAW_DECODER)           += pcm.o
>>> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index
>>> 4bd830e5d0..00799d3431 100644
>>> --- a/libavcodec/allcodecs.c
>>> +++ b/libavcodec/allcodecs.c
>>> @@ -761,6 +761,7 @@ extern AVCodec ff_idf_decoder;
>>>   * above is available */
>>>  extern AVCodec ff_aac_mf_encoder;
>>>  extern AVCodec ff_ac3_mf_encoder;
>>> +extern AVCodec ff_av1_decoder;
>>>  extern AVCodec ff_h263_v4l2m2m_encoder;  extern AVCodec
>>> ff_libaom_av1_decoder;  extern AVCodec ff_libopenh264_encoder; diff
>>> --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c new file mode 100644
>>> index 0000000000..ab88ed987a
>>> --- /dev/null
>>> +++ b/libavcodec/av1dec.c
>>> @@ -0,0 +1,746 @@
>>> +/*
>>> + * AV1video decoder
>>> + *
>>> + * This file is part of FFmpeg.
>>> + *
>>> + * FFmpeg is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU Lesser General Public
>>> + * License as published by the Free Software Foundation; either
>>> + * version 2.1 of the License, or (at your option) any later version.
>>> + *
>>> + * FFmpeg is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> + * Lesser General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU Lesser General Public
>>> + * License along with FFmpeg; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> +02110-1301 USA  */
>>> +
>>> +#include "avcodec.h"
>>> +#include "get_bits.h"
>>> +#include "hwconfig.h"
>>> +#include "internal.h"
>>> +#include "profiles.h"
>>> +#include "thread.h"
>>> +#include "videodsp.h"
>>> +#include "libavutil/avassert.h"
>>> +#include "libavutil/pixdesc.h"
>>> +
>>> +#include "av1dec.h"
>>> +#include "libavformat/av1.h"
>>> +
>>> +static void setup_past_independence(AV1Frame *f) {
>>> +    f->loop_filter_delta_enabled = 1;
>>> +
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_INTRA] = 1;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_LAST] = 0;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_LAST2] = 0;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_LAST3] = 0;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_GOLDEN] = -1;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_BWDREF] = 0;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_ALTREF2] = -1;
>>> +    f->loop_filter_ref_deltas[AV1_REF_FRAME_ALTREF] = -1;
>>> +
>>> +    f->loop_filter_mode_deltas[0] = 0;
>>> +    f->loop_filter_mode_deltas[1] = 0; }
>>> +
>>> +static void load_previous_and_update(AV1DecContext *s) {
>>> +    int i;
>>> +
>>> +    memcpy(s->cur_frame.loop_filter_ref_deltas,
>>> +           s->ref[s-
>>> raw_frame_header.primary_ref_frame].loop_filter_ref_deltas,
>>> +           AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
>>> +    memcpy(s->cur_frame.loop_filter_mode_deltas,
>>> +           s->ref[s-
>>> raw_frame_header.primary_ref_frame].loop_filter_mode_deltas,
>>> +           2 * sizeof(int8_t));
>>> +
>>> +    if (s->raw_frame_header.loop_filter_delta_update) {
>>> +        for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) {
>>> +            if (s->raw_frame_header.update_ref_delta[i])
>>> +                s->cur_frame.loop_filter_ref_deltas[i] =
>>> +                    s->raw_frame_header.loop_filter_ref_deltas[i];
>>> +        }
>>> +
>>> +        for (i = 0; i < 2; i++) {
>>> +            if (s->raw_frame_header.update_mode_delta[i])
>>> +                s->cur_frame.loop_filter_mode_deltas[i] =
>>> +                    s->raw_frame_header.loop_filter_mode_deltas[i];
>>> +        }
>>> +    }
>>> +
>>> +    s->cur_frame.loop_filter_delta_enabled =
>>> +        s->raw_frame_header.loop_filter_delta_enabled;
>>> +}
>>> +
>>> +static uint32_t inverse_recenter(int r, uint32_t v) {
>>> +    if (v > 2 * r)
>>> +        return v;
>>> +    else if (v & 1)
>>> +        return r - ((v + 1) >> 1);
>>> +    else
>>> +        return r + (v >> 1);
>>> +}
>>> +
>>> +static uint32_t decode_unsigned_subexp_with_ref(uint32_t sub_exp,
>>> +                                                int mx, int r) {
>>> +    if ((r << 1) <= mx) {
>>> +        return inverse_recenter(r, sub_exp);
>>> +    } else {
>>> +        return mx - 1 - inverse_recenter(mx - 1 - r, sub_exp);
>>> +    }
>>> +}
>>> +
>>> +static int32_t decode_signed_subexp_with_ref(uint32_t sub_exp, int low,
>>> +                                             int high, int r) {
>>> +    int32_t x = decode_unsigned_subexp_with_ref(sub_exp, high - low, r - low);
>>> +    return x + low;
>>> +}
>>> +
>>> +static void read_global_param(AV1DecContext *s, int type, int ref,
>>> +int idx) {
>>> +    uint32_t abs_bits, prec_bits, round, prec_diff, sub, mx, r;
>>> +    abs_bits = AV1_GM_ABS_ALPHA_BITS;
>>> +    prec_bits = AV1_GM_ALPHA_PREC_BITS;
>>> +
>>> +    if (idx < 2) {
>>> +        if (type == AV1_WARP_MODEL_TRANSLATION) {
>>> +            abs_bits = AV1_GM_ABS_TRANS_ONLY_BITS -
>>> +                !s->raw_frame_header.allow_high_precision_mv;
>>> +            prec_bits = AV1_GM_TRANS_ONLY_PREC_BITS -
>>> +                !s->raw_frame_header.allow_high_precision_mv;
>>> +        } else {
>>> +            abs_bits = AV1_GM_ABS_TRANS_BITS;
>>> +            prec_bits = AV1_GM_TRANS_PREC_BITS;
>>> +        }
>>> +    }
>>> +    round = (idx % 3) == 2 ? (1 << AV1_WARPEDMODEL_PREC_BITS) : 0;
>>> +    prec_diff = AV1_WARPEDMODEL_PREC_BITS - prec_bits;
>>> +    sub = (idx % 3) == 2 ? (1 << prec_bits) : 0;
>>> +    mx = 1 << abs_bits;
>>> +    r = (s->ref[s->raw_frame_header.primary_ref_frame].gm_params[ref][idx]
>>> +         >> prec_diff) - sub;
>>> +
>>> +    s->cur_frame.gm_params[ref][idx] =
>>> +        (decode_signed_subexp_with_ref(s-
>>> raw_frame_header.gm_params[ref][idx],
>>> +                                       -mx, mx + 1, r) << prec_diff)
>>> ++ round; }
>>> +
>>> +/**
>>> +* update gm type/params, since cbs already implemented part of this
>>> +funcation,
>>> +* so we don't need to full implement spec.
>>
>> FYI, the gm params code in cbs_av1 is currently buggy for some streams, and it
>> needs fixing.
> Thanks for your information. I will keep it in my mind. For clips(more than 200+) 
> that I tested, it looks good and I didn't meet any bug yet from cbs_av1. 
> 
> Thanks
> Fei

The known issues were fixed yesterday by Mark, so it should be good now.


More information about the ffmpeg-devel mailing list