diff mbox

[FFmpeg-devel,v3,2/3] lavc, doc, configure: add libdavs2 video decoder

Message ID 1527643189-2860-2-git-send-email-hwrenx@126.com
State New
Headers show

Commit Message

hwren May 30, 2018, 1:19 a.m. UTC
Add avs2 video decoder via libdavs2 library.

Signed-off-by: hwren <hwrenx@126.com>
---
 Changelog              |   1 +
 configure              |   4 +
 doc/decoders.texi      |  10 +++
 doc/general.texi       |   8 ++
 libavcodec/Makefile    |   1 +
 libavcodec/allcodecs.c |   1 +
 libavcodec/libdavs2.c  | 204 +++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 229 insertions(+)
 create mode 100644 libavcodec/libdavs2.c

Comments

Mark Thompson May 30, 2018, 10:32 p.m. UTC | #1
On 30/05/18 02:19, hwren wrote:
> Add avs2 video decoder via libdavs2 library.
> 
> Signed-off-by: hwren <hwrenx@126.com>
> ---
>  Changelog              |   1 +
>  configure              |   4 +
>  doc/decoders.texi      |  10 +++
>  doc/general.texi       |   8 ++
>  libavcodec/Makefile    |   1 +
>  libavcodec/allcodecs.c |   1 +
>  libavcodec/libdavs2.c  | 204 +++++++++++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 229 insertions(+)
>  create mode 100644 libavcodec/libdavs2.c
> 
> ...
> diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c
> new file mode 100644
> index 0000000..b4a5f72
> --- /dev/null
> +++ b/libavcodec/libdavs2.c
> @@ -0,0 +1,204 @@
> +/*
> + * AVS2 decoding using the davs2 library
> + *
> + * Copyright (C) 2018 Yiqun Xu, <yiqun.xu@vipl.ict.ac.cn>
> + *                    Falei Luo, <falei.luo@gmail.com>
> + *                    Huiwen Ren, <hwrenx@gmail.com>
> + *
> + * 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 "libavutil/avassert.h"
> +#include "libavutil/common.h"
> +#include "libavutil/avutil.h"
> +#include "avcodec.h"
> +#include "libavutil/imgutils.h"
> +#include "internal.h"
> +
> +#include <davs2.h>
> +
> +typedef struct DAVS2Context {
> +    void *decoder;
> +
> +    AVFrame *frame;
> +    davs2_param_t    param;      // decoding parameters
> +    davs2_packet_t   packet;     // input bitstream
> +
> +    int decoded_frames;
> +
> +    davs2_picture_t  out_frame;  // output data, frame data
> +    davs2_seq_info_t headerset;  // output data, sequence header
> +
> +}DAVS2Context;
> +
> +static av_cold davs2_init(AVCodecContext *avctx)

Missing return type.

> +{
> +    DAVS2Context *cad = avctx->priv_data;
> +
> +    /* init the decoder */
> +    cad->param.threads      = avctx->thread_count;
> +    cad->param.i_info_level = 0;
> +    cad->decoder = davs2_decoder_open(&cad->param);
> +    avctx->flags |= AV_CODEC_FLAG_TRUNCATED;

From avcodec.h:

    /**
     * AV_CODEC_FLAG_*.
     * - encoding: Set by user.
     * - decoding: Set by user.
     */
    int flags;

The decoder should not be setting this field.

Having run this and seen it reading in 1024-byte chunks from a flat, I think what you actually need here to support flat files is a demuxer/parser which is aware of the structure of the codec and can split the input file into sensible packets.  (Any input other than a flat file will already do this.)

