[FFmpeg-devel] [PATCH v3 2/3] lavc, doc, configure: add libdavs2 video decoder
hwren
hwrenx at 126.com
Wed May 30 04:19:48 EEST 2018
Add avs2 video decoder via libdavs2 library.
Signed-off-by: hwren <hwrenx at 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/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
+ at 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}.
+ at 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 at vipl.ict.ac.cn>
+ * Falei Luo, <falei.luo at gmail.com>
+ * Huiwen Ren, <hwrenx at 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",
+};
--
2.7.4
More information about the ffmpeg-devel
mailing list