From patchwork Sat May 26 04:41:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: hwren X-Patchwork-Id: 9088 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:155:0:0:0:0:0 with SMTP id c82-v6csp351817jad; Fri, 25 May 2018 22:12:56 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrt7JlL1OW0JIkRdPbd3R6Okumy0mKfi/oURo7aqiYfwmoa1omvoVTPZc4FXJKUPXxBx0X3 X-Received: by 2002:adf:e5d0:: with SMTP id a16-v6mr3819944wrn.190.1527311576068; Fri, 25 May 2018 22:12:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527311576; cv=none; d=google.com; s=arc-20160816; b=OcY2dmDSZWvP/982UFpRd58D7fl5wdCSlGYY+x0x81JEm0CT6yfmeJsz9GLMyDtHaA bs5iKuUFJx+3Mt16hvUyRW6/cfGF8f8EveynvvSMlIW1C93s8pEiDu5Fu9veZFMKMnjZ 1hfNUf5xWVmT/MfZiei5zclYxb6fTPjCsZ2Qk2IK73KobeoeJQ9lGvRih5uWTWuPWea7 FXA3WUXSrH0+1qFBlY63WpbRANjsnJ5gQO8FA6tonYh7fWFs2oFD9IPRKc7+lXia3bsC 2jl22CCK6TnCWYv9tEhdHXAzBE/2tiscrmZRYCoPCPYWpYfScJN7CIlP+N7hJ8tKKleg H5qA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=61jIOawlN3u0AKmNZm/6WguP4SqRSLXV6Fl3W9ovQa0=; b=djbqMNb6cNQQvDGbA2YUhyjgI2G9VtDYOJpiRJL/uXuZxVdhQiym6bWQVNFs+Y7Zk9 NEVRgQZvDCummrHpfc25iNHEiD/n7SSbrOYCbadNylCzeDEAedbSNKD9iJCKEb4PwCFS ti75RKEde9Xb0ddmcMzWU2W3S8JbHKMweNVv7jsOIvYX7fA6yXfmWnY11UBmgKp2nCx5 OKeAZ/QSyveU81WzzvdIetI8hXEHcKC0XXMixsNJ1Jm/p/xENxGC6gWyYGzjgdFZ0wmp u/ZLQQr1tVzHushI3vZSHTWyyyXtZhjmcVcWOimTmJBxamA6B1pewEQsUKaWRAuTkA5t F73Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@126.com header.s=s110527 header.b=VFVBVBQC; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=126.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k186-v6si6618855wmd.96.2018.05.25.22.12.55; Fri, 25 May 2018 22:12:56 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@126.com header.s=s110527 header.b=VFVBVBQC; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=126.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A4CA9689C3B; Sat, 26 May 2018 08:12:10 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from m15-111.126.com (m15-111.126.com [220.181.15.111]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 646506897AC for ; Sat, 26 May 2018 08:12:02 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-Id; bh=it472ZlQz4jzVaq/vH 57IphaM4+jS+bBx3d1ebetHUs=; b=VFVBVBQC92WwtFy9vfMJEnoGHGWNOZ1WdD snJTYPSZGl8363GmzIphLQE6kCNrCZltcTSURJu40HE+sTwCSVsgPrgERXTIpp8g Jt5yLRBMq+p8ZFmerZfKbK45nNyhGju9eq6f+xuF7nOtGvyE7+ypLyYT96OxJB+E wlKRnJZtY= Received: from localhost.localdomain (unknown [223.71.83.115]) by smtp1 (Coremail) with SMTP id C8mowADnGZxw5QhbstTMBg--.16446S3; Sat, 26 May 2018 12:41:21 +0800 (CST) From: hwren To: ffmpeg-devel@ffmpeg.org Date: Sat, 26 May 2018 12:41:14 +0800 Message-Id: <1527309674-432-1-git-send-email-hwrenx@126.com> X-Mailer: git-send-email 2.7.4 X-CM-TRANSID: C8mowADnGZxw5QhbstTMBg--.16446S3 X-Coremail-Antispam: 1Uf129KBjvAXoW3tF4fGry7Ar13tw1DAF15twb_yoW8Jry8Xo WxZF1jvw1DJr1S9F1kCr18W3ZxXr1FgrW7GwsYyay5G395ua45J34Ykw13WFZIkayfta9x AFWxtw47XFWDJws5n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxUvbAwDUUUU X-Originating-IP: [223.71.83.115] X-CM-SenderInfo: pkzuv0b06rjloofrz/1tbiuxJS6VpD5duW0AAAsz Subject: [FFmpeg-devel] [PATCH] lavc,lavf: add libdavs2 decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Add Chinese AVS2 video decoder, FFmpeg can make use of the libdavs2 library for AVS2 decoding. Signed-off-by: hwren --- 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 : - 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}. +@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, + * Falei Luo, + * Huiwen Ren, + * + * 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 +#include +#include + +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') },