> +
> +    av_log(avctx, AV_LOG_VERBOSE, "decoder created. %p\n", cad->decoder);
> +    return 0;
> +}
> +
> +static int davs_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, davs2_seq_info_t *headerset, AVFrame *frame)
> +{
> +    DAVS2Context *cad = avctx->priv_data;
> +    avctx->flags |= AV_CODEC_FLAG_TRUNCATED;

Remove this.

> +    int bytes_per_sample = pic->bytes_per_sample;
> +    int i;
> +
> +    if (!headerset)
> +        return 0;
> +
> +    if (!pic || pic->ret_type == DAVS2_GOT_HEADER) {
> +        avctx->width        = headerset->horizontal_size;
> +        avctx->height       = headerset->vertical_size;
> +        avctx->pix_fmt      = headerset->output_bitdepth == 10 ? AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV420P;

It looks like the output bitdepth is actually set at build time of the library, right?  Does that do downsampling/upsampling if the input has the other bitdepth, or will it fail in that case?

> +
> +        AVRational r = av_d2q(headerset->frame_rate,4096);
> +        avctx->framerate.num = r.num;
> +        avctx->framerate.den = r.den;

AVCodecContext.framerate is also an AVRational, so you don't need this indirection (also fixes the mixed declarations and code).

Alternatively: the API appears to give you frame_rate_code as well, so indexing that into ff_mpeg12_frame_rate_tab[] will give you the right value without any rounding.

> +        return 0;
> +    }
> +
> +    for (i = 0; i < 3; ++i) {
> +        int size_plane = pic->width[i] * pic->lines[i] * bytes_per_sample;
> +        frame->buf[i]      = av_buffer_alloc(size_plane);
> +        frame->data[i]     = frame->buf[i]->data;

Crashes if the allocation failed - you need to immediately check after the allocation.

> +        frame->linesize[i] = pic->width[i] * bytes_per_sample;
> +        if (!frame->buf[i] || !frame->data[i] || !frame->linesize[i]){
> +            av_log(avctx, AV_LOG_ERROR, "dump error: alloc failed.\n");
> +            return AVERROR(EINVAL);
> +        }
> +        memcpy(frame->data[i], pic->planes[i], size_plane);
> +    }
> +
> +    frame->width     = cad->headerset.horizontal_size;
> +    frame->height    = cad->headerset.vertical_size;
> +    frame->pts       = cad->out_frame.pts;

The timestamps on the output frames don't seem to make any sense?

E.g. from a raw 30000/1001fps stream made with xavs2 I got the output:

 frame  pts
     1  0
     2  48000
     3  48000
     4  48000
     5  48000
     6  48000
     7  48000
     8  48000
     9  48000
    10  AV_NOPTS_VALUE
    11  288000
    12  AV_NOPTS_VALUE
    13  AV_NOPTS_VALUE
    14  AV_NOPTS_VALUE
    15  AV_NOPTS_VALUE
    16  AV_NOPTS_VALUE
    17  240000
    18  AV_NOPTS_VALUE
    19  672000
    20  AV_NOPTS_VALUE
    21  624000
    22  AV_NOPTS_VALUE
    23  720000
    24  768000
    25  576000

> +    frame->pict_type = pic->type;
> +    frame->format    = avctx->pix_fmt;
> +
> +    cad->decoded_frames++;
> +    return 1;
> +}
> +
> +static av_cold davs2_end(AVCodecContext *avctx)

Missing return type.

