[PATCH v1 0/4] Supplement AVS3-P2/IEEE1857.10 video decoding via libuavs3d
From: hwren <hwrenx@126.com> These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream hwren (4): lavc: add AVS3 codec id and desc lavc/avs3_paeser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avs3_parser.c | 184 ++++++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 79 +++++++++++++ 14 files changed, 594 insertions(+) create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.7.4
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 9f88475..ad55d99 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1406,6 +1406,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, + { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, .name = "y41p", diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index d885962..7f7dee5 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -241,6 +241,7 @@ enum AVCodecID { AV_CODEC_ID_SCREENPRESSO, AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.7.4
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 186 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5a6ea59..f151277 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1053,6 +1053,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000..7a7f826 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,184 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "parser.h" + +#define SLICE_MAX_START_CODE 0x000001af + +#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define ISUNIT(x) ((x) == 0xB0 || ISPIC(x)) + +static av_cold int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state<<8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static unsigned int read_bits(const char** ppbuf, int *pidx, int bits) +{ + const char* p = *ppbuf; + int idx = *pidx; + unsigned int val = 0; + + while (bits) { + bits--; + val = (val << 1) | (((*p) >> idx) & 0x1); + if (--idx < 0) { + idx = 7; + p++; + } + } + + *ppbuf = p; + *pidx = idx; + + return val; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == 0xB0) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + int profile,ratecode; + const char* p = buf + 4; + int idx = 7; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = read_bits(&p, &idx, 8); + // level(8) + progressive(1) + field(1) + library(2) + resv(1) + width(14) + resv(1) + height(14) + chroma(2) + sampe_precision(3) + read_bits(&p, &idx, 47); + + if (profile == 0x22) { + avctx->pix_fmt = read_bits(&p, &idx, 3) == 1 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + } + + // resv(1) + aspect(4) + read_bits(&p, &idx, 5); + + ratecode = read_bits(&p, &idx, 4); + + // resv(1) + bitrate_low(18) + resv(1) + bitrate_high(12) + read_bits(&p, &idx, 32); + + avctx->has_b_frames = !read_bits(&p, &idx, 1); + + avctx->framerate.num = avctx->time_base.den = avs3_fps_num[ratecode]; + avctx->framerate.den = avctx->time_base.num = avs3_fps_den[ratecode]; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == 0xB3) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == 0xB6){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea..aab1d5e 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.7.4
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 libavformat/avs3dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 26af859..b433a60 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -120,6 +120,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 97fd06d..2d768b8 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -82,6 +82,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000..9758071 --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,79 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avformat.h" +#include "rawdec.h" +#include "libavcodec/internal.h" + +#define AVS3_SEQ_START_CODE 0x000001b0 +#define AVS3_PIC_I_START_CODE 0x000001b3 +#define AVS3_UNDEF_START_CODE 0x000001b4 +#define AVS3_PIC_PB_START_CODE 0x000001b6 +#define AVS3_VIDEO_EDIT_CODE 0x000001b7 +#define AVS3_PROFILE_JIZHUN 0x20 +#define AVS3_PROFILE_JIZHUN10 0x22 + +static int avs3video_probe(const AVProbeData *p) +{ + uint32_t code= -1; + int pic=0, seq=0, slice_pos = 0; + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + if ((code & 0xffffff00) == 0x100) { + if (code < AVS3_SEQ_START_CODE) { + /* slices have to be consecutive */ + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (code == AVS3_SEQ_START_CODE) { + seq++; + /* check for the only currently supported profile */ + if (*ptr != AVS3_PROFILE_JIZHUN && *ptr != AVS3_PROFILE_JIZHUN10) + return 0; + } else if ((code == AVS3_PIC_I_START_CODE) || + (code == AVS3_PIC_PB_START_CODE)) { + pic++; + } else if ((code == AVS3_UNDEF_START_CODE) || + (code > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + if (seq && pic) { + if (av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } else { + ret = AVPROBE_SCORE_EXTENSION + 1; + } + } + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) + -- 2.7.4
On Sat, Jun 20, 2020 at 09:45:51AM +0800, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 libavformat/avs3dec.c
this breaks: ./ffmpeg -i ~/tickets/1901/stream.avs -vframes 4 file.avi I assume the input file is here: https://osdn.net/projects/sfnet_openavs/downloads/test-bitstreams/test%20bit... thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Nations do behave wisely once they have exhausted all other alternatives. -- Abba Eban
From: hwren <hwrenx@126.com> === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS, AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. Thanks. hwren (4): lavc: add AVS3 codec id and desc lavc/avs3_paeser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 75 +++++++++++ 14 files changed, 590 insertions(+) create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 9f8847544f..ad55d992d3 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1405,6 +1405,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index d885962c9c..7f7dee51f1 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -241,6 +241,7 @@ enum AVCodecID { AV_CODEC_ID_SCREENPRESSO, AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 186 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5a6ea59715..f1512779be 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1053,6 +1053,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..7a7f826c59 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,184 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "parser.h" + +#define SLICE_MAX_START_CODE 0x000001af + +#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define ISUNIT(x) ((x) == 0xB0 || ISPIC(x)) + +static av_cold int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state<<8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static unsigned int read_bits(const char** ppbuf, int *pidx, int bits) +{ + const char* p = *ppbuf; + int idx = *pidx; + unsigned int val = 0; + + while (bits) { + bits--; + val = (val << 1) | (((*p) >> idx) & 0x1); + if (--idx < 0) { + idx = 7; + p++; + } + } + + *ppbuf = p; + *pidx = idx; + + return val; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == 0xB0) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + int profile,ratecode; + const char* p = buf + 4; + int idx = 7; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = read_bits(&p, &idx, 8); + // level(8) + progressive(1) + field(1) + library(2) + resv(1) + width(14) + resv(1) + height(14) + chroma(2) + sampe_precision(3) + read_bits(&p, &idx, 47); + + if (profile == 0x22) { + avctx->pix_fmt = read_bits(&p, &idx, 3) == 1 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + } + + // resv(1) + aspect(4) + read_bits(&p, &idx, 5); + + ratecode = read_bits(&p, &idx, 4); + + // resv(1) + bitrate_low(18) + resv(1) + bitrate_high(12) + read_bits(&p, &idx, 32); + + avctx->has_b_frames = !read_bits(&p, &idx, 1); + + avctx->framerate.num = avctx->time_base.den = avs3_fps_num[ratecode]; + avctx->framerate.den = avctx->time_base.num = avs3_fps_den[ratecode]; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == 0xB3) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == 0xB6){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 75 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 libavformat/avs3dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 26af859a28..b433a6029c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -120,6 +120,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 97fd06debb..2d768b8c88 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -82,6 +82,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..955114dc42 --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,75 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avformat.h" +#include "rawdec.h" +#include "libavcodec/internal.h" + +#define AVS3_SEQ_START_CODE 0x000001b0 +#define AVS3_PIC_I_START_CODE 0x000001b3 +#define AVS3_UNDEF_START_CODE 0x000001b4 +#define AVS3_PIC_PB_START_CODE 0x000001b6 +#define AVS3_VIDEO_EDIT_CODE 0x000001b7 +#define AVS3_PROFILE_JIZHUN 0x20 +#define AVS3_PROFILE_JIZHUN10 0x22 + +static int avs3video_probe(const AVProbeData *p) +{ + uint32_t code= -1; + int pic=0, seq=0, slice_pos = 0; + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + if ((code & 0xffffff00) == 0x100) { + if (code < AVS3_SEQ_START_CODE) { + /* slices have to be consecutive */ + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (code == AVS3_SEQ_START_CODE) { + seq++; + /* check for the only currently supported profile */ + if (*ptr != AVS3_PROFILE_JIZHUN && *ptr != AVS3_PROFILE_JIZHUN10) + return 0; + } else if ((code == AVS3_PIC_I_START_CODE) || + (code == AVS3_PIC_PB_START_CODE)) { + pic++; + } else if ((code == AVS3_UNDEF_START_CODE) || + (code > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) + -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index a60e7d2eb8..dfd56b3fc6 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version <next>: - AudioToolbox output device - MacCaption demuxer +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 7495f35faa..7340bc4a35 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvorbis libvpx @@ -3242,6 +3244,7 @@ libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6379,6 +6382,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d uavs3d uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..f1a0b3c36e 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -86,6 +86,27 @@ AVS2-P2/IEEE1857.4 video decoder wrapper. This decoder allows libavcodec to decode AVS2 streams with davs2 library. +@c man end VIDEO DECODERS + +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + @c man end VIDEO DECODERS @chapter Audio Decoders diff --git a/doc/general.texi b/doc/general.texi index 9b0ee96752..6d673b74e1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f1512779be..491485f3c0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 80f128cade..3d2d0af87a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavutil/opt.h" +#include "avcodec.h" +#include "uavs3d.h" +#include "libavutil/imgutils.h" +#include "internal.h" + +#define UAVS3D_MAX_FRAME_THREADS 48 + +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType IMGTYPE[8] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */ + ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */ + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs2_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs2_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs2_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs2_fps_den[frm_dec->seqhdr->frame_rate_code]; + avctx->has_b_frames = 1; + avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE }, + { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +}; -- 2.23.0.windows.1
? On Mon, Jun 22, 2020 at 9:59 PM <hwrenx@126.com> wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c
diff --git a/Changelog b/Changelog index a60e7d2eb8..dfd56b3fc6 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version <next>: - AudioToolbox output device - MacCaption demuxer +- AVS3 video decoder via libuavs3d
version 4.3: diff --git a/configure b/configure index 7495f35faa..7340bc4a35 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvorbis libvpx @@ -3242,6 +3244,7 @@ libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6379,6 +6382,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d uavs3d uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..f1a0b3c36e 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -86,6 +86,27 @@ AVS2-P2/IEEE1857.4 video decoder wrapper.
This decoder allows libavcodec to decode AVS2 streams with davs2 library.
+@c man end VIDEO DECODERS + +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + @c man end VIDEO DECODERS
@chapter Audio Decoders diff --git a/doc/general.texi b/doc/general.texi index 9b0ee96752..6d673b74e1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f1512779be..491485f3c0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 80f128cade..3d2d0af87a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavutil/opt.h" +#include "avcodec.h" +#include "uavs3d.h" +#include "libavutil/imgutils.h" +#include "internal.h" + +#define UAVS3D_MAX_FRAME_THREADS 48 + +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType IMGTYPE[8] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */ + ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */ + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs2_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs2_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 };
Why use a name like avs2_fps_num and avs2_fps_den ?
+ avctx->framerate.nu_nium = avs2_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs2_fps_den[frm_dec->seqhdr->frame_rate_code]; + avctx->has_b_frames = 1; + avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE }, + { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +}; -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS, AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. Thanks. hwren (4): lavc: add AVS3 codec id and desc lavc/avs3_paeser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 75 +++++++++++ 14 files changed, 590 insertions(+) create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 9f8847544f..ad55d992d3 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1405,6 +1405,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index d885962c9c..7f7dee51f1 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -241,6 +241,7 @@ enum AVCodecID { AV_CODEC_ID_SCREENPRESSO, AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 186 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5a6ea59715..f1512779be 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1053,6 +1053,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..7a7f826c59 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,184 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "parser.h" + +#define SLICE_MAX_START_CODE 0x000001af + +#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define ISUNIT(x) ((x) == 0xB0 || ISPIC(x)) + +static av_cold int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state<<8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static unsigned int read_bits(const char** ppbuf, int *pidx, int bits) +{ + const char* p = *ppbuf; + int idx = *pidx; + unsigned int val = 0; + + while (bits) { + bits--; + val = (val << 1) | (((*p) >> idx) & 0x1); + if (--idx < 0) { + idx = 7; + p++; + } + } + + *ppbuf = p; + *pidx = idx; + + return val; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == 0xB0) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + int profile,ratecode; + const char* p = buf + 4; + int idx = 7; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = read_bits(&p, &idx, 8); + // level(8) + progressive(1) + field(1) + library(2) + resv(1) + width(14) + resv(1) + height(14) + chroma(2) + sampe_precision(3) + read_bits(&p, &idx, 47); + + if (profile == 0x22) { + avctx->pix_fmt = read_bits(&p, &idx, 3) == 1 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + } + + // resv(1) + aspect(4) + read_bits(&p, &idx, 5); + + ratecode = read_bits(&p, &idx, 4); + + // resv(1) + bitrate_low(18) + resv(1) + bitrate_high(12) + read_bits(&p, &idx, 32); + + avctx->has_b_frames = !read_bits(&p, &idx, 1); + + avctx->framerate.num = avctx->time_base.den = avs3_fps_num[ratecode]; + avctx->framerate.den = avctx->time_base.num = avs3_fps_den[ratecode]; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == 0xB3) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == 0xB6){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
Typo "paeser" in the title. On 05/08/2020 17:18, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 186 insertions(+) create mode 100644 libavcodec/avs3_parser.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5a6ea59715..f1512779be 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1053,6 +1053,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..7a7f826c59 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,184 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "parser.h" + +#define SLICE_MAX_START_CODE 0x000001af + +#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define ISUNIT(x) ((x) == 0xB0 || ISPIC(x))
Perhaps give the magic numbers here symbolic constants? (Sequence header, etc.)
+ +static av_cold int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size)
This function doesn't look cold.
+{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state<<8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static unsigned int read_bits(const char** ppbuf, int *pidx, int bits) +{ + const char* p = *ppbuf; + int idx = *pidx; + unsigned int val = 0; + + while (bits) { + bits--; + val = (val << 1) | (((*p) >> idx) & 0x1); + if (--idx < 0) { + idx = 7; + p++; + } + } + + *ppbuf = p; + *pidx = idx; + + return val; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == 0xB0) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 };
Is this meant to be the MPEG-1 frame rate code table? (It looks the same other than num[1], which looks like a typo.) If so, there is a global ff_mpeg12_frame_rate_tab already containing the values.
+ int profile,ratecode; + const char* p = buf + 4; + int idx = 7; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = read_bits(&p, &idx, 8); + // level(8) + progressive(1) + field(1) + library(2) + resv(1) + width(14) + resv(1) + height(14) + chroma(2) + sampe_precision(3) + read_bits(&p, &idx, 47);
This ad-hoc reimplementation of get_bits does not seem like a good idea - it's reading one bit at a time and lacks any checks for overflow. Please just use get_bits().
+ + if (profile == 0x22) { + avctx->pix_fmt = read_bits(&p, &idx, 3) == 1 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + }
Are other values of profile likely to be valid in future, requiring different parsing? Is it worth rejecting these here?
+ + // resv(1) + aspect(4) + read_bits(&p, &idx, 5); + + ratecode = read_bits(&p, &idx, 4); + + // resv(1) + bitrate_low(18) + resv(1) + bitrate_high(12) + read_bits(&p, &idx, 32); + + avctx->has_b_frames = !read_bits(&p, &idx, 1); + + avctx->framerate.num = avctx->time_base.den = avs3_fps_num[ratecode]; + avctx->framerate.den = avctx->time_base.num = avs3_fps_den[ratecode];
ratecode isn't checked, so might overflow the array.
+ + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == 0xB3) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == 0xB6){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + }
What happens if you don't get a sequence header before seeing some frames?
+ } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser;
- Mark
Fix the mail format of reply message from <hbj515 at sina.com> and reset it to the correct thread. same content. At 2020-08-12 05:43:24, "Mark Thompson" <sw@jkqxz.net> wrote:
Typo "paeser" in the title.
On 05/08/2020 17:18, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 186 insertions(+) create mode 100644 libavcodec/avs3_parser.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5a6ea59715..f1512779be 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1053,6 +1053,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..7a7f826c59 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,184 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "parser.h" + +#define SLICE_MAX_START_CODE 0x000001af + +#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define ISUNIT(x) ((x) == 0xB0 || ISPIC(x))
Perhaps give the magic numbers here symbolic constants? (Sequence header, etc.)
Thanks, we will define the constants as bellow: #define AVS3_VIDEO_SEQ_START_CODE 0xB0 #define AVS3_INTRA_PIC_START_CODE 0xB3 #define AVS3_INTER_PIC_START_CODE 0xB6
+ +static av_cold int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size)
This function doesn't look cold.
Sorry, the av_cold will be removed.
+{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state<<8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static unsigned int read_bits(const char** ppbuf, int *pidx, int bits) +{ + const char* p = *ppbuf; + int idx = *pidx; + unsigned int val = 0; + + while (bits) { + bits--; + val = (val << 1) | (((*p) >> idx) & 0x1); + if (--idx < 0) { + idx = 7; + p++; + } + } + + *ppbuf = p; + *pidx = idx; + + return val; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == 0xB0) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 };
Is this meant to be the MPEG-1 frame rate code table? (It looks the same other than num[1], which looks like a typo.) If so, there is a global ff_mpeg12_frame_rate_tab already containing the values.
The AVS3 frame rate code table is not same to the MPEG-1, we will use the next table: const AVRational avs3_frame_rate_tab[16] = { { 0 , 0 }, // forbid { 24000, 1001}, { 24 , 1 }, { 25 , 1 }, { 30000, 1001}, { 30 , 1 }, { 50 , 1 }, { 60000, 1001}, { 60 , 1 }, { 100 , 1 }, { 120 , 1 }, { 200 , 1 }, { 240 , 1 }, { 300 , 1 }, { 0 , 0 }, // reserved { 0 , 0 } // reserved };
+ int profile,ratecode; + const char* p = buf + 4; + int idx = 7; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = read_bits(&p, &idx, 8); + // level(8) + progressive(1) + field(1) + library(2) + resv(1) + width(14) + resv(1) + height(14) + chroma(2) + sampe_precision(3) + read_bits(&p, &idx, 47);
This ad-hoc reimplementation of get_bits does not seem like a good idea - it's reading one bit at a time and lacks any checks for overflow. Please just use get_bits().
Thanks for your advice, we will use get_bits() in the next version.
+ + if (profile == 0x22) { + avctx->pix_fmt = read_bits(&p, &idx, 3) == 1 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + }
Are other values of profile likely to be valid in future, requiring different parsing? Is it worth rejecting these here?
Will be fixed. Thanks.
+ + // resv(1) + aspect(4) + read_bits(&p, &idx, 5); + + ratecode = read_bits(&p, &idx, 4); + + // resv(1) + bitrate_low(18) + resv(1) + bitrate_high(12) + read_bits(&p, &idx, 32); + + avctx->has_b_frames = !read_bits(&p, &idx, 1); + + avctx->framerate.num = avctx->time_base.den = avs3_fps_num[ratecode]; + avctx->framerate.den = avctx->time_base.num = avs3_fps_den[ratecode];
ratecode isn't checked, so might overflow the array.
ratecode is in range of [0, 15], it will not be overflowed for the new table avs3_frame_rate_tab.
+ + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == 0xB3) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == 0xB6){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + }
What happens if you don't get a sequence header before seeing some frames?
Even if the sequence header is not got in the first several frames, it will be decoded again in the next decoding process in libuavs3d.c.
+ } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser;
- Mark _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 75 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 libavformat/avs3dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 26af859a28..b433a6029c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -120,6 +120,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 97fd06debb..2d768b8c88 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -82,6 +82,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..955114dc42 --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,75 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +#define AVS3_SEQ_START_CODE 0x000001b0 +#define AVS3_PIC_I_START_CODE 0x000001b3 +#define AVS3_UNDEF_START_CODE 0x000001b4 +#define AVS3_PIC_PB_START_CODE 0x000001b6 +#define AVS3_VIDEO_EDIT_CODE 0x000001b7 +#define AVS3_PROFILE_JIZHUN 0x20 +#define AVS3_PROFILE_JIZHUN10 0x22 + +static int avs3video_probe(const AVProbeData *p) +{ + uint32_t code= -1; + int pic=0, seq=0, slice_pos = 0; + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + if ((code & 0xffffff00) == 0x100) { + if (code < AVS3_SEQ_START_CODE) { + /* slices have to be consecutive */ + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (code == AVS3_SEQ_START_CODE) { + seq++; + /* check for the only currently supported profile */ + if (*ptr != AVS3_PROFILE_JIZHUN && *ptr != AVS3_PROFILE_JIZHUN10) + return 0; + } else if ((code == AVS3_PIC_I_START_CODE) || + (code == AVS3_PIC_PB_START_CODE)) { + pic++; + } else if ((code == AVS3_UNDEF_START_CODE) || + (code > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) + -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index a60e7d2eb8..dfd56b3fc6 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version <next>: - AudioToolbox output device - MacCaption demuxer +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 7495f35faa..7340bc4a35 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvorbis libvpx @@ -3242,6 +3244,7 @@ libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6379,6 +6382,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d uavs3d uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..f1a0b3c36e 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -86,6 +86,27 @@ AVS2-P2/IEEE1857.4 video decoder wrapper. This decoder allows libavcodec to decode AVS2 streams with davs2 library. +@c man end VIDEO DECODERS + +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + @c man end VIDEO DECODERS @chapter Audio Decoders diff --git a/doc/general.texi b/doc/general.texi index 9b0ee96752..6d673b74e1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f1512779be..491485f3c0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 80f128cade..3d2d0af87a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "uavs3d.h" + +#define UAVS3D_MAX_FRAME_THREADS 48 + +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType IMGTYPE[8] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */ + ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */ + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs3_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs3_fps_den[frm_dec->seqhdr->frame_rate_code]; + avctx->has_b_frames = 1; + avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE }, + { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +}; -- 2.23.0.windows.1
On 8/5/2020 1:18 PM, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c
diff --git a/Changelog b/Changelog index a60e7d2eb8..dfd56b3fc6 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version <next>: - AudioToolbox output device - MacCaption demuxer +- AVS3 video decoder via libuavs3d
version 4.3: diff --git a/configure b/configure index 7495f35faa..7340bc4a35 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvorbis libvpx @@ -3242,6 +3244,7 @@ libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6379,6 +6382,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d uavs3d uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..f1a0b3c36e 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -86,6 +86,27 @@ AVS2-P2/IEEE1857.4 video decoder wrapper.
This decoder allows libavcodec to decode AVS2 streams with davs2 library.
+@c man end VIDEO DECODERS + +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + @c man end VIDEO DECODERS
@chapter Audio Decoders diff --git a/doc/general.texi b/doc/general.texi index 9b0ee96752..6d673b74e1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f1512779be..491485f3c0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 80f128cade..3d2d0af87a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "uavs3d.h" + +#define UAVS3D_MAX_FRAME_THREADS 48 + +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType IMGTYPE[8] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */ + ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */ + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL);
Is it really necessary to destroy and create the decoder context on every seek? It feels slow and inefficient.
+ h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{
Looking at this function, it seems that this decoder would be better implemented using the decoupled input/output AVCodec.receive_frame API instead of the AVCodec.decode one like you're doing here, as it lets you request for packets as you need them. See binkaudio and libdav1d decoders for example implementations: You fetch one packet, keep it around and return frames until it's fully consumed, then attempt to fetch another and repeat the process.
+ UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs3_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs3_fps_den[frm_dec->seqhdr->frame_rate_code]; + avctx->has_b_frames = 1; + avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE },
No need for a custom option and UAVS3DContext field, you have avctx->threads for this. Just add the AV_CODEC_CAP_AUTO_THREADS capability to ff_libuavs3d_decoder and it will default to 0.
+ { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +};
At 2020-08-06 05:21:43, "James Almer" <jamrial@gmail.com> wrote:
On 8/5/2020 1:18 PM, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c
diff --git a/Changelog b/Changelog index a60e7d2eb8..dfd56b3fc6 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version <next>: - AudioToolbox output device - MacCaption demuxer +- AVS3 video decoder via libuavs3d
version 4.3: diff --git a/configure b/configure index 7495f35faa..7340bc4a35 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvorbis libvpx @@ -3242,6 +3244,7 @@ libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6379,6 +6382,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d uavs3d uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..f1a0b3c36e 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -86,6 +86,27 @@ AVS2-P2/IEEE1857.4 video decoder wrapper.
This decoder allows libavcodec to decode AVS2 streams with davs2 library.
+@c man end VIDEO DECODERS + +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + @c man end VIDEO DECODERS
@chapter Audio Decoders diff --git a/doc/general.texi b/doc/general.texi index 9b0ee96752..6d673b74e1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f1512779be..491485f3c0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 80f128cade..3d2d0af87a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "uavs3d.h" + +#define UAVS3D_MAX_FRAME_THREADS 48 + +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType IMGTYPE[8] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */ + ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */ + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL);
Is it really necessary to destroy and create the decoder context on every seek? It feels slow and inefficient.
No, it is redundant. Will be fixed it in the next version. Thanks for pointing out.
+ h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{
Looking at this function, it seems that this decoder would be better implemented using the decoupled input/output AVCodec.receive_frame API instead of the AVCodec.decode one like you're doing here, as it lets you request for packets as you need them.
See binkaudio and libdav1d decoders for example implementations: You fetch one packet, keep it around and return frames until it's fully consumed, then attempt to fetch another and repeat the process.
I am not sure if I correctly understand the difference between AVCodec.receive_frame and AVCodec.decode. It seems that both AVCodec.receive_frame and AVCodec.decode are used in function decode_receive_frame_internal in lavc/decode.c. Once we use the AVCodec.decode, we have to wait until the frame buffer is filled, (which means we got a frame). If we use the AVCodec.receive_frame, we fetch one packet, send it to decoder directly, then request output from the decoder. Considering that the decode_receive_frame function should get one decoded frame data in each receive call, and not all packets in AVS3 contain frame data, these two functions would be equivalent in some respects. I mean, both of them fetch and send packet, and wait for output. Cause AVS3 packets may contain 0 or 1 frame data, the libuavs3d_receive_frame function still needs to wait, and may be exactly the same format as decode_simple_receive_frame, which is the upper encapsulation of AVCodec.decode in lavc/decode.c. So...I haven't got how to optimize this part or receive_frame should be used in which condition. Please tell me more and correct me if there is any problem. Thanks.
+ UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs3_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs3_fps_den[frm_dec->seqhdr->frame_rate_code]; + avctx->has_b_frames = 1; + avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE },
No need for a custom option and UAVS3DContext field, you have avctx->threads for this. Just add the AV_CODEC_CAP_AUTO_THREADS capability to ff_libuavs3d_decoder and it will default to 0.
Will be fixed. Thanks.
+ { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +};
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On 05/08/2020 17:18, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c
... diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "uavs3d.h" + +#define UAVS3D_MAX_FRAME_THREADS 48
This restriction seems weird. Is it reflecting some intrinsic property of the codec, or might it change in future?
+ +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +};
These tables aren't used anywhere.
+ +static const enum AVPictureType IMGTYPE[8] = {
This name is doesn't conform to the usual naming convention. uavs3_frame_types[], maybe?
+ AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +};
What do the other four values in the table mean?
+ +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */
This pointer cast will be undefined behaviour, because the data need not be aligned. Even if it were valid, it's still going to give the wrong answer on a machine with different endianness to the one you tested on. Use AV_RB32() or AV_RL32().
+ ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */
Make symbolic constants for the magic numbers here.
+ data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type];
Is overflow possible?
+ frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth);
Is this copy really required? Decoders will normally allow you to reference the frame they hold internally. Can the call ever fail?
+} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL);
Can this call fail? (For example, if out of memory.)
+ h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data;
No need for explicit casts from void*.
+ int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame
Always allocating here if you have sequence header looks suspicious. What if you don't get any frame output?
+ } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec);
Does this call return any sort of error? More generally, what happens if there is an error in decoding? (For example, because the stream is corrupted.)
+ buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs3_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs3_fps_den[frm_dec->seqhdr->frame_rate_code];
Same comment as in 2/4 about ff_mpeg12_frame_rate_tab[].
+ avctx->has_b_frames = 1;
Always?
+ avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE }, + { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +};
- Mark
Fix the mail format of reply message from <hbj515 at sina.com> and reset it to the correct thread. Same content. At 2020-08-12 06:18:46, "Mark Thompson" <sw@jkqxz.net> wrote:
On 05/08/2020 17:18, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c
... diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..c0d89cd1ce --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "uavs3d.h" + +#define UAVS3D_MAX_FRAME_THREADS 48
This restriction seems weird. Is it reflecting some intrinsic property of the codec, or might it change in future?
The restriction will be removed in the next version.
+ +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +};
These tables aren't used anywhere.
These informations are located in the sequence extension header, and the tables are ID maps between FFMPEG ID ans AVS3 ID. We will add decoding these informations in the next version.
+ +static const enum AVPictureType IMGTYPE[8] = {
This name is doesn't conform to the usual naming convention. uavs3_frame_types[], maybe?
+ AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +};
What do the other four values in the table mean?
Sorry, it is a mistake. It will be fixed.
+ +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */
This pointer cast will be undefined behaviour, because the data need not be aligned. Even if it were valid, it's still going to give the wrong answer on a machine with different endianness to the one you tested on. Use AV_RB32() or AV_RL32().
Thanks, we will use AV_RL32() instead of it.
+ ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */
Make symbolic constants for the magic numbers here.
Thanks, these will be fixed.
+ data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type];
Is overflow possible?
It will be fixed.
+ frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth);
Is this copy really required? Decoders will normally allow you to reference the frame they hold internally.
Can the call ever fail?
Sorry, the decoder will reuse the buffer of dec_frame in the next decoding, so the copy is necessory. If the call "uavs3d_img_cpy_cvt" fail, an error image will be display. The error code is useless, and it not easy for error check with SIMD instructions for various CPUs. We will check if the buffer is vaild in the next version. If not, set the got_pic flag with false.
+} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL);
Can this call fail? (For example, if out of memory.)
Thanks, it will be fixed.
+ h->got_seqhdr = 0; + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data;
No need for explicit casts from void*.
Thanks, it will be fixed.
+ int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame
Always allocating here if you have sequence header looks suspicious. What if you don't get any frame output?
Thanks, we will free the buffer in the next version if no frame is outputed. We don't know whether one frame will be got before decoding, so it is a simple but effective implementation to allocate the buffer once the frame size and pix_fmt are received.
+ } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec);
Does this call return any sort of error?
More generally, what happens if there is an error in decoding? (For example, because the stream is corrupted.)
Thanks, errors will be checked.
+ buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs3_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs3_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs3_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs3_fps_den[frm_dec->seqhdr->frame_rate_code];
Same comment as in 2/4 about ff_mpeg12_frame_rate_tab[].
It will be fixed.
+ avctx->has_b_frames = 1;
Always?
In AVS3, no flag shows whether B frames exist, we will choose the low delay flag for it.
+ avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE }, + { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +};
- Mark _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
From: hwren <hwrenx@126.com> === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS, AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. === Version 4 === Add avs3_parser.h for some reusable definitions in AVS3 Refine avs3_parser.c and libuavs3d.c Fix some vague definitions and potential risks Thanks. hwren (4): lavc: add AVS3 codec id and desc lavc/avs3_parser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avs3_parser.c | 179 ++++++++++++++++++++++++ libavcodec/avs3_parser.h | 64 +++++++++ libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 294 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 69 +++++++++ 15 files changed, 654 insertions(+) create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/avs3_parser.h create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..c5259bf824 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1405,6 +1405,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_PGX, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..47aa0787b6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -242,6 +242,7 @@ enum AVCodecID { AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 179 +++++++++++++++++++++++++++++++++++++++ libavcodec/avs3_parser.h | 64 ++++++++++++++ libavcodec/parsers.c | 1 + 4 files changed, 245 insertions(+) create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/avs3_parser.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..5c031f7777 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1059,6 +1059,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..f04f696a89 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,179 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avs3_parser.h" +#include "get_bits.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + // low_delay + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/avs3_parser.h b/libavcodec/avs3_parser.h new file mode 100644 index 0000000000..afc6d235b9 --- /dev/null +++ b/libavcodec/avs3_parser.h @@ -0,0 +1,64 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 + */ + +#ifndef AVCODEC_AVS3PARSER_H +#define AVCODEC_AVS3PARSER_H + +#include "parser.h" + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || ISPIC(x)) + +static const AVRational avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +#endif /* AVCODEC_AVS3PARSER_H */ diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
hwrenx@126.com:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- diff --git a/libavcodec/avs3_parser.h b/libavcodec/avs3_parser.h new file mode 100644 index 0000000000..afc6d235b9 --- /dev/null +++ b/libavcodec/avs3_parser.h @@ -0,0 +1,64 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 + */ + +#ifndef AVCODEC_AVS3PARSER_H +#define AVCODEC_AVS3PARSER_H + +#include "parser.h" + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || ISPIC(x)) + +static const AVRational avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +#endif /* AVCODEC_AVS3PARSER_H */
None of the stuff in this header file (except the '#include "parser.h"') is parser-specific. It should be part of a generic avs3 header file. And the frame rate table should not be defined in said header file, as this will lead to duplications of the table. If it is used in more than one place, it should be declared via extern in this header file; if not, it should just be declared inside the file that uses it (right now, only the parser uses it). (If it is used in more than one library, then it needs to exist in these libraries separately (or it needs to be avpriv).) - Andreas
At 2020-08-19 01:00:57, "Andreas Rheinhardt" <andreas.rheinhardt@gmail.com> wrote:
hwrenx@126.com:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- diff --git a/libavcodec/avs3_parser.h b/libavcodec/avs3_parser.h new file mode 100644 index 0000000000..afc6d235b9 --- /dev/null +++ b/libavcodec/avs3_parser.h @@ -0,0 +1,64 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 + */ + +#ifndef AVCODEC_AVS3PARSER_H +#define AVCODEC_AVS3PARSER_H + +#include "parser.h" + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || ISPIC(x)) + +static const AVRational avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +#endif /* AVCODEC_AVS3PARSER_H */
None of the stuff in this header file (except the '#include "parser.h"') is parser-specific. It should be part of a generic avs3 header file. And the frame rate table should not be defined in said header file, as this will lead to duplications of the table. If it is used in more than one place, it should be declared via extern in this header file; if not, it should just be declared inside the file that uses it (right now, only the parser uses it). (If it is used in more than one library, then it needs to exist in these libraries separately (or it needs to be avpriv).)
Indeed. There would be a new file as avs3.h including all those common definitions. avs3_parser.h will be removed. Thanks.
- Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 libavformat/avs3dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..8ddab3aee5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -122,6 +122,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..7f41c12d7c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -84,6 +84,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..21c24893a9 --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/avs3_parser.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) \ No newline at end of file -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 294 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 330 insertions(+) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index 1efc768387..91794629e5 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 +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5c031f7777..31d5f39bcd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1032,6 +1032,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..9f82dbde69 --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,294 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3_parser.h" +#include "internal.h" +#include "uavs3d.h" + +static const int uavs3d_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int uavs3d_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int uavs3d_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType uavs3d_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = uavs3d_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (seqh->frame_rate_code >= 16) { + av_log(avctx, AV_LOG_WARNING, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } + avctx->framerate.num = avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = avs3_frame_rate_tab[seqh->frame_rate_code].den; + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + avctx->color_primaries = uavs3d_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = uavs3d_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = uavs3d_color_matrix_tab [seqh->matrix_coefficients]; + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; -- 2.23.0.windows.1
On 8/18/20, hwrenx@126.com <hwrenx@126.com> wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 294 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 330 insertions(+) create mode 100644 libavcodec/libuavs3d.c
diff --git a/Changelog b/Changelog index 1efc768387..91794629e5 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 +- AVS3 video decoder via libuavs3d
version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library.
@c man end VIDEO DECODERS
+@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS
diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5c031f7777..31d5f39bcd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1032,6 +1032,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..9f82dbde69 --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,294 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3_parser.h" +#include "internal.h" +#include "uavs3d.h" + +static const int uavs3d_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int uavs3d_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int uavs3d_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType uavs3d_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = uavs3d_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (seqh->frame_rate_code >= 16) { + av_log(avctx, AV_LOG_WARNING, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } + avctx->framerate.num = avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = avs3_frame_rate_tab[seqh->frame_rate_code].den; + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + avctx->color_primaries = uavs3d_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = uavs3d_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = uavs3d_color_matrix_tab [seqh->matrix_coefficients]; + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10 decoder"),
Please remove "decoder" word from long description. Its unnecessary.
+ .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; -- 2.23.0.windows.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
At 2020-08-19 00:49:12, "Paul B Mahol" <onemda@gmail.com> wrote:
On 8/18/20, hwrenx@126.com <hwrenx@126.com> wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 294 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 330 insertions(+) create mode 100644 libavcodec/libuavs3d.c
diff --git a/Changelog b/Changelog index 1efc768387..91794629e5 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 +- AVS3 video decoder via libuavs3d
version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library.
@c man end VIDEO DECODERS
+@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS
diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5c031f7777..31d5f39bcd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1032,6 +1032,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..9f82dbde69 --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,294 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3_parser.h" +#include "internal.h" +#include "uavs3d.h" + +static const int uavs3d_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int uavs3d_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int uavs3d_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType uavs3d_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = uavs3d_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (seqh->frame_rate_code >= 16) { + av_log(avctx, AV_LOG_WARNING, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } + avctx->framerate.num = avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = avs3_frame_rate_tab[seqh->frame_rate_code].den; + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + avctx->color_primaries = uavs3d_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = uavs3d_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = uavs3d_color_matrix_tab [seqh->matrix_coefficients]; + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10 decoder"),
Please remove "decoder" word from long description. Its unnecessary.
It wiIl be removed in the next version. Thanks.
+ .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; -- 2.23.0.windows.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
From: hwren <hwrenx@126.com> === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS. AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. === Version 4 === Add avs3_parser.h for some reusable definitions in AVS3 Refine avs3_parser.c and libuavs3d.c Fix some vague definitions and potential risks === Version 5 === Fix the wrong codec order in lavc/codec_desc.c Use additional lavc/avs3.h and lavc/avs3.c for common definitions Remove redundant description in the long name of libuavs3d. Update iteration information in lavf/version.h and lavc/version.h. Thanks. hwren (5): lavc: add AVS3 codec id and desc lavc/avs3: add AVS3 related definitions lavc/avs3_parser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 1 + libavcodec/avs3.c | 95 +++++++++++++++ libavcodec/avs3.h | 52 +++++++++ libavcodec/avs3_parser.c | 180 +++++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 241 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavcodec/version.h | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 +++++++++++ libavformat/version.h | 2 +- 18 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..61473178fc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1412,6 +1412,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..47aa0787b6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -242,6 +242,7 @@ enum AVCodecID { AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..8587e36def --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definition + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; \ No newline at end of file diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..9f79adb7bf --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,52 @@ +/* + * AVS3 related definition + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +extern const AVRational ff_avs3_frame_rate_tab[16]; +extern const int ff_avs3_color_primaries_tab[10]; +extern const int ff_avs3_color_transfer_tab[15]; +extern const int ff_avs3_color_matrix_tab[12]; +extern const enum AVPictureType ff_avs3_image_type[4]; + +#endif /* AVCODEC_AVS3_H */ -- 2.23.0.windows.1
hwrenx@126.com (12020-08-19):
From: hwren <hwrenx@126.com>
Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h
Except ff_avs3_frame_rate_tab, all these tables are only used in the decoder. Is there a reason you want them in a separate header? Regards, -- Nicolas George
At 2020-08-19 20:56:27, "Nicolas George" <george@nsup.org> wrote:
hwrenx@126.com (12020-08-19):
From: hwren <hwrenx@126.com>
Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h
Except ff_avs3_frame_rate_tab, all these tables are only used in the decoder. Is there a reason you want them in a separate header?
Considering that the other tables are also declared in AVS3, and they may get reused by other coming encoders or decoders, so I put them together with the ff_avs3_frame_rate_tab in avs3.h. Thanks. Huiwen Ren
Regards,
-- Nicolas George
hwrenx@126.com:
From: hwren <hwrenx@126.com>
Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..8587e36def --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definition + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +};
These two coincide with the values of the constants, so they could be removed.
\ No newline at end of file
This should be fixed. - Andreas
At 2020-08-19 21:15:32, "Andreas Rheinhardt" <andreas.rheinhardt@gmail.com> wrote:
hwrenx@126.com:
From: hwren <hwrenx@126.com>
Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..8587e36def --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definition + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +};
These two coincide with the values of the constants, so they could be removed.
Indeed. But I prefer to keep these mappings in case any side changes their related tables, and ensure the completeness of the group of definitions. These table may also help to check the validity of the type value and describe supported range in AVS3. Thanks.
\ No newline at end of file
This should be fixed.
Will be fixed. Thanks. Regards, Huiwen Ren
- Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On Wed, Aug 19, 2020 at 14:25:53 +0800, hwrenx@126.com wrote:
+ * AVS3 related definition
definitions?
+}; \ No newline at end of file
Please amend a carriage return to the last line.
+ * AVS3 related definition
definitions? Moritz
At 2020-08-19 22:18:52, "Moritz Barsnick" <barsnick@gmx.net> wrote:
On Wed, Aug 19, 2020 at 14:25:53 +0800, hwrenx@126.com wrote:
+ * AVS3 related definition
definitions?
+}; \ No newline at end of file
Please amend a carriage return to the last line.
+ * AVS3 related definition
definitions?
Moritz
Will be corrected. Thanks for pointing out. Regards, Huiwen Ren
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On Thu, Aug 20, 2020 at 13:24:44 +0800, hwren wrote:
At 2020-08-19 22:18:52, "Moritz Barsnick" <barsnick@gmx.net> wrote:
On Wed, Aug 19, 2020 at 14:25:53 +0800, hwrenx@126.com wrote:
+ * AVS3 related definition
definitions?
+}; \ No newline at end of file
Please amend a carriage return to the last line.
+ * AVS3 related definition
definitions?
Moritz
Will be corrected. Thanks for pointing out.
This didn't change in v7. Moritz
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 180 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 182 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e1e0c4629d..4c596515ee 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1061,6 +1061,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..36ca19797d --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,180 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avs3.h" +#include "get_bits.h" +#include "parser.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + // low_delay + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
On Wed, Aug 19, 2020 at 14:25:54 +0800, hwrenx@126.com wrote:
+ for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur;
ffmpeg prefers the "cur++" style (twice in this block, and elsewhere).
+ // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + // low_delay + skip_bits(&gb, 32);
Is "low_delay" part of the skipped bits? The rest already adds up to 32.
+ av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode);
Incorrect indentation. Cheers, Moritz
At 2020-08-19 22:14:04, "Moritz Barsnick" <barsnick@gmx.net> wrote:
On Wed, Aug 19, 2020 at 14:25:54 +0800, hwrenx@126.com wrote:
+ for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur;
ffmpeg prefers the "cur++" style (twice in this block, and elsewhere).
Will be corrected. Thanks.
+ // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + // low_delay + skip_bits(&gb, 32);
Is "low_delay" part of the skipped bits? The rest already adds up to 32.
No it's not...The low_delay is added by mistake. I will remove it in the next version.
+ av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode);
Incorrect indentation.
Will be corrected. Thanks. Cheers, Huiwen Ren
Cheers, Moritz _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On Thu, Aug 20, 2020 at 13:31:12 +0800, hwren wrote:
At 2020-08-19 22:14:04, "Moritz Barsnick" <barsnick@gmx.net> wrote:
ffmpeg prefers the "cur++" style (twice in this block, and elsewhere).
Will be corrected. Thanks.
Is "low_delay" part of the skipped bits? The rest already adds up to 32.
No it's not...The low_delay is added by mistake. I will remove it in the next version.
Incorrect indentation.
Will be corrected. Thanks.
None of these changed in v7. Moritz
At 2020-08-26 19:51:20, "Moritz Barsnick" <barsnick@gmx.net> wrote:
On Thu, Aug 20, 2020 at 13:31:12 +0800, hwren wrote:
At 2020-08-19 22:14:04, "Moritz Barsnick" <barsnick@gmx.net> wrote:
ffmpeg prefers the "cur++" style (twice in this block, and elsewhere).
Will be corrected. Thanks.
Is "low_delay" part of the skipped bits? The rest already adds up to 32.
No it's not...The low_delay is added by mistake. I will remove it in the next version.
Incorrect indentation.
Will be corrected. Thanks.
None of these changed in v7.
Looks like I used a wrong base. I will check them again. Thanks for your mention. Regards, Huiwen Ren
Moritz _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 libavformat/avs3dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..8ddab3aee5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -122,6 +122,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..7f41c12d7c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -84,6 +84,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..af14550b55 --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/avs3.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) \ No newline at end of file diff --git a/libavformat/version.h b/libavformat/version.h index aa309ecc77..146db09d1b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 51 +#define LIBAVFORMAT_VERSION_MINOR 52 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 241 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index 1efc768387..91794629e5 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 +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4c596515ee..5cccc654b3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1034,6 +1034,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..83b873fc1c --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,241 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3.h" +#include "internal.h" +#include "uavs3d.h" + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (seqh->frame_rate_code >= 16) { + av_log(avctx, AV_LOG_WARNING, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } + avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + avctx->color_primaries = ff_avs3_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = ff_avs3_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = ff_avs3_color_matrix_tab [seqh->matrix_coefficients]; + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a3f9f828ee..5bdfdce363 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 100 +#define LIBAVCODEC_VERSION_MINOR 101 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- 2.23.0.windows.1
On Wed, Aug 19, 2020 at 14:25:56 +0800, hwrenx@126.com wrote:
- AV1 Low overhead bitstream format demuxer +- AVS3 video decoder via libuavs3d
I wonder whether the raw demuxer should have been mentioned in its respective patch. Moritz
At 2020-08-19 22:23:07, "Moritz Barsnick" <barsnick@gmx.net> wrote:
On Wed, Aug 19, 2020 at 14:25:56 +0800, hwrenx@126.com wrote:
- AV1 Low overhead bitstream format demuxer +- AVS3 video decoder via libuavs3d
I wonder whether the raw demuxer should have been mentioned in its respective patch.
Yes, I missed it. The demuxer will be mentioned in Changlog in the next version. Thanks. Huiwen Ren
Moritz _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
From: hwren <hwrenx@126.com> === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS. AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. === Version 4 === Add avs3_parser.h for some reusable definitions in AVS3 Refine avs3_parser.c and libuavs3d.c Fix some vague definitions and potential risks === Version 5 === Fix the wrong codec order in lavc/codec_desc.c Use additional lavc/avs3.h and lavc/avs3.c for common definitions Remove redundant description in the long name of libuavs3d. Update iteration information in lavf/version.h and lavc/version.h. === Version 6 === Fix incorrect code style problems. Remove confused comments. Add missing demuxer entry in Changelog. Add value check in lavc/libuavs3d.c Thanks. hwren (5): lavc: add AVS3 codec id and desc lavc/avs3: add AVS3 related definitions lavc/avs3_parser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 2 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 1 + libavcodec/avs3.c | 95 +++++++++++++++ libavcodec/avs3.h | 52 +++++++++ libavcodec/avs3_parser.c | 179 +++++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 241 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavcodec/version.h | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 +++++++++++ libavformat/version.h | 2 +- 18 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..61473178fc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1412,6 +1412,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..47aa0787b6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -242,6 +242,7 @@ enum AVCodecID { AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..411a6c39a0 --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..8653e7c476 --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,52 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define AVS3_ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define AVS3_ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || AVS3_ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +extern const AVRational ff_avs3_frame_rate_tab[16]; +extern const int ff_avs3_color_primaries_tab[10]; +extern const int ff_avs3_color_transfer_tab[15]; +extern const int ff_avs3_color_matrix_tab[12]; +extern const enum AVPictureType ff_avs3_image_type[4]; + +#endif /* AVCODEC_AVS3_H */ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 179 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 181 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e1e0c4629d..4c596515ee 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1061,6 +1061,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..bf97f75db6 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,179 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avs3.h" +#include "get_bits.h" +#include "parser.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (AVS3_ISPIC(buf[cur])){ + cur++; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && AVS3_ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "AVS3 parse seq HDR: profile %d; coded size: %dx%d; frame rate code: %d\n", + profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 libavformat/avs3dec.c diff --git a/Changelog b/Changelog index 1efc768387..f70ed4927a 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 +- AVS3 bitstream format demuxer version 4.3: diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..8ddab3aee5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -122,6 +122,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..7f41c12d7c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -84,6 +84,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..a85f6f6c0b --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/avs3.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (AVS3_ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) \ No newline at end of file diff --git a/libavformat/version.h b/libavformat/version.h index aa309ecc77..146db09d1b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 51 +#define LIBAVFORMAT_VERSION_MINOR 52 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 255 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index f70ed4927a..a0e171d496 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version <next>: - Argonaut Games ASF muxer - AV1 Low overhead bitstream format demuxer - AVS3 bitstream format demuxer +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4c596515ee..5cccc654b3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1034,6 +1034,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..f5a0201fb9 --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,255 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3.h" +#include "internal.h" +#include "uavs3d.h" + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +#define UAVS3D_CHECK_VAILD_RANGE(v, l, r) ((v)>=(l)&&(v)<=(r)) +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (!UAVS3D_CHECK_VAILD_RANGE(seqh->frame_rate_code, 0, 15) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } else { + avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; + } + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + if (!UAVS3D_CHECK_VAILD_RANGE(seqh->colour_primaries, 0, 9) || + !UAVS3D_CHECK_VAILD_RANGE(seqh->transfer_characteristics, 0, 14) || + !UAVS3D_CHECK_VAILD_RANGE(seqh->matrix_coefficients, 0, 11)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid colour description: primaries: %d" + "transfer characteristics: %d" + "matrix coefficients: %d.\n", + seqh->colour_primaries, + seqh->transfer_characteristics, + seqh->matrix_coefficients); + } else { + avctx->color_primaries = ff_avs3_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = ff_avs3_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = ff_avs3_color_matrix_tab [seqh->matrix_coefficients]; + } + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a3f9f828ee..5bdfdce363 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 100 +#define LIBAVCODEC_VERSION_MINOR 101 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> *** Latest changes *** Supplement information in dec_frame, including pkt_pos, pkt_size, coded_picture_number and display_picture_number. Will push if no more comments. Thanks. *** Historical changes *** === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS. AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. === Version 4 === Add avs3_parser.h for some reusable definitions in AVS3 Refine avs3_parser.c and libuavs3d.c Fix some vague definitions and potential risks === Version 5 === Fix the wrong codec order in lavc/codec_desc.c Use additional lavc/avs3.h and lavc/avs3.c for common definitions Remove redundant description in the long name of libuavs3d. Update iteration information in lavf/version.h and lavc/version.h. === Version 6 === Fix incorrect code style problems. Remove confused comments. Add missing demuxer entry in Changelog. Add value check in lavc/libuavs3d.c Thanks. hwren (5): lavc: add AVS3 codec id and desc lavc/avs3: add AVS3 related definition lavc/avs3_parser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 1 + libavcodec/avs3.c | 95 +++++++++++++++ libavcodec/avs3.h | 52 ++++++++ libavcodec/avs3_parser.c | 180 ++++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 248 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavcodec/version.h | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 +++++++++++ libavformat/version.h | 2 +- 18 files changed, 695 insertions(+), 2 deletions(-) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..61473178fc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1412,6 +1412,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..47aa0787b6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -242,6 +242,7 @@ enum AVCodecID { AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..8587e36def --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definition + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; \ No newline at end of file diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..9f79adb7bf --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,52 @@ +/* + * AVS3 related definition + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +extern const AVRational ff_avs3_frame_rate_tab[16]; +extern const int ff_avs3_color_primaries_tab[10]; +extern const int ff_avs3_color_transfer_tab[15]; +extern const int ff_avs3_color_matrix_tab[12]; +extern const enum AVPictureType ff_avs3_image_type[4]; + +#endif /* AVCODEC_AVS3_H */ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 180 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 182 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e1e0c4629d..4c596515ee 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1061,6 +1061,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..36ca19797d --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,180 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avs3.h" +#include "get_bits.h" +#include "parser.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (ISPIC(buf[cur])){ + ++cur; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + // low_delay + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "avs3 parse seq hdr: profile %d; coded wxh: %dx%d; " + "frame_rate_code %d\n", profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 libavformat/avs3dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..8ddab3aee5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -122,6 +122,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..7f41c12d7c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -84,6 +84,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..af14550b55 --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/avs3.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) \ No newline at end of file diff --git a/libavformat/version.h b/libavformat/version.h index aa309ecc77..146db09d1b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 51 +#define LIBAVFORMAT_VERSION_MINOR 52 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 248 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index 1efc768387..91794629e5 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 +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4c596515ee..5cccc654b3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1034,6 +1034,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..d9829f1077 --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,248 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3.h" +#include "internal.h" +#include "uavs3d.h" + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pkt_pos = dec_frame->pkt_pos; + frm->pkt_size = dec_frame->pkt_size; + frm->coded_picture_number = dec_frame->dtr; + frm->display_picture_number = dec_frame->ptr; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + buf_ptr = buf; + buf_end = buf + buf_size; + frm_dec->pkt_pos = avpkt->pos; + frm_dec->pkt_size = avpkt->size; + + while (!finish) { + int bs_len; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (seqh->frame_rate_code >= 16) { + av_log(avctx, AV_LOG_WARNING, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } + avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + avctx->color_primaries = ff_avs3_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = ff_avs3_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = ff_avs3_color_matrix_tab [seqh->matrix_coefficients]; + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a3f9f828ee..5bdfdce363 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 100 +#define LIBAVCODEC_VERSION_MINOR 101 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> *** Latest changes *** Pickup missing changes from previous version. *** Historical changes *** === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS. AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. === Version 4 === Add avs3_parser.h for some reusable definitions in AVS3 Refine avs3_parser.c and libuavs3d.c Fix some vague definitions and potential risks === Version 5 === Fix the wrong codec order in lavc/codec_desc.c Use additional lavc/avs3.h and lavc/avs3.c for common definitions Remove redundant description in the long name of libuavs3d. Update iteration information in lavf/version.h and lavc/version.h. === Version 6 === Fix incorrect code style problems. Remove confused comments. Add missing demuxer entry in Changelog. Add value check in lavc/libuavs3d.c === Version 7 === Supplement information in dec_frame, including pkt_pos, pkt_size, coded_picture_number and display_picture_number. Thanks. hwren (5): lavc: add AVS3 codec id and desc lavc/avs3: add AVS3 related definitions lavc/avs3_parser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 2 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 1 + libavcodec/avs3.c | 95 ++++++++++++++ libavcodec/avs3.h | 52 ++++++++ libavcodec/avs3_parser.c | 179 ++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 262 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavcodec/version.h | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++ libavformat/version.h | 2 +- 18 files changed, 709 insertions(+), 2 deletions(-) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..61473178fc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1412,6 +1412,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..47aa0787b6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -242,6 +242,7 @@ enum AVCodecID { AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..411a6c39a0 --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..8653e7c476 --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,52 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define AVS3_ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define AVS3_ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || AVS3_ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +extern const AVRational ff_avs3_frame_rate_tab[16]; +extern const int ff_avs3_color_primaries_tab[10]; +extern const int ff_avs3_color_transfer_tab[15]; +extern const int ff_avs3_color_matrix_tab[12]; +extern const enum AVPictureType ff_avs3_image_type[4]; + +#endif /* AVCODEC_AVS3_H */ -- 2.23.0.windows.1
On Thu, Aug 27, 2020 at 1:34 PM <hwrenx@126.com> wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 2 + libavcodec/avs3.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/avs3.h | 52 +++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 libavcodec/avs3.c create mode 100644 libavcodec/avs3.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3431ba2dca..e1e0c4629d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -6,6 +6,7 @@ HEADERS = ac3_parser.h \ avcodec.h \ avdct.h \ avfft.h \ + avs3.h \ bsf.h \ codec.h \ codec_desc.h \ @@ -32,6 +33,7 @@ OBJS = ac3_parser.o \ avdct.o \ avpacket.o \ avpicture.o \ + avs3.o \ bitstream.o \ bitstream_filter.o \ bitstream_filters.o \ diff --git a/libavcodec/avs3.c b/libavcodec/avs3.c new file mode 100644 index 0000000000..411a6c39a0 --- /dev/null +++ b/libavcodec/avs3.c @@ -0,0 +1,95 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 "avs3.h" + +const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..8653e7c476 --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,52 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define AVS3_ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define AVS3_ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || AVS3_ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +extern const AVRational ff_avs3_frame_rate_tab[16]; +extern const int ff_avs3_color_primaries_tab[10]; +extern const int ff_avs3_color_transfer_tab[15]; +extern const int ff_avs3_color_matrix_tab[12]; +extern const enum AVPictureType ff_avs3_image_type[4]; + +#endif /* AVCODEC_AVS3_H */ -- 2.23.0.windows.1
Why split two files avs3.c and avs3.h ? I think use one avs3.h file is Ok
From: hwren <hwrenx@126.com> *** Latest changes *** Put AVS3 related definitions in sigle avs3.h file. *** Historical changes *** === Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper. The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream === Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS. AVS3 demuxer only supports raw streams in format <*.avs3>. Fix API function conflict. === Version 3 === Rename parameter names that may be confused with AVS2 Reorder header files. === Version 4 === Add avs3_parser.h for some reusable definitions in AVS3 Refine avs3_parser.c and libuavs3d.c Fix some vague definitions and potential risks === Version 5 === Fix the wrong codec order in lavc/codec_desc.c Use additional lavc/avs3.h and lavc/avs3.c for common definitions Remove redundant description in the long name of libuavs3d. Update iteration information in lavf/version.h and lavc/version.h. === Version 6 === Fix incorrect code style problems. Remove confused comments. Add missing demuxer entry in Changelog. Add value check in lavc/libuavs3d.c === Version 7 === Supplement information in dec_frame, including pkt_pos, pkt_size, coded_picture_number and display_picture_number. === Version 8 === Pickup missing changes from previous version. Thanks. hwren (5): lavc: add AVS3 codec id and desc lavc/avs3: add AVS3 related definitions lavc/avs3_parser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper Changelog | 2 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avs3.h | 118 ++++++++++++++++++ libavcodec/avs3_parser.c | 179 ++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 262 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavcodec/version.h | 4 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++ libavformat/version.h | 2 +- 17 files changed, 679 insertions(+), 3 deletions(-) create mode 100644 libavcodec/avs3.h create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + 2 files changed, 8 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..61473178fc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1412,6 +1412,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..47aa0787b6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -242,6 +242,7 @@ enum AVCodecID { AV_CODEC_ID_RSCC, AV_CODEC_ID_AVS2, AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, AV_CODEC_ID_Y41P = 0x8000, AV_CODEC_ID_AVRP, -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/avs3.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 libavcodec/avs3.h diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..4189d9b583 --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,118 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define AVS3_ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define AVS3_ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || AVS3_ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +static const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +static const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +#endif /* AVCODEC_AVS3_H */ -- 2.23.0.windows.1
On Mon, Aug 31, 2020 at 11:09 PM <hwrenx@126.com> wrote:
From: hwren <hwrenx@126.com>
Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/avs3.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 libavcodec/avs3.h
diff --git a/libavcodec/avs3.h b/libavcodec/avs3.h new file mode 100644 index 0000000000..4189d9b583 --- /dev/null +++ b/libavcodec/avs3.h @@ -0,0 +1,118 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 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 + */ + +#ifndef AVCODEC_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define AVS3_ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define AVS3_ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || AVS3_ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +static const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +static const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +#endif /* AVCODEC_AVS3_H */ --
Now patchset is OK for me, no more comments
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 179 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 181 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ca2e8a2530..5a2ddf8560 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1060,6 +1060,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..bf97f75db6 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,179 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avs3.h" +#include "get_bits.h" +#include "parser.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (AVS3_ISPIC(buf[cur])){ + cur++; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && AVS3_ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "AVS3 parse seq HDR: profile %d; coded size: %dx%d; frame rate code: %d\n", + profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 libavformat/avs3dec.c diff --git a/Changelog b/Changelog index 7467e73306..e68461e85c 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version <next>: - Argonaut Games ASF muxer - AV1 Low overhead bitstream format demuxer - RPZA video encoder +- AVS3 bitstream format demuxer version 4.3: diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..8ddab3aee5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -122,6 +122,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..7f41c12d7c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -84,6 +84,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..a85f6f6c0b --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/avs3.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (AVS3_ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) \ No newline at end of file diff --git a/libavformat/version.h b/libavformat/version.h index 88876aec79..09444893eb 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 51 +#define LIBAVFORMAT_VERSION_MINOR 52 #define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 262 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +- 8 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index e68461e85c..40300d6756 100644 --- a/Changelog +++ b/Changelog @@ -16,6 +16,7 @@ version <next>: - AV1 Low overhead bitstream format demuxer - RPZA video encoder - AVS3 bitstream format demuxer +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 564072053b..c84c857d45 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index d618565347..d68b9c69b7 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5a2ddf8560..d391e1401f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1033,6 +1033,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 729d2fd9ad..0782ac62ec 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -733,6 +733,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..d77cc2192d --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,262 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3.h" +#include "internal.h" +#include "uavs3d.h" + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pkt_pos = dec_frame->pkt_pos; + frm->pkt_size = dec_frame->pkt_size; + frm->coded_picture_number = dec_frame->dtr; + frm->display_picture_number = dec_frame->ptr; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +#define UAVS3D_CHECK_INVALID_RANGE(v, l, r) ((v)<(l)||(v)>(r)) +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + buf_ptr = buf; + buf_end = buf + buf_size; + frm_dec->pkt_pos = avpkt->pos; + frm_dec->pkt_size = avpkt->size; + + while (!finish) { + int bs_len; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (UAVS3D_CHECK_INVALID_RANGE(seqh->frame_rate_code, 0, 15)) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } else { + avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; + } + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + if (UAVS3D_CHECK_INVALID_RANGE(seqh->colour_primaries, 0, 9) || + UAVS3D_CHECK_INVALID_RANGE(seqh->transfer_characteristics, 0, 14) || + UAVS3D_CHECK_INVALID_RANGE(seqh->matrix_coefficients, 0, 11)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid colour description: primaries: %d" + "transfer characteristics: %d" + "matrix coefficients: %d.\n", + seqh->colour_primaries, + seqh->transfer_characteristics, + seqh->matrix_coefficients); + } else { + avctx->color_primaries = ff_avs3_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = ff_avs3_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = ff_avs3_color_matrix_tab [seqh->matrix_coefficients]; + } + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 91e0564570..739caf5c6e 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 101 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 102 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ -- 2.23.0.windows.1
Hello, On Mon, 31 Aug 2020, at 17:07, hwrenx@126.com wrote:
+ --enable-libuavs3d enable AVS3 decoding via libuavs3d [no]
uavs3d is BSD 4-clause, and is therefore not compatible with GPLv2, GPLv3, LGPLv2.1 or LGPLv3 uavs3d should be flagged as "non-free" (and undistributable) then. Best, -- Jean-Baptiste Kempf - President +33 672 704 734
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- libavcodec/Makefile | 1 + libavcodec/avs3_parser.c | 179 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 3 files changed, 181 insertions(+) create mode 100644 libavcodec/avs3_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e1e0c4629d..4c596515ee 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1061,6 +1061,7 @@ OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c new file mode 100644 index 0000000000..bf97f75db6 --- /dev/null +++ b/libavcodec/avs3_parser.c @@ -0,0 +1,179 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "avs3.h" +#include "get_bits.h" +#include "parser.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (AVS3_ISPIC(buf[cur])){ + cur++; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && AVS3_ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "AVS3 parse seq HDR: profile %d; coded size: %dx%d; frame rate code: %d\n", + profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 7d75cea830..aab1d5e3e5 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -28,6 +28,7 @@ extern AVCodecParser ff_ac3_parser; extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 68 ++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 libavformat/avs3dec.c diff --git a/Changelog b/Changelog index 1efc768387..f70ed4927a 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 +- AVS3 bitstream format demuxer version 4.3: diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..8ddab3aee5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -122,6 +122,7 @@ OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..7f41c12d7c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -84,6 +84,7 @@ extern AVInputFormat ff_avr_demuxer; extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c new file mode 100644 index 0000000000..a85f6f6c0b --- /dev/null +++ b/libavformat/avs3dec.c @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavcodec/avs3.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (AVS3_ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) \ No newline at end of file diff --git a/libavformat/version.h b/libavformat/version.h index aa309ecc77..146db09d1b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 51 +#define LIBAVFORMAT_VERSION_MINOR 52 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ -- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 262 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index f70ed4927a..a0e171d496 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version <next>: - Argonaut Games ASF muxer - AV1 Low overhead bitstream format demuxer - AVS3 bitstream format demuxer +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 6faff9bc7b..0fde821742 100755 --- a/configure +++ b/configure @@ -277,6 +277,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1811,6 +1812,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvmaf libvorbis @@ -3253,6 +3255,7 @@ libspeex_encoder_select="audio_frame_queue" libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6416,6 +6419,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714e3c..42b46fe153 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -88,6 +88,27 @@ This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index fac5377504..233f69d349 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4c596515ee..5cccc654b3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1034,6 +1034,7 @@ OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4bd830e5d0..04b990dd37 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -732,6 +732,7 @@ extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000000..d77cc2192d --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,262 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3.h" +#include "internal.h" +#include "uavs3d.h" + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pkt_pos = dec_frame->pkt_pos; + frm->pkt_size = dec_frame->pkt_size; + frm->coded_picture_number = dec_frame->dtr; + frm->display_picture_number = dec_frame->ptr; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +#define UAVS3D_CHECK_INVALID_RANGE(v, l, r) ((v)<(l)||(v)>(r)) +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + buf_ptr = buf; + buf_end = buf + buf_size; + frm_dec->pkt_pos = avpkt->pos; + frm_dec->pkt_size = avpkt->size; + + while (!finish) { + int bs_len; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (UAVS3D_CHECK_INVALID_RANGE(seqh->frame_rate_code, 0, 15)) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } else { + avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; + } + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + if (UAVS3D_CHECK_INVALID_RANGE(seqh->colour_primaries, 0, 9) || + UAVS3D_CHECK_INVALID_RANGE(seqh->transfer_characteristics, 0, 14) || + UAVS3D_CHECK_INVALID_RANGE(seqh->matrix_coefficients, 0, 11)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid colour description: primaries: %d" + "transfer characteristics: %d" + "matrix coefficients: %d.\n", + seqh->colour_primaries, + seqh->transfer_characteristics, + seqh->matrix_coefficients); + } else { + avctx->color_primaries = ff_avs3_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = ff_avs3_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = ff_avs3_color_matrix_tab [seqh->matrix_coefficients]; + } + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a3f9f828ee..5bdfdce363 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 100 +#define LIBAVCODEC_VERSION_MINOR 101 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- 2.23.0.windows.1
Ping. Looking forward to more suggestions :-) At 2020-06-22 21:57:48, hwrenx@126.com wrote:
From: hwren <hwrenx@126.com>
=== Version1 === These patches are to supplement the third generation of Audio Video Coding Standard, part 2: video (AVS3-P2), aka IEEE1857.10, decoding support via libuavs3d wrapper.
The uAVS3d decoder could be found in https://github.com/uavs3/uavs3d AVS3 sample streams could be found in https://github.com/uavs3/avs3stream
=== Version 2 === Fix conflict with CAVS streams. Considering that there is no direct version flag in AVS, AVS3 demuxer only supports raw streams in format <*.avs3>.
Fix API function conflict.
Thanks.
hwren (4): lavc: add AVS3 codec id and desc lavc/avs3_paeser: add avs3 parser lavf/avs3dec: add raw avs3 demuxer lavc,doc: add libuavs3d video decoder wrapper
Changelog | 1 + configure | 4 + doc/decoders.texi | 21 +++ doc/general.texi | 8 ++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avs3_parser.c | 184 +++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/avs3dec.c | 75 +++++++++++ 14 files changed, 590 insertions(+) create mode 100644 libavcodec/avs3_parser.c create mode 100644 libavcodec/libuavs3d.c create mode 100644 libavformat/avs3dec.c
-- 2.23.0.windows.1
From: hwren <hwrenx@126.com> Signed-off-by: hbj <hanbj@pku.edu.cn> Signed-off-by: hwren <hwrenx@126.com> --- Changelog | 1 + configure | 4 + doc/decoders.texi | 21 ++++ doc/general.texi | 8 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/libuavs3d.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 libavcodec/libuavs3d.c diff --git a/Changelog b/Changelog index a60e7d2..dfd56b3 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version <next>: - AudioToolbox output device - MacCaption demuxer +- AVS3 video decoder via libuavs3d version 4.3: diff --git a/configure b/configure index 7495f35..459f3a6 100755 --- a/configure +++ b/configure @@ -274,6 +274,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" libtesseract libtheora libtwolame + libuavs3d libv4l2 libvorbis libvpx @@ -3242,6 +3244,7 @@ libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -6379,6 +6382,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d uavs3d "uavs3d > 1.0.0" uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf diff --git a/doc/decoders.texi b/doc/decoders.texi index 9005714..f1a0b3c 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -87,6 +87,27 @@ AVS2-P2/IEEE1857.4 video decoder wrapper. This decoder allows libavcodec to decode AVS2 streams with davs2 library. @c man end VIDEO DECODERS + +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS @chapter Audio Decoders @c man begin AUDIO DECODERS diff --git a/doc/general.texi b/doc/general.texi index 9b0ee96..6d673b7 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -125,6 +125,14 @@ 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 uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + @float NOTE libdavs2 is under the GNU Public License Version 2 or later (see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f151277..491485f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 80f128c..3d2d0af 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c new file mode 100644 index 0000000..bee09b1 --- /dev/null +++ b/libavcodec/libuavs3d.c @@ -0,0 +1,283 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang <wangzhenyu@pkusz.edu.cn> + * Bingjie Han <hanbj@pkusz.edu.cn> + * 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 "libavutil/opt.h" +#include "avcodec.h" +#include "uavs3d.h" +#include "libavutil/imgutils.h" +#include "internal.h" + +#define UAVS3D_MAX_FRAME_THREADS 48 + +static const int color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType IMGTYPE[8] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +typedef struct UAVS3DContext { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} UAVS3DContext; + + +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + ((*(unsigned int *)data_ptr) != 0xB6010000) && /* P/B picture */ + ((*(unsigned int *)data_ptr) != 0xB3010000) && /* I picture */ + ((*(unsigned int *)data_ptr) != 0xB0010000) && /* sequence header */ + ((*(unsigned int *)data_ptr) != 0x00010000) && /* first slice */ + ((*(unsigned int *)data_ptr) != 0xB1010000)) { /* sequence end */ + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm) { + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pict_type = IMGTYPE[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int uavs3d_init(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + return 0; +} + +static av_cold int uavs3d_end(AVCodecContext *avctx) +{ + UAVS3DContext *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void uavs3d_flush(AVCodecContext * avctx) +{ + UAVS3DContext *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + cdsc.frm_threads = FFMIN(h->frame_threads > 0 ? h->frame_threads : av_cpu_count(), UAVS3D_MAX_FRAME_THREADS); + cdsc.check_md5 = 0; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + } + + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; +} + +static int uavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + UAVS3DContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = (AVFrame*)data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (!buf_size) { + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + buf_ptr = buf; + buf_end = buf + buf_size; + + while (!finish) { + int bs_len; + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + static const int avs2_fps_num[9] = {0, 240000, 24, 25, 30000, 30, 50, 60000, 60 }; + static const int avs2_fps_den[9] = {1, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; + avctx->framerate.num = avs2_fps_num[frm_dec->seqhdr->frame_rate_code]; + avctx->framerate.den = avs2_fps_den[frm_dec->seqhdr->frame_rate_code]; + avctx->has_b_frames = 1; + avctx->pix_fmt = frm_dec->seqhdr->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, frm_dec->seqhdr->horizontal_size, frm_dec->seqhdr->vertical_size); + h->got_seqhdr = 1; + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + return buf_ptr - buf; +} + +#define UAVS3D_OFFSET(x) offsetof(UAVS3DContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "frame_threads", "number of frame-level threads ", UAVS3D_OFFSET(frame_threads), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, UAVS3D_MAX_FRAME_THREADS, VE }, + { NULL } +}; +static const AVClass libuavs3d_class = { + .class_name = "libuavs3d_class", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("uavs3d AVS3-P2/IEEE1857.10 decoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(UAVS3DContext), + .priv_class = &libuavs3d_class, + .init = uavs3d_init, + .close = uavs3d_end, + .decode = uavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .flush = uavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, + + .wrapper_name = "libuavs3d", +}; -- 2.7.4
participants (11)
-
Andreas Rheinhardt -
hwren -
hwrenx@126.com -
James Almer -
Jean-Baptiste Kempf -
Mark Thompson -
Michael Niedermayer -
Moritz Barsnick -
mypopy@gmail.com -
Nicolas George -
Paul B Mahol