[FFmpeg-devel] [PATCH] lavc,lavf: add libdavs2 decoder
hwren
hwrenx at 126.com
Sat May 26 07:41:14 EEST 2018
Add Chinese AVS2 video decoder, FFmpeg can make use of the libdavs2 library for AVS2 decoding.
Signed-off-by: hwren <hwrenx at 126.com>
---
Changelog | 1 +
configure | 6 ++
doc/general.texi | 8 ++
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/codec_desc.c | 7 ++
libavcodec/libdavs2.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
libavformat/riff.c | 1 +
9 files changed, 242 insertions(+)
create mode 100644 libavcodec/libdavs2.c
diff --git a/Changelog b/Changelog
index 3d25564..0f97679 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
version 4.0:
diff --git a/configure b/configure
index 09ff0c5..9aec00d 100755
--- a/configure
+++ b/configure
@@ -276,6 +276,7 @@ External library support:
--enable-libx264 enable H.264 encoding via x264 [no]
--enable-libx265 enable HEVC encoding via x265 [no]
--enable-libxavs enable AVS encoding via xavs [no]
+ --enable-libdavs2 enable AVS2 decoding via davs2 [no]
--enable-libxcb enable X11 grabbing using XCB [autodetect]
--enable-libxcb-shm enable X11 grabbing shm communication [autodetect]
--enable-libxcb-xfixes enable X11 grabbing mouse rendering [autodetect]
@@ -1641,6 +1642,7 @@ EXTERNAL_LIBRARY_GPL_LIST="
libx264
libx265
libxavs
+ libdavs2
libxvid
"
@@ -3095,6 +3097,7 @@ libx264rgb_encoder_deps="libx264 x264_csp_bgr"
libx264rgb_encoder_select="libx264_encoder"
libx265_encoder_deps="libx265"
libxavs_encoder_deps="libxavs"
+libdavs2_decoder_deps="libdavs2"
libxvid_encoder_deps="libxvid"
libzvbi_teletext_decoder_deps="libzvbi"
vapoursynth_demuxer_deps="vapoursynth"
@@ -6104,6 +6107,9 @@ enabled libx264 && { check_pkg_config libx264 x264 "stdint.h x264.h" x
enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get &&
require_cpp_condition x265.h "X265_BUILD >= 68"
enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs"
+enabled libdavs2 && require_pkg_config libdavs2 davs2 "stdint.h davs2.h" davs2_decoder_decode &&
+ { check_cpp_condition davs2 davs2.h "DAVS2_BUILD >= 12" ||
+ die "ERROR: libdavs2 version must be >= 12." ; }
enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore
enabled libzimg && require_pkg_config libzimg "zimg >= 2.7.0" zimg.h zimg_get_api_version
enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new
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..e85b74c 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -985,6 +985,7 @@ OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
+OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 7b7a8c7..6103081 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -705,6 +705,7 @@ extern AVCodec ff_libx264_encoder;
extern AVCodec ff_libx264rgb_encoder;
extern AVCodec ff_libx265_encoder;
extern AVCodec ff_libxavs_encoder;
+extern AVCodec ff_libdavs2_decoder;
extern AVCodec ff_libxvid_encoder;
extern AVCodec ff_libzvbi_teletext_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index fb0c6fa..a8cbc7b 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -303,6 +303,7 @@ enum AVCodecID {
AV_CODEC_ID_KMVC,
AV_CODEC_ID_FLASHSV,
AV_CODEC_ID_CAVS,
+ AV_CODEC_ID_AVS2,
AV_CODEC_ID_JPEG2000,
AV_CODEC_ID_VMNC,
AV_CODEC_ID_VP5,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 79552a9..9b50dae 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -651,6 +651,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
},
{
+ .id = AV_CODEC_ID_AVS2,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "avs2",
+ .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS2 (Audio Video Standar) (AVS2-P2, JiZhun profile)"),
+ .props = AV_CODEC_PROP_LOSSY,
+ },
+ {
.id = AV_CODEC_ID_JPEG2000,
.type = AVMEDIA_TYPE_VIDEO,
.name = "jpeg2000",
diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c
new file mode 100644
index 0000000..3537f40
--- /dev/null
+++ b/libavcodec/libdavs2.c
@@ -0,0 +1,216 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <davs2.h>
+
+typedef struct DAVS2Context {
+ AVCodecContext *avctx;
+ void *dec_handle;
+ int got_seqhdr;
+
+ void *decoder;
+
+ AVFrame *frame;
+ davs2_param_t param; // decoding parameters
+ davs2_packet_t packet; // input bitstream
+ int ret;
+
+ int img_width[3];
+ int img_height[3];
+ int out_flag;
+ int decoded_frames;
+
+ davs2_picture_t out_frame; // output data, frame data
+ davs2_seq_info_t headerset; // output data, sequence header
+
+}DAVS2Context;
+
+static int ff_davs2_init(AVCodecContext *avctx)
+{
+ DAVS2Context *cad = avctx->priv_data;
+
+ /* init the decoder */
+ cad->param.threads = 0;
+ cad->param.i_info_level = 0;
+ cad->decoder = davs2_decoder_open(&cad->param);
+ avctx->flags |= AV_CODEC_FLAG_TRUNCATED;
+
+ av_log(avctx, AV_LOG_WARNING, "[davs2] decoder created. 0x%llx\n", cad->decoder);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------------
+ */
+static int DumpFrames(AVCodecContext *avctx, davs2_picture_t *pic, davs2_seq_info_t *headerset, AVFrame *frm)
+{
+ DAVS2Context *cad = avctx->priv_data;
+ avctx->flags |= AV_CODEC_FLAG_TRUNCATED;
+
+ if (headerset == NULL) {
+ return 0;
+ }
+
+ if (pic == NULL || pic->ret_type == DAVS2_GOT_HEADER) {
+ avctx->frame_size = (headerset->horizontal_size * headerset->vertical_size * 3 * headerset->bytes_per_sample) >> 1;
+ avctx->coded_width = headerset->horizontal_size;
+ avctx->coded_height = headerset->vertical_size;
+ 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);
+ avctx->framerate.num = (int)(headerset->frame_rate);
+ avctx->framerate.den = 1;
+ return 0;
+ }
+
+ const int bytes_per_sample = pic->bytes_per_sample;
+ int i;
+
+ for (i = 0; i < 3; ++i) {
+ int size_plane = pic->width[i] * pic->lines[i] * bytes_per_sample;
+ frm->buf[i] = av_buffer_alloc(size_plane);
+ frm->data[i] = frm->buf[i]->data;
+ frm->linesize[i] = pic->width[i] * bytes_per_sample;
+ memcpy(frm->data[i], pic->planes[i], size_plane);
+ }
+
+ frm->width = cad->headerset.horizontal_size;
+ frm->height = cad->headerset.vertical_size;
+ frm->pts = cad->out_frame.pts;
+
+ frm->key_frame = 1;
+ frm->pict_type = AV_PICTURE_TYPE_I;
+ frm->format = avctx->pix_fmt;
+ cad->out_flag = 1;
+
+ cad->decoded_frames++;
+ return 1;
+}
+
+static int ff_davs2_end(AVCodecContext *avctx)
+{
+ DAVS2Context *cad = avctx->priv_data;
+
+ /* close the decoder */
+ if (cad->decoder != NULL) {
+ davs2_decoder_close(cad->decoder);
+ av_log(avctx, AV_LOG_WARNING, "[davs2] decoder destroyed. 0x%llx; 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;
+ const uint8_t *buf_ptr = avpkt->data;
+ AVFrame *frm = data;
+
+ *got_frame = 0;
+ cad->out_flag=0;
+ cad->frame = frm;
+ avctx->flags |= AV_CODEC_FLAG_TRUNCATED;
+
+ if (buf_size == 0) {
+ cad->packet.data = buf_ptr;
+ cad->packet.len = buf_size;
+ cad->packet.pts = avpkt->pts;
+ cad->packet.dts = avpkt->dts;
+
+ for (;;) {
+ cad->ret = davs2_decoder_flush(cad->decoder, &cad->headerset, &cad->out_frame);
+
+ if (cad->ret < 0) {
+ return 0;
+ }
+
+ if (cad->out_frame.ret_type != DAVS2_DEFAULT) {
+ *got_frame = DumpFrames(avctx, &cad->out_frame, &cad->headerset, frm);
+ davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
+ }
+ if(cad->out_flag == 1) {
+ break;
+ }
+ }
+ return 0;
+ } else {
+ for(; 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 = DumpFrames(avctx, &cad->out_frame, &cad->headerset, frm);
+ davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
+ }
+
+ if (len < 0) {
+ av_log(NULL, AV_LOG_ERROR, "An decoder error counted\n");
+
+ return -1;
+ }
+
+ buf_ptr += len;
+ buf_size -= len;
+
+ if(cad->out_flag == 1) {
+ break;
+ }
+ }
+ }
+
+ buf_size = (buf_ptr - avpkt->data);
+
+ return buf_size;
+}
+
+AVCodec ff_libdavs2_decoder = {
+ .name = "libdavs2",
+ .long_name = NULL_IF_CONFIG_SMALL("Decoder for Chinese AVS2"),
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_AVS2,
+ .priv_data_size = sizeof(DAVS2Context),
+ .init = ff_davs2_init,
+ .close = ff_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 },
+};
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 8911725..4153372 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -369,6 +369,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') },
{ AV_CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') },
{ AV_CODEC_ID_CAVS, MKTAG('C', 'A', 'V', 'S') },
+ { AV_CODEC_ID_AVS2, MKTAG('A', 'V', 'S', '2') },
{ AV_CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') },
{ AV_CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') },
{ AV_CODEC_ID_JPEG2000, MKTAG('L', 'J', '2', 'C') },
--
2.7.4
More information about the ffmpeg-devel
mailing list