> +{
> +    DAVS2Context *cad = avctx->priv_data;
> +
> +    /* close the decoder */
> +    if (cad->decoder) {
> +        davs2_decoder_close(cad->decoder);
> +        av_log(avctx, AV_LOG_VERBOSE, "decoder destroyed. %p; frames %d\n", cad->decoder, cad->decoded_frames);
> +        cad->decoder = NULL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int davs2_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
> +{
> +    DAVS2Context *cad = avctx->priv_data;
> +    int buf_size       = avpkt->size;
> +    uint8_t *buf_ptr = avpkt->data;
> +    AVFrame *frame = data;
> +    int ret = 0;
> +
> +    *got_frame = 0;
> +    cad->frame = frame;

This field is assigned to but never read?

> +    avctx->flags |= AV_CODEC_FLAG_TRUNCATED;

Remove this.

> +
> +    if (!buf_size) {
> +        cad->packet.data = buf_ptr;
> +        cad->packet.len  = buf_size;
> +        cad->packet.pts  = avpkt->pts;
> +        cad->packet.dts  = avpkt->dts;
> +
> +        while (1) {
> +            ret = davs2_decoder_flush(cad->decoder, &cad->headerset, &cad->out_frame);
> +
> +            if (ret < 0)
> +                return 0;

I think this looks like it's checking for an error, but actually it's checking for DAVS2_END.  It might be clearer if you used the davs2_ret_e type and compared the symbolic name.

> +
> +            if (cad->out_frame.ret_type != DAVS2_DEFAULT) {
> +                *got_frame = davs_dump_frames(avctx, &cad->out_frame, &cad->headerset, frame);
> +                davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
> +            }
> +            if (*got_frame)
> +                break;
> +        }
> +        return 0;
> +    } else {
> +        while (buf_size > 0) {
> +            int len = buf_size;   // for API-3, pass all data in
> +
> +            cad->packet.marker = 0;
> +            cad->packet.data = buf_ptr;
> +            cad->packet.len  = len;
> +            cad->packet.pts  = avpkt->pts;
> +            cad->packet.dts  = avpkt->dts;
> +
> +            len = davs2_decoder_decode(cad->decoder, &cad->packet, &cad->headerset, &cad->out_frame);
> +
> +            if (cad->out_frame.ret_type != DAVS2_DEFAULT) {
> +                *got_frame = davs_dump_frames(avctx, &cad->out_frame, &cad->headerset, frame);
> +                davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
> +            }
> +
> +            if (len < 0) {
> +                av_log(avctx, AV_LOG_ERROR, "A decoder error counted\n");

I'm not sure what you mean by "counted" here.

> +                if (cad->decoder) {
> +                    davs2_decoder_close(cad->decoder);
> +                    av_log(avctx, AV_LOG_VERBOSE, "decoder destroyed. %p; frames %d\n", cad->decoder, cad->decoded_frames);
> +                    cad->decoder = NULL;

It is guaranteed that the close function will be called to clean up, so this doesn't need to be done here.

> +                }
> +                return AVERROR(EINVAL);
> +            }
> +
> +            buf_ptr     += len;
> +            buf_size    -= len;
> +
> +            if (*got_frame)
> +                break;
> +        }
> +    }
> +
> +    buf_size = (buf_ptr - avpkt->data);
> +
> +    return buf_size;
> +}
> +
> +AVCodec ff_libdavs2_decoder = {
> +    .name           = "libdavs2",
> +    .long_name      = NULL_IF_CONFIG_SMALL("Decoder for AVS2/IEEE 1857.4"),
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_AVS2,
> +    .priv_data_size = sizeof(DAVS2Context),
> +    .init           = davs2_init,
> +    .close          = davs2_end,
> +    .decode         = davs2_decode_frame,
> +    .capabilities   =  AV_CODEC_CAP_DELAY,//AV_CODEC_CAP_DR1 |
> +    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10,
> +                                                     AV_PIX_FMT_NONE },
> +    .wrapper_name   = "libdavs2",
> +};
> 

- Mark
diff mbox

Patch

diff --git a/Changelog b/Changelog
index 3d25564..ce1f97c 100644
--- a/Changelog
+++ b/Changelog
@@ -9,6 +9,7 @@  version <next>:
 - aderivative and aintegral audio filters
 - pal75bars and pal100bars video filter sources
 - support mbedTLS based TLS
+- AVS2 video decoder via libdavs2
 
 
 version 4.0:
diff --git a/configure b/configure
index 22eeca2..3c9129f 100755
--- a/configure
+++ b/configure
@@ -226,6 +226,7 @@  External library support:
   --enable-libcelt         enable CELT decoding via libcelt [no]
   --enable-libcdio         enable audio CD grabbing with libcdio [no]
   --enable-libcodec2       enable codec2 en/decoding using libcodec2 [no]
+  --enable-libdavs2        enable AVS2 decoding via libdavs2 [no]
   --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394
                            and libraw1394 [no]
   --enable-libfdk-aac      enable AAC de/encoding via libfdk-aac [no]
@@ -1636,6 +1637,7 @@  EXTERNAL_LIBRARY_GPL_LIST="
     avisynth
     frei0r
     libcdio
+    libdavs2
     librubberband
     libvidstab
     libx264
@@ -3042,6 +3044,7 @@  libaom_av1_encoder_deps="libaom"
 libcelt_decoder_deps="libcelt"
 libcodec2_decoder_deps="libcodec2"
 libcodec2_encoder_deps="libcodec2"
+libdavs2_decoder_deps="libdavs2"
 libfdk_aac_decoder_deps="libfdk_aac"
 libfdk_aac_encoder_deps="libfdk_aac"
 libfdk_aac_encoder_select="audio_frame_queue"
@@ -5992,6 +5995,7 @@  enabled libcelt           && require libcelt celt/celt.h celt_decode -lcelt0 &&
                                die "ERROR: libcelt must be installed and version must be >= 0.11.0."; }
 enabled libcaca           && require_pkg_config libcaca caca caca.h caca_create_canvas
 enabled libcodec2         && require libcodec2 codec2/codec2.h codec2_create -lcodec2
+enabled libdavs2          && require_pkg_config libdavs2 "davs2 >= 1.2.34" davs2.h davs2_decoder_decode
 enabled libdc1394         && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new
 enabled libdrm            && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion
 enabled libfdk_aac        && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen ||
diff --git a/doc/decoders.texi b/doc/decoders.texi
index a551d5d..f9d1b78 100644
--- a/doc/decoders.texi
+++ b/doc/decoders.texi
@@ -47,6 +47,16 @@  top-field-first is assumed
 
 @end table
 
+@section libdavs2
+
+AVS2/IEEE 1857.4 video decoder wrapper.
+
+This decoder allows libavcodec to decode AVS2 streams with libdavs2 library.
+Using it requires the presence of the libdavs2 headers and library during
+configuration. You need to explicitly configure the build with @code{--enable-libdavs2}.
+
+libdavs2 uses GPLv2, so you may also need to add @code{--enable-gpl} while configuring.
+
 @c man end VIDEO DECODERS
 
 @chapter Audio Decoders
diff --git a/doc/general.texi b/doc/general.texi
index 2583006..d3c1503 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -17,6 +17,14 @@  for more formats. None of them are used by default, their use has to be
 explicitly requested by passing the appropriate flags to
 @command{./configure}.
 
+@section libdavs2
+
+FFmpeg can make use of the libdavs2 library for AVS2 decoding.
+
+Go to @url{https://github.com/pkuvcl/davs2} and follow the instructions for
+installing the library. Then pass @code{--enable-libdavs2} to configure to
+enable it.
+
 @section Alliance for Open Media libaom
 
 FFmpeg can make use of the libaom library for AV1 decoding.
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3ab071a..2a845f1 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -944,6 +944,7 @@  OBJS-$(CONFIG_LIBAOM_AV1_ENCODER)         += libaomenc.o
 OBJS-$(CONFIG_LIBCELT_DECODER)            += libcelt_dec.o
 OBJS-$(CONFIG_LIBCODEC2_DECODER)          += libcodec2.o codec2utils.o
 OBJS-$(CONFIG_LIBCODEC2_ENCODER)          += libcodec2.o codec2utils.o
+OBJS-$(CONFIG_LIBDAVS2_DECODER)           += libdavs2.o
 OBJS-$(CONFIG_LIBFDK_AAC_DECODER)         += libfdk-aacdec.o
 OBJS-$(CONFIG_LIBFDK_AAC_ENCODER)         += libfdk-aacenc.o
 OBJS-$(CONFIG_LIBGSM_DECODER)             += libgsmdec.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 90d170b..a59b601 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -667,6 +667,7 @@  extern AVCodec ff_libaom_av1_encoder;
 extern AVCodec ff_libcelt_decoder;
 extern AVCodec ff_libcodec2_encoder;
 extern AVCodec ff_libcodec2_decoder;
+extern AVCodec ff_libdavs2_decoder;
 extern AVCodec ff_libfdk_aac_encoder;
 extern AVCodec ff_libfdk_aac_decoder;
 extern AVCodec ff_libgsm_encoder;
diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c
new file mode 100644
index 0000000..b4a5f72
--- /dev/null
+++ b/libavcodec/libdavs2.c
@@ -0,0 +1,204 @@ 
+/*
+ * AVS2 decoding using the davs2 library
+ *
+ * Copyright (C) 2018 Yiqun Xu, <yiqun.xu@vipl.ict.ac.cn>
+ *                    Falei Luo, <falei.luo@gmail.com>
+ *                    Huiwen Ren, <hwrenx@gmail.com>
+ *
+ * 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 "libavutil/avassert.h"
+#include "libavutil/common.h"
+#include "libavutil/avutil.h"
+#include "avcodec.h"
+#include "libavutil/imgutils.h"
+#include "internal.h"
+
+#include <davs2.h>
+
+typedef struct DAVS2Context {
+    void *decoder;
+
+    AVFrame *frame;
+    davs2_param_t    param;      // decoding parameters
+    davs2_packet_t   packet;     // input bitstream
+
+    int decoded_frames;
+
+    davs2_picture_t  out_frame;  // output data, frame data
+    davs2_seq_info_t headerset;  // output data, sequence header
+
+}DAVS2Context;
+
+static av_cold davs2_init(AVCodecContext *avctx)
+{
+    DAVS2Context *cad = avctx->priv_data;
+
+    /* init the decoder */
+    cad->param.threads      = avctx->thread_count;
+    cad->param.i_info_level = 0;
+    cad->decoder = davs2_decoder_open(&cad->param);
+    avctx->flags |= AV_CODEC_FLAG_TRUNCATED;
+
+    av_log(avctx, AV_LOG_VERBOSE, "decoder created. %p\n", cad->decoder);
+    return 0;
+}
+
+static int davs_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, davs2_seq_info_t *headerset, AVFrame *frame)
+{
+    DAVS2Context *cad = avctx->priv_data;
+    avctx->flags |= AV_CODEC_FLAG_TRUNCATED;
+    int bytes_per_sample = pic->bytes_per_sample;
+    int i;
+
+    if (!headerset)
+        return 0;
+
+    if (!pic || pic->ret_type == DAVS2_GOT_HEADER) {
+        avctx->width        = headerset->horizontal_size;
+        avctx->height       = headerset->vertical_size;
+        avctx->pix_fmt      = headerset->output_bitdepth == 10 ? AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV420P;
+
+        AVRational r = av_d2q(headerset->frame_rate,4096);
+        avctx->framerate.num = r.num;
+        avctx->framerate.den = r.den;
+        return 0;
+    }
+
+    for (i = 0; i < 3; ++i) {
+        int size_plane = pic->width[i] * pic->lines[i] * bytes_per_sample;
+        frame->buf[i]      = av_buffer_alloc(size_plane);
+        frame->data[i]     = frame->buf[i]->data;
+        frame->linesize[i] = pic->width[i] * bytes_per_sample;
+        if (!frame->buf[i] || !frame->data[i] || !frame->linesize[i]){
+            av_log(avctx, AV_LOG_ERROR, "dump error: alloc failed.\n");
+            return AVERROR(EINVAL);
+        }
+        memcpy(frame->data[i], pic->planes[i], size_plane);
+    }
+
+    frame->width     = cad->headerset.horizontal_size;
+    frame->height    = cad->headerset.vertical_size;
+    frame->pts       = cad->out_frame.pts;
+    frame->pict_type = pic->type;
+    frame->format    = avctx->pix_fmt;
+
+    cad->decoded_frames++;
+    return 1;
+}
+
+static av_cold davs2_end(AVCodecContext *avctx)
+{
+    DAVS2Context *cad = avctx->priv_data;
+
+    /* close the decoder */
+    if (cad->decoder) {
+        davs2_decoder_close(cad->decoder);
+        av_log(avctx, AV_LOG_VERBOSE, "decoder destroyed. %p; frames %d\n", cad->decoder, cad->decoded_frames);
+        cad->decoder = NULL;
+    }
+
+    return 0;
+}
+
+static int davs2_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
+{
+    DAVS2Context *cad = avctx->priv_data;
+    int buf_size       = avpkt->size;
+    uint8_t *buf_ptr = avpkt->data;
+    AVFrame *frame = data;
+    int ret = 0;
+
+    *got_frame = 0;
+    cad->frame = frame;
+    avctx->flags |= AV_CODEC_FLAG_TRUNCATED;
+
+    if (!buf_size) {
+        cad->packet.data = buf_ptr;
+        cad->packet.len  = buf_size;
+        cad->packet.pts  = avpkt->pts;
+        cad->packet.dts  = avpkt->dts;
+
+        while (1) {
+            ret = davs2_decoder_flush(cad->decoder, &cad->headerset, &cad->out_frame);
+
+            if (ret < 0)
+                return 0;
+
+            if (cad->out_frame.ret_type != DAVS2_DEFAULT) {
+                *got_frame = davs_dump_frames(avctx, &cad->out_frame, &cad->headerset, frame);
+                davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
+            }
+            if (*got_frame)
+                break;
+        }
+        return 0;
+    } else {
+        while (buf_size > 0) {
+            int len = buf_size;   // for API-3, pass all data in
+
+            cad->packet.marker = 0;
+            cad->packet.data = buf_ptr;
+            cad->packet.len  = len;
+            cad->packet.pts  = avpkt->pts;
+            cad->packet.dts  = avpkt->dts;
+
+            len = davs2_decoder_decode(cad->decoder, &cad->packet, &cad->headerset, &cad->out_frame);
+
+            if (cad->out_frame.ret_type != DAVS2_DEFAULT) {
+                *got_frame = davs_dump_frames(avctx, &cad->out_frame, &cad->headerset, frame);
+                davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
+            }
+
+            if (len < 0) {
+                av_log(avctx, AV_LOG_ERROR, "A decoder error counted\n");
+                if (cad->decoder) {
+                    davs2_decoder_close(cad->decoder);
+                    av_log(avctx, AV_LOG_VERBOSE, "decoder destroyed. %p; frames %d\n", cad->decoder, cad->decoded_frames);
+                    cad->decoder = NULL;
+                }
+                return AVERROR(EINVAL);
+            }
+
+            buf_ptr     += len;
+            buf_size    -= len;
+
+            if (*got_frame)
+                break;
+        }
+    }
+
+    buf_size = (buf_ptr - avpkt->data);
+
+    return buf_size;
+}
+
+AVCodec ff_libdavs2_decoder = {
+    .name           = "libdavs2",
+    .long_name      = NULL_IF_CONFIG_SMALL("Decoder for AVS2/IEEE 1857.4"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_AVS2,
+    .priv_data_size = sizeof(DAVS2Context),
+    .init           = davs2_init,
+    .close          = davs2_end,
+    .decode         = davs2_decode_frame,
+    .capabilities   =  AV_CODEC_CAP_DELAY,//AV_CODEC_CAP_DR1 |
+    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10,
+                                                     AV_PIX_FMT_NONE },
+    .wrapper_name   = "libdavs2",
+};