[FFmpeg-devel] Add decoding support for the second generation IEEE 1857 video coding standard(AVS2) using uavs2d library(git clones https://github.com/nelvtpkusz/uavs2d.git uavs2d). Support AVS2 in mpegts, flv and mp4 format.

Submitted by Zhenyu Wang on Nov. 8, 2016, 12:57 p.m.

Details

Message ID 1478609833-15193-1-git-send-email-wangzhenyu@pkusz.edu.cn
State New
Headers show

Commit Message

Zhenyu Wang Nov. 8, 2016, 12:57 p.m.
---
 configure                  |   4 +
 libavcodec/Makefile        |   1 +
 libavcodec/allcodecs.c     |   2 +
 libavcodec/avcodec.h       |   1 +
 libavcodec/cavs_parser.c   |   9 ++
 libavcodec/codec_desc.c    |   7 ++
 libavcodec/libuavs2d.c     | 218 +++++++++++++++++++++++++++++++++++++++++++++
 libavformat/allformats.c   |   1 +
 libavformat/cavsvideodec.c |  47 ++++++++++
 libavformat/flv.h          |   1 +
 libavformat/flvdec.c       |   5 ++
 libavformat/isom.c         |   2 +
 libavformat/mpeg.h         |   1 +
 libavformat/mpegts.c       |   1 +
 libavformat/mpegts.h       |   1 +
 libavformat/rawenc.c       |  13 +++
 libavformat/riff.c         |   1 +
 17 files changed, 315 insertions(+)
 create mode 100644 libavcodec/libuavs2d.c

Comments

Steven Liu Nov. 8, 2016, 1:07 p.m.
2016-11-08 20:57 GMT+08:00 Zhenyu Wang <wangzhenyu@pkusz.edu.cn>:

> ---
>  configure                  |   4 +
>  libavcodec/Makefile        |   1 +
>  libavcodec/allcodecs.c     |   2 +
>  libavcodec/avcodec.h       |   1 +
>  libavcodec/cavs_parser.c   |   9 ++
>  libavcodec/codec_desc.c    |   7 ++
>  libavcodec/libuavs2d.c     | 218 ++++++++++++++++++++++++++++++
> +++++++++++++++
>  libavformat/allformats.c   |   1 +
>  libavformat/cavsvideodec.c |  47 ++++++++++
>  libavformat/flv.h          |   1 +
>  libavformat/flvdec.c       |   5 ++
>  libavformat/isom.c         |   2 +
>  libavformat/mpeg.h         |   1 +
>  libavformat/mpegts.c       |   1 +
>  libavformat/mpegts.h       |   1 +
>  libavformat/rawenc.c       |  13 +++
>  libavformat/riff.c         |   1 +
>  17 files changed, 315 insertions(+)
>  create mode 100644 libavcodec/libuavs2d.c
>
> diff --git a/configure b/configure
> index 87b06f1..76f00ed 100755
> --- a/configure
> +++ b/configure
> @@ -269,6 +269,7 @@ External library support:
>    --enable-libx264         enable H.264 encoding via x264 [no]
>    --enable-libx265         enable HEVC encoding via x265 [no]
>    --enable-libxavs         enable AVS encoding via xavs [no]
> +  --enable-libuavs2d       enable AVS2 decoding via uavs2d [no]
>    --enable-libxcb          enable X11 grabbing using XCB [autodetect]
>    --enable-libxcb-shm      enable X11 grabbing shm communication
> [autodetect]
>    --enable-libxcb-xfixes   enable X11 grabbing mouse rendering
> [autodetect]
> @@ -1535,6 +1536,7 @@ EXTERNAL_LIBRARY_LIST="
>      libx264
>      libx265
>      libxavs
> +    libuavs2d
>      libxcb
>      libxcb_shm
>      libxcb_shape
> @@ -2833,6 +2835,7 @@ libx264rgb_encoder_deps="libx264 x264_csp_bgr"
>  libx264rgb_encoder_select="libx264_encoder"
>  libx265_encoder_deps="libx265"
>  libxavs_encoder_deps="libxavs"
> +libuavs2d_decoder_deps="libuavs2d"
>  libxvid_encoder_deps="libxvid"
>  libzvbi_teletext_decoder_deps="libzvbi"
>  videotoolbox_deps="VideoToolbox_VideoToolbox_h"
> @@ -5787,6 +5790,7 @@ enabled libx265           && require_pkg_config x265
> x265.h x265_api_get &&
>                               { check_cpp_condition x265.h "X265_BUILD >=
> 68" ||
>                                 die "ERROR: libx265 version must be >=
> 68."; }
>  enabled libxavs           && require libxavs xavs.h xavs_encoder_encode
> -lxavs
> +enabled libuavs2d         && require libuavs2d uavs2d.h uavs2d_lib_decode
> -luavs2d
>  enabled libxvid           && require libxvid xvid.h xvid_global -lxvidcore
>  enabled libzimg           && require_pkg_config zimg zimg.h
> zimg_get_api_version
>  enabled libzmq            && require_pkg_config libzmq zmq.h zmq_ctx_new
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index f1d5bf1..ca9282d 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -910,6 +910,7 @@ OBJS-$(CONFIG_LIBX262_ENCODER)            += libx264.o
>  OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
>  OBJS-$(CONFIG_LIBX265_ENCODER)            += libx265.o
>  OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
> +OBJS-$(CONFIG_LIBUAVS2D_DECODER)          += libuavs2d.o
>  OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
>  OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o ass.o
>
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index ada9481..9afa3e8 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -622,6 +622,7 @@ void avcodec_register_all(void)
>      REGISTER_ENCODER(LIBX264RGB,        libx264rgb);
>      REGISTER_ENCODER(LIBX265,           libx265);
>      REGISTER_ENCODER(LIBXAVS,           libxavs);
> +    REGISTER_DECODER(LIBUAVS2D,         libuavs2d);
>      REGISTER_ENCODER(LIBXVID,           libxvid);
>      REGISTER_DECODER(LIBZVBI_TELETEXT,  libzvbi_teletext);
>
> @@ -670,6 +671,7 @@ void avcodec_register_all(void)
>      REGISTER_PARSER(ADX,                adx);
>      REGISTER_PARSER(BMP,                bmp);
>      REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
> +    REGISTER_PARSER(CAVS2VIDEO,         cavs2video);
>      REGISTER_PARSER(COOK,               cook);
>      REGISTER_PARSER(DCA,                dca);
>      REGISTER_PARSER(DIRAC,              dirac);
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 211112f..9c0a4bf 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -282,6 +282,7 @@ enum AVCodecID {
>      AV_CODEC_ID_KMVC,
>      AV_CODEC_ID_FLASHSV,
>      AV_CODEC_ID_CAVS,
> +    AV_CODEC_ID_CAVS2,
>      AV_CODEC_ID_JPEG2000,
>      AV_CODEC_ID_VMNC,
>      AV_CODEC_ID_VP5,
> diff --git a/libavcodec/cavs_parser.c b/libavcodec/cavs_parser.c
> index 6067a39..a2cef8b 100644
> --- a/libavcodec/cavs_parser.c
> +++ b/libavcodec/cavs_parser.c
> @@ -104,3 +104,12 @@ AVCodecParser ff_cavsvideo_parser = {
>      .parser_close   = ff_parse_close,
>      .split          = ff_mpeg4video_split,
>  };
> +
> +AVCodecParser ff_cavs2video_parser = {
> +    .codec_ids      = { AV_CODEC_ID_CAVS2 },
> +    .priv_data_size = sizeof(ParseContext),
> +    .parser_parse   = cavsvideo_parse,
> +    .parser_close   = ff_parse_close,
> +    .split          = ff_mpeg4video_split,
> +};
> +
> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
> index 9dbe2dc..c510a4d 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -601,6 +601,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
>          .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
>      },
>      {
> +        .id        = AV_CODEC_ID_CAVS2,
> +        .type      = AVMEDIA_TYPE_VIDEO,
> +        .name      = "cavs2",
> +        .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS2 (Audio Video
> Standard)"),
> +        .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
> +    },
> +    {
>          .id        = AV_CODEC_ID_JPEG2000,
>          .type      = AVMEDIA_TYPE_VIDEO,
>          .name      = "jpeg2000",
> diff --git a/libavcodec/libuavs2d.c b/libavcodec/libuavs2d.c
> new file mode 100644
> index 0000000..0e80afd
> --- /dev/null
> +++ b/libavcodec/libuavs2d.c
> @@ -0,0 +1,218 @@
> +/*
> + * AVS2 decoding using the uavs2d library
> + * Copyright (C) 2016 uavs2d project,
> + * National Engineering Laboratory for Video Technology(Shenzhen),
> + * Digital Media R&D Center at Peking University Shenzhen Graduate
> School, China
> + *
> + * Z.Y. Wang <wangzhenyu@pkusz.edu.cn>
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> + */
> +
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/common.h"
> +#include "libavutil/avutil.h"
> +#include "avcodec.h"
> +#include "uavs2d.h"
> +#include "libavutil/imgutils.h"
> +#include "internal.h"
> +
> +
> +const enum AVPictureType IMGTYPE[8] = {
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_I,
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_P,
> +    AV_PICTURE_TYPE_P,
> +    AV_PICTURE_TYPE_B
> +};
> +
> +typedef struct UAVS2DContext {
> +    AVCodecContext *avctx;
> +    void *dec_handle;
> +    avs2_frame_t dec_frame;
> +    int got_seqhdr;
> +} UAVS2DContext;
> +
> +
> +static int 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) != 0xB1010000)) { /* sequence end */
> +        data_ptr++;
> +        count--;
> +    }
> +
> +    if (count >= 4) {
> +        *left = count;
> +        return 1;
> +    }
> +
> +    return 0;
> +}
> +
> +
> +static int ff_uavs2d_init(AVCodecContext *avctx)
> +{
> +    UAVS2DContext *h = avctx->priv_data;
> +    h->dec_handle = uavs2d_lib_create(1, 1);
> +    h->dec_frame.i_output_type = AVS2_OUT_I420;
> +    h->got_seqhdr = 0;
> +
> +    avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
> +    return 0;
> +}
> +
> +static int ff_uavs2d_end(AVCodecContext *avctx)
> +{
> +    UAVS2DContext *h = avctx->priv_data;
> +    uavs2d_lib_destroy(h->dec_handle);
> +    h->got_seqhdr = 0;
> +    return 0;
> +}
> +
> +static void uavs2d_flush(AVCodecContext * avctx)
> +{
> +    UAVS2DContext *h = avctx->priv_data;
> +    h->dec_frame.bs_len = -1;
> +
> +    do {
> +        uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
> +    } while (h->dec_frame.dec_stats == AVS2_TYPE_DECODED);
> +
> +    h->got_seqhdr = 0;
> +
> +    uavs2d_lib_destroy(h->dec_handle);
> +    h->got_seqhdr = 0;
> +    h->dec_handle = uavs2d_lib_create(1, 1);
> +    h->dec_frame.i_output_type = AVS2_OUT_I420;
> +}
> +
> +static int uavs2d_decode_frame(AVCodecContext *avctx, void *data, int
> *got_frame, AVPacket *avpkt)
> +{
> +    UAVS2DContext *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;
> +
> +    if (buf_size == 0) {
> +        if (h->got_seqhdr) {
> +            if (frm->data[0] == NULL && (ret = ff_get_buffer(avctx, frm,
> 0)) < 0) {
> +                return ret;
> +            }
> +            h->dec_frame.bs_len = -1;
> +            h->dec_frame.p_buf_y = frm->data[0];
> +            h->dec_frame.p_buf_u = frm->data[1];
> +            h->dec_frame.p_buf_v = frm->data[2];
> +            h->dec_frame.i_stride = frm->linesize[0];
> +            h->dec_frame.i_stridec = frm->linesize[1];
> +            uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
> +            if (h->dec_frame.dec_stats == AVS2_TYPE_DECODED) {
> +                *got_frame = 1;
> +                frm->pts = h->dec_frame.pts;
> +                frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
> +            }
> +        }
> +        return 0;
> +    }
> +
> +    buf_ptr = buf;
> +    buf_end = buf + buf_size;
> +
> +    while (finish == 0) {
> +        if (find_next_start_code(buf_ptr, buf_end - buf_ptr,
> &left_bytes)) {
> +            h->dec_frame.bs_len = buf_end - buf_ptr - left_bytes;
> +        } else {
> +            h->dec_frame.bs_len = buf_end - buf_ptr;
> +            finish = 1;
> +        }
> +        h->dec_frame.bs_buf = (uint8_t*)buf_ptr;
> +        h->dec_frame.pts = avpkt->pts;
> +
> +        buf_ptr += h->dec_frame.bs_len;
> +
> +        if (h->got_seqhdr && frm->data[0]== NULL && (ret =
> ff_get_buffer(avctx, frm, 0)) < 0) {
> +            return ret;
> +        }
> +        h->dec_frame.p_buf_y = frm->data[0];
> +        h->dec_frame.p_buf_u = frm->data[1];
> +        h->dec_frame.p_buf_v = frm->data[2];
> +        h->dec_frame.i_stride = frm->linesize[0];
> +        h->dec_frame.i_stridec = frm->linesize[1];
> +
> +        uavs2d_lib_decode(h->dec_handle, &h->dec_frame);
> +
> +        switch (h->dec_frame.dec_stats) {
> +        case AVS2_TYPE_DECODED:   /* decode one frame */
> +            *got_frame = 1;
> +            finish = 1;
> +            frm->pts = h->dec_frame.pts;
> +            frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
> +            break;
> +        case AVS2_TYPE_ERROR:     /* error, current or next frame was not
> decoded */
> +            av_log(h->avctx, AV_LOG_WARNING, "decode error\n");
> +            break;
> +        case AVS2_TYPE_DROP:     /* error, current or next frame was not
> decoded */
> +            av_log(h->avctx, AV_LOG_WARNING, "DROP non-RA frame\n");
> +            break;
> +        case AVS2_TYPE_SEQ:       /* sequence header was decoded */
> +            if (avctx->width != h->dec_frame.info.img_width ||
> avctx->height != h->dec_frame.info.img_height) {
> +                static const int avs2_fps_num[8] = { 240000, 24, 25,
> 30000, 30, 50, 60000, 60 };
> +                static const int avs2_fps_den[8] = {   1001,  1,  1,
> 1001,  1,  1,  1001,  1 };
> +                av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d ->
> %dx%d\n", avctx->width, avctx->height, h->dec_frame.info.img_width,
> h->dec_frame.info.img_height);
> +                ret = ff_set_dimensions(avctx,
> h->dec_frame.info.img_width, h->dec_frame.info.img_height);
> +
> +                if (ret < 0) {
> +                    return ret;
> +                }
> +                avctx->framerate.num = avs2_fps_num[h->dec_frame.
> info.frame_rate_code];
> +                avctx->framerate.den = avs2_fps_den[h->dec_frame.
> info.frame_rate_code];
> +            }
> +            h->got_seqhdr = 1;
> +        }
> +     }
> +
> +    return buf_ptr - buf;
> +}
> +
> +AVCodec ff_libuavs2d_decoder = {
> +    .name           = "uavs2d",
> +    .long_name      = NULL_IF_CONFIG_SMALL("Decoder for Chinese AVS2"),
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_CAVS2,
> +    .priv_data_size = sizeof(UAVS2DContext),
> +    .init           = ff_uavs2d_init,
> +    .close          = ff_uavs2d_end,
> +    .decode         = uavs2d_decode_frame,
> +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
> +    .flush          = uavs2d_flush,
> +    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
> +                                                     AV_PIX_FMT_NONE },
> +};
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 6a216ef..7f7a755 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -95,6 +95,7 @@ void av_register_all(void)
>      REGISTER_DEMUXER (C93,              c93);
>      REGISTER_MUXDEMUX(CAF,              caf);
>      REGISTER_MUXDEMUX(CAVSVIDEO,        cavsvideo);
> +    REGISTER_MUXDEMUX(CAVS2VIDEO,       cavs2video);
>      REGISTER_DEMUXER (CDG,              cdg);
>      REGISTER_DEMUXER (CDXL,             cdxl);
>      REGISTER_DEMUXER (CINE,             cine);
> diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c
> index b4da58e..8d6325d 100644
> --- a/libavformat/cavsvideodec.c
> +++ b/libavformat/cavsvideodec.c
> @@ -19,6 +19,7 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
>   */
>
> +#include <ctype.h>
>  #include "avformat.h"
>  #include "rawdec.h"
>  #include "libavcodec/internal.h"
> @@ -66,4 +67,50 @@ static int cavsvideo_probe(AVProbeData *p)
>      return 0;
>  }
>
> +static int cavs2video_probe(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 < CAVS_SEQ_START_CODE) {
> +                /* slices have to be consecutive */
> +                if(code < slice_pos)
> +                    return 0;
> +                slice_pos = code;
> +            } else {
> +                slice_pos = 0;
> +            }
> +            if (code == CAVS_SEQ_START_CODE) {
> +                seq++;
> +                /* check for the only currently supported profile */
> +                if (*ptr != CAVS_PROFILE_JIZHUN)
> +                    return 0;
> +            } else if ((code == CAVS_PIC_I_START_CODE) ||
> +                       (code == CAVS_PIC_PB_START_CODE)) {
> +                pic++;
> +            } else if ((code == CAVS_UNDEF_START_CODE) ||
> +                       (code >  CAVS_VIDEO_EDIT_CODE)) {
> +                return 0;
> +            }
> +        }
> +    }
> +    if(seq && pic) {
> +        const char *str = p->filename + strlen(p->filename) - 5;
> +        if (tolower(str[0]) == 'c' && tolower(str[1]) == 'a' &&
> tolower(str[2]) == 'v' &&tolower(str[3]) == 's' && str[4] == '2') {
> +            ret = AVPROBE_SCORE_EXTENSION+2;
> +        }
> +    }
> +    return ret;
> +}
> +
> +
> +
>  FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video
> Standard)", cavsvideo_probe, NULL, AV_CODEC_ID_CAVS)
> +
> +FF_DEF_RAWVIDEO_DEMUXER(cavs2video, "raw Chinese AVS2 (Audio Video
> Standard)", cavs2video_probe, "cavs2", AV_CODEC_ID_CAVS2)
> +
> diff --git a/libavformat/flv.h b/libavformat/flv.h
> index df5ce3d..78ff1b3 100644
> --- a/libavformat/flv.h
> +++ b/libavformat/flv.h
> @@ -109,6 +109,7 @@ enum {
>      FLV_CODECID_H264    = 7,
>      FLV_CODECID_REALH263= 8,
>      FLV_CODECID_MPEG4   = 9,
> +    FLV_CODECID_CAVS2   = 10,
>  };
>
>  enum {
> diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
> index e53c345..e85fcbc 100644
> --- a/libavformat/flvdec.c
> +++ b/libavformat/flvdec.c
> @@ -281,6 +281,8 @@ static int flv_same_video_codec(AVCodecParameters
> *vpar, int flags)
>          return vpar->codec_id == AV_CODEC_ID_VP6A;
>      case FLV_CODECID_H264:
>          return vpar->codec_id == AV_CODEC_ID_H264;
> +    case FLV_CODECID_CAVS2:
> +        return vpar->codec_id == AV_CODEC_ID_CAVS2;
>      default:
>          return vpar->codec_tag == flv_codecid;
>      }
> @@ -325,6 +327,9 @@ static int flv_set_video_codec(AVFormatContext *s,
> AVStream *vstream,
>      case FLV_CODECID_MPEG4:
>          par->codec_id = AV_CODEC_ID_MPEG4;
>          return 3;
> +    case FLV_CODECID_CAVS2:
> +        par->codec_id = AV_CODEC_ID_CAVS2;
> +        break;
>      default:
>          avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
>          par->codec_tag = flv_codecid;
> diff --git a/libavformat/isom.c b/libavformat/isom.c
> index 1fa46bd..b0bb8c3 100644
> --- a/libavformat/isom.c
> +++ b/libavformat/isom.c
> @@ -36,6 +36,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
>      { AV_CODEC_ID_MPEG4       , 0x20 },
>      { AV_CODEC_ID_H264        , 0x21 },
>      { AV_CODEC_ID_HEVC        , 0x23 },
> +    { AV_CODEC_ID_CAVS2       , 0x24 },
>      { AV_CODEC_ID_AAC         , 0x40 },
>      { AV_CODEC_ID_MP4ALS      , 0x40 }, /* 14496-3 ALS */
>      { AV_CODEC_ID_MPEG2VIDEO  , 0x61 }, /* MPEG-2 Main */
> @@ -244,6 +245,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
>
>      { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */
>      { AV_CODEC_ID_CAVS, MKTAG('a', 'v', 's', '2') },
> +    { AV_CODEC_ID_CAVS2, MKTAG('c', 'a', 'v', '2') },
>
>      { AV_CODEC_ID_DIRAC,     MKTAG('d', 'r', 'a', 'c') },
>      { AV_CODEC_ID_DNXHD,     MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */
> diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h
> index 617e36c..faa875e 100644
> --- a/libavformat/mpeg.h
> +++ b/libavformat/mpeg.h
> @@ -56,6 +56,7 @@
>  #define STREAM_TYPE_VIDEO_MPEG4     0x10
>  #define STREAM_TYPE_VIDEO_H264      0x1b
>  #define STREAM_TYPE_VIDEO_CAVS      0x42
> +#define STREAM_TYPE_VIDEO_CAVS2     0x52
>
>  #define STREAM_TYPE_AUDIO_AC3       0x81
>
> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
> index fad10c6..2dbd460 100644
> --- a/libavformat/mpegts.c
> +++ b/libavformat/mpegts.c
> @@ -705,6 +705,7 @@ static const StreamType ISO_types[] = {
>      { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000   },
>      { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC       },
>      { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS       },
> +    { 0x52, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS2      },
>      { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC      },
>      { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1        },
>      { 0 },
> diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
> index 272e2be..d0f7033 100644
> --- a/libavformat/mpegts.h
> +++ b/libavformat/mpegts.h
> @@ -55,6 +55,7 @@
>  #define STREAM_TYPE_VIDEO_H264      0x1b
>  #define STREAM_TYPE_VIDEO_HEVC      0x24
>  #define STREAM_TYPE_VIDEO_CAVS      0x42
> +#define STREAM_TYPE_VIDEO_CAVS2     0x52
>  #define STREAM_TYPE_VIDEO_VC1       0xea
>  #define STREAM_TYPE_VIDEO_DIRAC     0xd1
>
> diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
> index 730e99a..bd0d415 100644
> --- a/libavformat/rawenc.c
> +++ b/libavformat/rawenc.c
> @@ -104,6 +104,19 @@ AVOutputFormat ff_cavsvideo_muxer = {
>  };
>  #endif
>
> +#if CONFIG_CAVS2VIDEO_MUXER
> +AVOutputFormat ff_cavs2video_muxer = {
> +    .name              = "cavs2video",
> +    .long_name         = NULL_IF_CONFIG_SMALL("raw Chinese AVS2 (Audio
> Video Standard) video"),
> +    .extensions        = "cavs2",
> +    .audio_codec       = AV_CODEC_ID_NONE,
> +    .video_codec       = AV_CODEC_ID_CAVS2,
> +    .write_header      = force_one_stream,
> +    .write_packet      = ff_raw_write_packet,
> +    .flags             = AVFMT_NOTIMESTAMPS,
> +};
> +#endif
> +
>  #if CONFIG_DATA_MUXER
>  AVOutputFormat ff_data_muxer = {
>      .name              = "data",
> diff --git a/libavformat/riff.c b/libavformat/riff.c
> index 3c5a37c..ec2d1cf 100644
> --- a/libavformat/riff.c
> +++ b/libavformat/riff.c
> @@ -362,6 +362,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
>      { AV_CODEC_ID_ZMBV,         MKTAG('Z', 'M', 'B', 'V') },
>      { AV_CODEC_ID_KMVC,         MKTAG('K', 'M', 'V', 'C') },
>      { AV_CODEC_ID_CAVS,         MKTAG('C', 'A', 'V', 'S') },
> +    { AV_CODEC_ID_CAVS2,        MKTAG('C', 'A', 'V', '2') },
>      { AV_CODEC_ID_JPEG2000,     MKTAG('m', 'j', 'p', '2') },
>      { AV_CODEC_ID_JPEG2000,     MKTAG('M', 'J', '2', 'C') },
>      { AV_CODEC_ID_JPEG2000,     MKTAG('L', 'J', '2', 'C') },
> --
> 2.7.4
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Aha, AVS2 in China is used by broadcast television, this is a important
decoder.
Steven Liu Nov. 8, 2016, 1:12 p.m.
2016-11-08 21:07 GMT+08:00 Steven Liu <lingjiujianke@gmail.com>:

>
>
> 2016-11-08 20:57 GMT+08:00 Zhenyu Wang <wangzhenyu@pkusz.edu.cn>:
>

https://ffmpeg.org/developer.html

Keep the main commit message short with an extended description below.

The commit message should have a short first line in the form of a ‘topic:
short description’ as a header, separated by a newline from the body
consisting of an explanation of why the change is necessary. If the commit
fixes a known bug on the bug tracker, the commit message should include its
bug ID. Referring to the issue on the bug tracker does not exempt you from
writing an excerpt of the bug in the commit message.


> ---
>>  configure                  |   4 +
>>  libavcodec/Makefile        |   1 +
>>  libavcodec/allcodecs.c     |   2 +
>>  libavcodec/avcodec.h       |   1 +
>>  libavcodec/cavs_parser.c   |   9 ++
>>  libavcodec/codec_desc.c    |   7 ++
>>  libavcodec/libuavs2d.c     | 218 ++++++++++++++++++++++++++++++
>> +++++++++++++++
>>  libavformat/allformats.c   |   1 +
>>  libavformat/cavsvideodec.c |  47 ++++++++++
>>  libavformat/flv.h          |   1 +
>>  libavformat/flvdec.c       |   5 ++
>>  libavformat/isom.c         |   2 +
>>  libavformat/mpeg.h         |   1 +
>>  libavformat/mpegts.c       |   1 +
>>  libavformat/mpegts.h       |   1 +
>>  libavformat/rawenc.c       |  13 +++
>>  libavformat/riff.c         |   1 +
>>  17 files changed, 315 insertions(+)
>>  create mode 100644 libavcodec/libuavs2d.c
>>
>> diff --git a/configure b/configure
>> index 87b06f1..76f00ed 100755
>> --- a/configure
>> +++ b/configure
>> @@ -269,6 +269,7 @@ External library support:
>>    --enable-libx264         enable H.264 encoding via x264 [no]
>>    --enable-libx265         enable HEVC encoding via x265 [no]
>>    --enable-libxavs         enable AVS encoding via xavs [no]
>> +  --enable-libuavs2d       enable AVS2 decoding via uavs2d [no]
>>    --enable-libxcb          enable X11 grabbing using XCB [autodetect]
>>    --enable-libxcb-shm      enable X11 grabbing shm communication
>> [autodetect]
>>    --enable-libxcb-xfixes   enable X11 grabbing mouse rendering
>> [autodetect]
>> @@ -1535,6 +1536,7 @@ EXTERNAL_LIBRARY_LIST="
>>      libx264
>>      libx265
>>      libxavs
>> +    libuavs2d
>>      libxcb
>>      libxcb_shm
>>      libxcb_shape
>> @@ -2833,6 +2835,7 @@ libx264rgb_encoder_deps="libx264 x264_csp_bgr"
>>  libx264rgb_encoder_select="libx264_encoder"
>>  libx265_encoder_deps="libx265"
>>  libxavs_encoder_deps="libxavs"
>> +libuavs2d_decoder_deps="libuavs2d"
>>  libxvid_encoder_deps="libxvid"
>>  libzvbi_teletext_decoder_deps="libzvbi"
>>  videotoolbox_deps="VideoToolbox_VideoToolbox_h"
>> @@ -5787,6 +5790,7 @@ enabled libx265           && require_pkg_config
>> x265 x265.h x265_api_get &&
>>                               { check_cpp_condition x265.h "X265_BUILD >=
>> 68" ||
>>                                 die "ERROR: libx265 version must be >=
>> 68."; }
>>  enabled libxavs           && require libxavs xavs.h xavs_encoder_encode
>> -lxavs
>> +enabled libuavs2d         && require libuavs2d uavs2d.h
>> uavs2d_lib_decode -luavs2d
>>  enabled libxvid           && require libxvid xvid.h xvid_global
>> -lxvidcore
>>  enabled libzimg           && require_pkg_config zimg zimg.h
>> zimg_get_api_version
>>  enabled libzmq            && require_pkg_config libzmq zmq.h zmq_ctx_new
>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>> index f1d5bf1..ca9282d 100644
>> --- a/libavcodec/Makefile
>> +++ b/libavcodec/Makefile
>> @@ -910,6 +910,7 @@ OBJS-$(CONFIG_LIBX262_ENCODER)            +=
>> libx264.o
>>  OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
>>  OBJS-$(CONFIG_LIBX265_ENCODER)            += libx265.o
>>  OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
>> +OBJS-$(CONFIG_LIBUAVS2D_DECODER)          += libuavs2d.o
>>  OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
>>  OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o ass.o
>>
>> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
>> index ada9481..9afa3e8 100644
>> --- a/libavcodec/allcodecs.c
>> +++ b/libavcodec/allcodecs.c
>> @@ -622,6 +622,7 @@ void avcodec_register_all(void)
>>      REGISTER_ENCODER(LIBX264RGB,        libx264rgb);
>>      REGISTER_ENCODER(LIBX265,           libx265);
>>      REGISTER_ENCODER(LIBXAVS,           libxavs);
>> +    REGISTER_DECODER(LIBUAVS2D,         libuavs2d);
>>      REGISTER_ENCODER(LIBXVID,           libxvid);
>>      REGISTER_DECODER(LIBZVBI_TELETEXT,  libzvbi_teletext);
>>
>> @@ -670,6 +671,7 @@ void avcodec_register_all(void)
>>      REGISTER_PARSER(ADX,                adx);
>>      REGISTER_PARSER(BMP,                bmp);
>>      REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
>> +    REGISTER_PARSER(CAVS2VIDEO,         cavs2video);
>>      REGISTER_PARSER(COOK,               cook);
>>      REGISTER_PARSER(DCA,                dca);
>>      REGISTER_PARSER(DIRAC,              dirac);
>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>> index 211112f..9c0a4bf 100644
>> --- a/libavcodec/avcodec.h
>> +++ b/libavcodec/avcodec.h
>> @@ -282,6 +282,7 @@ enum AVCodecID {
>>      AV_CODEC_ID_KMVC,
>>      AV_CODEC_ID_FLASHSV,
>>      AV_CODEC_ID_CAVS,
>> +    AV_CODEC_ID_CAVS2,
>>      AV_CODEC_ID_JPEG2000,
>>      AV_CODEC_ID_VMNC,
>>      AV_CODEC_ID_VP5,
>> diff --git a/libavcodec/cavs_parser.c b/libavcodec/cavs_parser.c
>> index 6067a39..a2cef8b 100644
>> --- a/libavcodec/cavs_parser.c
>> +++ b/libavcodec/cavs_parser.c
>> @@ -104,3 +104,12 @@ AVCodecParser ff_cavsvideo_parser = {
>>      .parser_close   = ff_parse_close,
>>      .split          = ff_mpeg4video_split,
>>  };
>> +
>> +AVCodecParser ff_cavs2video_parser = {
>> +    .codec_ids      = { AV_CODEC_ID_CAVS2 },
>> +    .priv_data_size = sizeof(ParseContext),
>> +    .parser_parse   = cavsvideo_parse,
>> +    .parser_close   = ff_parse_close,
>> +    .split          = ff_mpeg4video_split,
>> +};
>> +
>> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
>> index 9dbe2dc..c510a4d 100644
>> --- a/libavcodec/codec_desc.c
>> +++ b/libavcodec/codec_desc.c
>> @@ -601,6 +601,13 @@ static const AVCodecDescriptor codec_descriptors[] =
>> {
>>          .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
>>      },
>>      {
>> +        .id        = AV_CODEC_ID_CAVS2,
>> +        .type      = AVMEDIA_TYPE_VIDEO,
>> +        .name      = "cavs2",
>> +        .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS2 (Audio Video
>> Standard)"),
>> +        .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
>> +    },
>> +    {
>>          .id        = AV_CODEC_ID_JPEG2000,
>>          .type      = AVMEDIA_TYPE_VIDEO,
>>          .name      = "jpeg2000",
>> diff --git a/libavcodec/libuavs2d.c b/libavcodec/libuavs2d.c
>> new file mode 100644
>> index 0000000..0e80afd
>> --- /dev/null
>> +++ b/libavcodec/libuavs2d.c
>> @@ -0,0 +1,218 @@
>> +/*
>> + * AVS2 decoding using the uavs2d library
>> + * Copyright (C) 2016 uavs2d project,
>> + * National Engineering Laboratory for Video Technology(Shenzhen),
>> + * Digital Media R&D Center at Peking University Shenzhen Graduate
>> School, China
>> + *
>> + * Z.Y. Wang <wangzhenyu@pkusz.edu.cn>
>> + *
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + *
>> + * FFmpeg is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with FFmpeg; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> 02110-1301 USA
>> + */
>> +
>> +
>> +#include "libavutil/avassert.h"
>> +#include "libavutil/common.h"
>> +#include "libavutil/avutil.h"
>> +#include "avcodec.h"
>> +#include "uavs2d.h"
>> +#include "libavutil/imgutils.h"
>> +#include "internal.h"
>> +
>> +
>> +const enum AVPictureType IMGTYPE[8] = {
>> +    AV_PICTURE_TYPE_NONE,
>> +    AV_PICTURE_TYPE_I,
>> +    AV_PICTURE_TYPE_NONE,
>> +    AV_PICTURE_TYPE_NONE,
>> +    AV_PICTURE_TYPE_NONE,
>> +    AV_PICTURE_TYPE_P,
>> +    AV_PICTURE_TYPE_P,
>> +    AV_PICTURE_TYPE_B
>> +};
>> +
>> +typedef struct UAVS2DContext {
>> +    AVCodecContext *avctx;
>> +    void *dec_handle;
>> +    avs2_frame_t dec_frame;
>> +    int got_seqhdr;
>> +} UAVS2DContext;
>> +
>> +
>> +static int 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) != 0xB1010000)) { /* sequence end */
>> +        data_ptr++;
>> +        count--;
>> +    }
>> +
>> +    if (count >= 4) {
>> +        *left = count;
>> +        return 1;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +
>> +static int ff_uavs2d_init(AVCodecContext *avctx)
>> +{
>> +    UAVS2DContext *h = avctx->priv_data;
>> +    h->dec_handle = uavs2d_lib_create(1, 1);
>> +    h->dec_frame.i_output_type = AVS2_OUT_I420;
>> +    h->got_seqhdr = 0;
>> +
>> +    avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
>> +    return 0;
>> +}
>> +
>> +static int ff_uavs2d_end(AVCodecContext *avctx)
>> +{
>> +    UAVS2DContext *h = avctx->priv_data;
>> +    uavs2d_lib_destroy(h->dec_handle);
>> +    h->got_seqhdr = 0;
>> +    return 0;
>> +}
>> +
>> +static void uavs2d_flush(AVCodecContext * avctx)
>> +{
>> +    UAVS2DContext *h = avctx->priv_data;
>> +    h->dec_frame.bs_len = -1;
>> +
>> +    do {
>> +        uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
>> +    } while (h->dec_frame.dec_stats == AVS2_TYPE_DECODED);
>> +
>> +    h->got_seqhdr = 0;
>> +
>> +    uavs2d_lib_destroy(h->dec_handle);
>> +    h->got_seqhdr = 0;
>> +    h->dec_handle = uavs2d_lib_create(1, 1);
>> +    h->dec_frame.i_output_type = AVS2_OUT_I420;
>> +}
>> +
>> +static int uavs2d_decode_frame(AVCodecContext *avctx, void *data, int
>> *got_frame, AVPacket *avpkt)
>> +{
>> +    UAVS2DContext *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;
>> +
>> +    if (buf_size == 0) {
>> +        if (h->got_seqhdr) {
>> +            if (frm->data[0] == NULL && (ret = ff_get_buffer(avctx, frm,
>> 0)) < 0) {
>> +                return ret;
>> +            }
>> +            h->dec_frame.bs_len = -1;
>> +            h->dec_frame.p_buf_y = frm->data[0];
>> +            h->dec_frame.p_buf_u = frm->data[1];
>> +            h->dec_frame.p_buf_v = frm->data[2];
>> +            h->dec_frame.i_stride = frm->linesize[0];
>> +            h->dec_frame.i_stridec = frm->linesize[1];
>> +            uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
>> +            if (h->dec_frame.dec_stats == AVS2_TYPE_DECODED) {
>> +                *got_frame = 1;
>> +                frm->pts = h->dec_frame.pts;
>> +                frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
>> +            }
>> +        }
>> +        return 0;
>> +    }
>> +
>> +    buf_ptr = buf;
>> +    buf_end = buf + buf_size;
>> +
>> +    while (finish == 0) {
>> +        if (find_next_start_code(buf_ptr, buf_end - buf_ptr,
>> &left_bytes)) {
>> +            h->dec_frame.bs_len = buf_end - buf_ptr - left_bytes;
>> +        } else {
>> +            h->dec_frame.bs_len = buf_end - buf_ptr;
>> +            finish = 1;
>> +        }
>> +        h->dec_frame.bs_buf = (uint8_t*)buf_ptr;
>> +        h->dec_frame.pts = avpkt->pts;
>> +
>> +        buf_ptr += h->dec_frame.bs_len;
>> +
>> +        if (h->got_seqhdr && frm->data[0]== NULL && (ret =
>> ff_get_buffer(avctx, frm, 0)) < 0) {
>> +            return ret;
>> +        }
>> +        h->dec_frame.p_buf_y = frm->data[0];
>> +        h->dec_frame.p_buf_u = frm->data[1];
>> +        h->dec_frame.p_buf_v = frm->data[2];
>> +        h->dec_frame.i_stride = frm->linesize[0];
>> +        h->dec_frame.i_stridec = frm->linesize[1];
>> +
>> +        uavs2d_lib_decode(h->dec_handle, &h->dec_frame);
>> +
>> +        switch (h->dec_frame.dec_stats) {
>> +        case AVS2_TYPE_DECODED:   /* decode one frame */
>> +            *got_frame = 1;
>> +            finish = 1;
>> +            frm->pts = h->dec_frame.pts;
>> +            frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
>> +            break;
>> +        case AVS2_TYPE_ERROR:     /* error, current or next frame was
>> not decoded */
>> +            av_log(h->avctx, AV_LOG_WARNING, "decode error\n");
>> +            break;
>> +        case AVS2_TYPE_DROP:     /* error, current or next frame was not
>> decoded */
>> +            av_log(h->avctx, AV_LOG_WARNING, "DROP non-RA frame\n");
>> +            break;
>> +        case AVS2_TYPE_SEQ:       /* sequence header was decoded */
>> +            if (avctx->width != h->dec_frame.info.img_width ||
>> avctx->height != h->dec_frame.info.img_height) {
>> +                static const int avs2_fps_num[8] = { 240000, 24, 25,
>> 30000, 30, 50, 60000, 60 };
>> +                static const int avs2_fps_den[8] = {   1001,  1,  1,
>> 1001,  1,  1,  1001,  1 };
>> +                av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d ->
>> %dx%d\n", avctx->width, avctx->height, h->dec_frame.info.img_width,
>> h->dec_frame.info.img_height);
>> +                ret = ff_set_dimensions(avctx,
>> h->dec_frame.info.img_width, h->dec_frame.info.img_height);
>> +
>> +                if (ret < 0) {
>> +                    return ret;
>> +                }
>> +                avctx->framerate.num = avs2_fps_num[h->dec_frame.info
>> .frame_rate_code];
>> +                avctx->framerate.den = avs2_fps_den[h->dec_frame.info
>> .frame_rate_code];
>> +            }
>> +            h->got_seqhdr = 1;
>> +        }
>> +     }
>> +
>> +    return buf_ptr - buf;
>> +}
>> +
>> +AVCodec ff_libuavs2d_decoder = {
>> +    .name           = "uavs2d",
>> +    .long_name      = NULL_IF_CONFIG_SMALL("Decoder for Chinese AVS2"),
>> +    .type           = AVMEDIA_TYPE_VIDEO,
>> +    .id             = AV_CODEC_ID_CAVS2,
>> +    .priv_data_size = sizeof(UAVS2DContext),
>> +    .init           = ff_uavs2d_init,
>> +    .close          = ff_uavs2d_end,
>> +    .decode         = uavs2d_decode_frame,
>> +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
>> +    .flush          = uavs2d_flush,
>> +    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
>> +                                                     AV_PIX_FMT_NONE },
>> +};
>> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
>> index 6a216ef..7f7a755 100644
>> --- a/libavformat/allformats.c
>> +++ b/libavformat/allformats.c
>> @@ -95,6 +95,7 @@ void av_register_all(void)
>>      REGISTER_DEMUXER (C93,              c93);
>>      REGISTER_MUXDEMUX(CAF,              caf);
>>      REGISTER_MUXDEMUX(CAVSVIDEO,        cavsvideo);
>> +    REGISTER_MUXDEMUX(CAVS2VIDEO,       cavs2video);
>>      REGISTER_DEMUXER (CDG,              cdg);
>>      REGISTER_DEMUXER (CDXL,             cdxl);
>>      REGISTER_DEMUXER (CINE,             cine);
>> diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c
>> index b4da58e..8d6325d 100644
>> --- a/libavformat/cavsvideodec.c
>> +++ b/libavformat/cavsvideodec.c
>> @@ -19,6 +19,7 @@
>>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> 02110-1301 USA
>>   */
>>
>> +#include <ctype.h>
>>  #include "avformat.h"
>>  #include "rawdec.h"
>>  #include "libavcodec/internal.h"
>> @@ -66,4 +67,50 @@ static int cavsvideo_probe(AVProbeData *p)
>>      return 0;
>>  }
>>
>> +static int cavs2video_probe(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 < CAVS_SEQ_START_CODE) {
>> +                /* slices have to be consecutive */
>> +                if(code < slice_pos)
>> +                    return 0;
>> +                slice_pos = code;
>> +            } else {
>> +                slice_pos = 0;
>> +            }
>> +            if (code == CAVS_SEQ_START_CODE) {
>> +                seq++;
>> +                /* check for the only currently supported profile */
>> +                if (*ptr != CAVS_PROFILE_JIZHUN)
>> +                    return 0;
>> +            } else if ((code == CAVS_PIC_I_START_CODE) ||
>> +                       (code == CAVS_PIC_PB_START_CODE)) {
>> +                pic++;
>> +            } else if ((code == CAVS_UNDEF_START_CODE) ||
>> +                       (code >  CAVS_VIDEO_EDIT_CODE)) {
>> +                return 0;
>> +            }
>> +        }
>> +    }
>> +    if(seq && pic) {
>> +        const char *str = p->filename + strlen(p->filename) - 5;
>> +        if (tolower(str[0]) == 'c' && tolower(str[1]) == 'a' &&
>> tolower(str[2]) == 'v' &&tolower(str[3]) == 's' && str[4] == '2') {
>> +            ret = AVPROBE_SCORE_EXTENSION+2;
>> +        }
>> +    }
>> +    return ret;
>> +}
>> +
>> +
>> +
>>  FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video
>> Standard)", cavsvideo_probe, NULL, AV_CODEC_ID_CAVS)
>> +
>> +FF_DEF_RAWVIDEO_DEMUXER(cavs2video, "raw Chinese AVS2 (Audio Video
>> Standard)", cavs2video_probe, "cavs2", AV_CODEC_ID_CAVS2)
>> +
>> diff --git a/libavformat/flv.h b/libavformat/flv.h
>> index df5ce3d..78ff1b3 100644
>> --- a/libavformat/flv.h
>> +++ b/libavformat/flv.h
>> @@ -109,6 +109,7 @@ enum {
>>      FLV_CODECID_H264    = 7,
>>      FLV_CODECID_REALH263= 8,
>>      FLV_CODECID_MPEG4   = 9,
>> +    FLV_CODECID_CAVS2   = 10,
>>  };
>>
>>  enum {
>> diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
>> index e53c345..e85fcbc 100644
>> --- a/libavformat/flvdec.c
>> +++ b/libavformat/flvdec.c
>> @@ -281,6 +281,8 @@ static int flv_same_video_codec(AVCodecParameters
>> *vpar, int flags)
>>          return vpar->codec_id == AV_CODEC_ID_VP6A;
>>      case FLV_CODECID_H264:
>>          return vpar->codec_id == AV_CODEC_ID_H264;
>> +    case FLV_CODECID_CAVS2:
>> +        return vpar->codec_id == AV_CODEC_ID_CAVS2;
>>      default:
>>          return vpar->codec_tag == flv_codecid;
>>      }
>> @@ -325,6 +327,9 @@ static int flv_set_video_codec(AVFormatContext *s,
>> AVStream *vstream,
>>      case FLV_CODECID_MPEG4:
>>          par->codec_id = AV_CODEC_ID_MPEG4;
>>          return 3;
>> +    case FLV_CODECID_CAVS2:
>> +        par->codec_id = AV_CODEC_ID_CAVS2;
>> +        break;
>>      default:
>>          avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
>>          par->codec_tag = flv_codecid;
>> diff --git a/libavformat/isom.c b/libavformat/isom.c
>> index 1fa46bd..b0bb8c3 100644
>> --- a/libavformat/isom.c
>> +++ b/libavformat/isom.c
>> @@ -36,6 +36,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
>>      { AV_CODEC_ID_MPEG4       , 0x20 },
>>      { AV_CODEC_ID_H264        , 0x21 },
>>      { AV_CODEC_ID_HEVC        , 0x23 },
>> +    { AV_CODEC_ID_CAVS2       , 0x24 },
>>      { AV_CODEC_ID_AAC         , 0x40 },
>>      { AV_CODEC_ID_MP4ALS      , 0x40 }, /* 14496-3 ALS */
>>      { AV_CODEC_ID_MPEG2VIDEO  , 0x61 }, /* MPEG-2 Main */
>> @@ -244,6 +245,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
>>
>>      { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */
>>      { AV_CODEC_ID_CAVS, MKTAG('a', 'v', 's', '2') },
>> +    { AV_CODEC_ID_CAVS2, MKTAG('c', 'a', 'v', '2') },
>>
>>      { AV_CODEC_ID_DIRAC,     MKTAG('d', 'r', 'a', 'c') },
>>      { AV_CODEC_ID_DNXHD,     MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD
>> */
>> diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h
>> index 617e36c..faa875e 100644
>> --- a/libavformat/mpeg.h
>> +++ b/libavformat/mpeg.h
>> @@ -56,6 +56,7 @@
>>  #define STREAM_TYPE_VIDEO_MPEG4     0x10
>>  #define STREAM_TYPE_VIDEO_H264      0x1b
>>  #define STREAM_TYPE_VIDEO_CAVS      0x42
>> +#define STREAM_TYPE_VIDEO_CAVS2     0x52
>>
>>  #define STREAM_TYPE_AUDIO_AC3       0x81
>>
>> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
>> index fad10c6..2dbd460 100644
>> --- a/libavformat/mpegts.c
>> +++ b/libavformat/mpegts.c
>> @@ -705,6 +705,7 @@ static const StreamType ISO_types[] = {
>>      { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000   },
>>      { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC       },
>>      { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS       },
>> +    { 0x52, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS2      },
>>      { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC      },
>>      { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1        },
>>      { 0 },
>> diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
>> index 272e2be..d0f7033 100644
>> --- a/libavformat/mpegts.h
>> +++ b/libavformat/mpegts.h
>> @@ -55,6 +55,7 @@
>>  #define STREAM_TYPE_VIDEO_H264      0x1b
>>  #define STREAM_TYPE_VIDEO_HEVC      0x24
>>  #define STREAM_TYPE_VIDEO_CAVS      0x42
>> +#define STREAM_TYPE_VIDEO_CAVS2     0x52
>>  #define STREAM_TYPE_VIDEO_VC1       0xea
>>  #define STREAM_TYPE_VIDEO_DIRAC     0xd1
>>
>> diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
>> index 730e99a..bd0d415 100644
>> --- a/libavformat/rawenc.c
>> +++ b/libavformat/rawenc.c
>> @@ -104,6 +104,19 @@ AVOutputFormat ff_cavsvideo_muxer = {
>>  };
>>  #endif
>>
>> +#if CONFIG_CAVS2VIDEO_MUXER
>> +AVOutputFormat ff_cavs2video_muxer = {
>> +    .name              = "cavs2video",
>> +    .long_name         = NULL_IF_CONFIG_SMALL("raw Chinese AVS2 (Audio
>> Video Standard) video"),
>> +    .extensions        = "cavs2",
>> +    .audio_codec       = AV_CODEC_ID_NONE,
>> +    .video_codec       = AV_CODEC_ID_CAVS2,
>> +    .write_header      = force_one_stream,
>> +    .write_packet      = ff_raw_write_packet,
>> +    .flags             = AVFMT_NOTIMESTAMPS,
>> +};
>> +#endif
>> +
>>  #if CONFIG_DATA_MUXER
>>  AVOutputFormat ff_data_muxer = {
>>      .name              = "data",
>> diff --git a/libavformat/riff.c b/libavformat/riff.c
>> index 3c5a37c..ec2d1cf 100644
>> --- a/libavformat/riff.c
>> +++ b/libavformat/riff.c
>> @@ -362,6 +362,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
>>      { AV_CODEC_ID_ZMBV,         MKTAG('Z', 'M', 'B', 'V') },
>>      { AV_CODEC_ID_KMVC,         MKTAG('K', 'M', 'V', 'C') },
>>      { AV_CODEC_ID_CAVS,         MKTAG('C', 'A', 'V', 'S') },
>> +    { AV_CODEC_ID_CAVS2,        MKTAG('C', 'A', 'V', '2') },
>>      { AV_CODEC_ID_JPEG2000,     MKTAG('m', 'j', 'p', '2') },
>>      { AV_CODEC_ID_JPEG2000,     MKTAG('M', 'J', '2', 'C') },
>>      { AV_CODEC_ID_JPEG2000,     MKTAG('L', 'J', '2', 'C') },
>> --
>> 2.7.4
>>
>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>
> Aha, AVS2 in China is used by broadcast television, this is a important
> decoder.
>
>
>
Steven Liu Nov. 8, 2016, 1:20 p.m.
2016-11-08 20:57 GMT+08:00 Zhenyu Wang <wangzhenyu@pkusz.edu.cn>:

> ---
>  configure                  |   4 +
>  libavcodec/Makefile        |   1 +
>  libavcodec/allcodecs.c     |   2 +
>  libavcodec/avcodec.h       |   1 +
>  libavcodec/cavs_parser.c   |   9 ++
>  libavcodec/codec_desc.c    |   7 ++
>  libavcodec/libuavs2d.c     | 218 ++++++++++++++++++++++++++++++
> +++++++++++++++
>  libavformat/allformats.c   |   1 +
>  libavformat/cavsvideodec.c |  47 ++++++++++
>  libavformat/flv.h          |   1 +
>  libavformat/flvdec.c       |   5 ++
>  libavformat/isom.c         |   2 +
>  libavformat/mpeg.h         |   1 +
>  libavformat/mpegts.c       |   1 +
>  libavformat/mpegts.h       |   1 +
>  libavformat/rawenc.c       |  13 +++
>  libavformat/riff.c         |   1 +
>  17 files changed, 315 insertions(+)
>  create mode 100644 libavcodec/libuavs2d.c
>
> diff --git a/configure b/configure
> index 87b06f1..76f00ed 100755
> --- a/configure
> +++ b/configure
> @@ -269,6 +269,7 @@ External library support:
>    --enable-libx264         enable H.264 encoding via x264 [no]
>    --enable-libx265         enable HEVC encoding via x265 [no]
>    --enable-libxavs         enable AVS encoding via xavs [no]
> +  --enable-libuavs2d       enable AVS2 decoding via uavs2d [no]
>    --enable-libxcb          enable X11 grabbing using XCB [autodetect]
>    --enable-libxcb-shm      enable X11 grabbing shm communication
> [autodetect]
>    --enable-libxcb-xfixes   enable X11 grabbing mouse rendering
> [autodetect]
> @@ -1535,6 +1536,7 @@ EXTERNAL_LIBRARY_LIST="
>      libx264
>      libx265
>      libxavs
> +    libuavs2d
>      libxcb
>      libxcb_shm
>      libxcb_shape
> @@ -2833,6 +2835,7 @@ libx264rgb_encoder_deps="libx264 x264_csp_bgr"
>  libx264rgb_encoder_select="libx264_encoder"
>  libx265_encoder_deps="libx265"
>  libxavs_encoder_deps="libxavs"
> +libuavs2d_decoder_deps="libuavs2d"
>  libxvid_encoder_deps="libxvid"
>  libzvbi_teletext_decoder_deps="libzvbi"
>  videotoolbox_deps="VideoToolbox_VideoToolbox_h"
> @@ -5787,6 +5790,7 @@ enabled libx265           && require_pkg_config x265
> x265.h x265_api_get &&
>                               { check_cpp_condition x265.h "X265_BUILD >=
> 68" ||
>                                 die "ERROR: libx265 version must be >=
> 68."; }
>  enabled libxavs           && require libxavs xavs.h xavs_encoder_encode
> -lxavs
> +enabled libuavs2d         && require libuavs2d uavs2d.h uavs2d_lib_decode
> -luavs2d
>  enabled libxvid           && require libxvid xvid.h xvid_global -lxvidcore
>  enabled libzimg           && require_pkg_config zimg zimg.h
> zimg_get_api_version
>  enabled libzmq            && require_pkg_config libzmq zmq.h zmq_ctx_new
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index f1d5bf1..ca9282d 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -910,6 +910,7 @@ OBJS-$(CONFIG_LIBX262_ENCODER)            += libx264.o
>  OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
>  OBJS-$(CONFIG_LIBX265_ENCODER)            += libx265.o
>  OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
> +OBJS-$(CONFIG_LIBUAVS2D_DECODER)          += libuavs2d.o
>  OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
>  OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o ass.o
>
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index ada9481..9afa3e8 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -622,6 +622,7 @@ void avcodec_register_all(void)
>      REGISTER_ENCODER(LIBX264RGB,        libx264rgb);
>      REGISTER_ENCODER(LIBX265,           libx265);
>      REGISTER_ENCODER(LIBXAVS,           libxavs);
> +    REGISTER_DECODER(LIBUAVS2D,         libuavs2d);
>      REGISTER_ENCODER(LIBXVID,           libxvid);
>      REGISTER_DECODER(LIBZVBI_TELETEXT,  libzvbi_teletext);
>
> @@ -670,6 +671,7 @@ void avcodec_register_all(void)
>      REGISTER_PARSER(ADX,                adx);
>      REGISTER_PARSER(BMP,                bmp);
>      REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
> +    REGISTER_PARSER(CAVS2VIDEO,         cavs2video);
>      REGISTER_PARSER(COOK,               cook);
>      REGISTER_PARSER(DCA,                dca);
>      REGISTER_PARSER(DIRAC,              dirac);
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 211112f..9c0a4bf 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -282,6 +282,7 @@ enum AVCodecID {
>      AV_CODEC_ID_KMVC,
>      AV_CODEC_ID_FLASHSV,
>      AV_CODEC_ID_CAVS,
> +    AV_CODEC_ID_CAVS2,
>      AV_CODEC_ID_JPEG2000,
>      AV_CODEC_ID_VMNC,
>      AV_CODEC_ID_VP5,
> diff --git a/libavcodec/cavs_parser.c b/libavcodec/cavs_parser.c
> index 6067a39..a2cef8b 100644
> --- a/libavcodec/cavs_parser.c
> +++ b/libavcodec/cavs_parser.c
> @@ -104,3 +104,12 @@ AVCodecParser ff_cavsvideo_parser = {
>      .parser_close   = ff_parse_close,
>      .split          = ff_mpeg4video_split,
>  };
> +
> +AVCodecParser ff_cavs2video_parser = {
> +    .codec_ids      = { AV_CODEC_ID_CAVS2 },
> +    .priv_data_size = sizeof(ParseContext),
> +    .parser_parse   = cavsvideo_parse,
> +    .parser_close   = ff_parse_close,
> +    .split          = ff_mpeg4video_split,
> +};
> +
> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
> index 9dbe2dc..c510a4d 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -601,6 +601,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
>          .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
>      },
>      {
> +        .id        = AV_CODEC_ID_CAVS2,
> +        .type      = AVMEDIA_TYPE_VIDEO,
> +        .name      = "cavs2",
> +        .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS2 (Audio Video
> Standard)"),
> +        .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
> +    },
> +    {
>          .id        = AV_CODEC_ID_JPEG2000,
>          .type      = AVMEDIA_TYPE_VIDEO,
>          .name      = "jpeg2000",
> diff --git a/libavcodec/libuavs2d.c b/libavcodec/libuavs2d.c
> new file mode 100644
> index 0000000..0e80afd
> --- /dev/null
> +++ b/libavcodec/libuavs2d.c
> @@ -0,0 +1,218 @@
> +/*
> + * AVS2 decoding using the uavs2d library
> + * Copyright (C) 2016 uavs2d project,
> + * National Engineering Laboratory for Video Technology(Shenzhen),
> + * Digital Media R&D Center at Peking University Shenzhen Graduate
> School, China
> + *
> + * Z.Y. Wang <wangzhenyu@pkusz.edu.cn>
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> + */
> +
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/common.h"
> +#include "libavutil/avutil.h"
> +#include "avcodec.h"
> +#include "uavs2d.h"
> +#include "libavutil/imgutils.h"
> +#include "internal.h"
> +
> +
> +const enum AVPictureType IMGTYPE[8] = {
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_I,
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_NONE,
> +    AV_PICTURE_TYPE_P,
> +    AV_PICTURE_TYPE_P,
> +    AV_PICTURE_TYPE_B
> +};
> +
> +typedef struct UAVS2DContext {
> +    AVCodecContext *avctx;
> +    void *dec_handle;
> +    avs2_frame_t dec_frame;
> +    int got_seqhdr;
> +} UAVS2DContext;
> +
> +
> +static int 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) != 0xB1010000)) { /* sequence end */
> +        data_ptr++;
> +        count--;
> +    }
> +
> +    if (count >= 4) {
> +        *left = count;
> +        return 1;
> +    }
> +
> +    return 0;
> +}
> +
> +
> +static int ff_uavs2d_init(AVCodecContext *avctx)
> +{
> +    UAVS2DContext *h = avctx->priv_data;
> +    h->dec_handle = uavs2d_lib_create(1, 1);
> +    h->dec_frame.i_output_type = AVS2_OUT_I420;
> +    h->got_seqhdr = 0;
> +
> +    avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
> +    return 0;
> +}
> +
> +static int ff_uavs2d_end(AVCodecContext *avctx)
> +{
> +    UAVS2DContext *h = avctx->priv_data;
> +    uavs2d_lib_destroy(h->dec_handle);
> +    h->got_seqhdr = 0;
> +    return 0;
> +}
> +
> +static void uavs2d_flush(AVCodecContext * avctx)
> +{
> +    UAVS2DContext *h = avctx->priv_data;
> +    h->dec_frame.bs_len = -1;
> +
> +    do {
> +        uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
> +    } while (h->dec_frame.dec_stats == AVS2_TYPE_DECODED);
> +
> +    h->got_seqhdr = 0;
> +
> +    uavs2d_lib_destroy(h->dec_handle);
> +    h->got_seqhdr = 0;
> +    h->dec_handle = uavs2d_lib_create(1, 1);
> +    h->dec_frame.i_output_type = AVS2_OUT_I420;
> +}
> +
> +static int uavs2d_decode_frame(AVCodecContext *avctx, void *data, int
> *got_frame, AVPacket *avpkt)
> +{
> +    UAVS2DContext *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;
> +
> +    if (buf_size == 0) {
>
if (!buf_size) {

> +        if (h->got_seqhdr) {
> +            if (frm->data[0] == NULL && (ret = ff_get_buffer(avctx, frm,
> 0)) < 0) {
>
if ((!frm->data[0]) && ff_get_buffer(avctx, frm, 0) < 0)  {

> +                return ret;
> +            }
> +            h->dec_frame.bs_len = -1;
> +            h->dec_frame.p_buf_y = frm->data[0];
> +            h->dec_frame.p_buf_u = frm->data[1];
> +            h->dec_frame.p_buf_v = frm->data[2];
> +            h->dec_frame.i_stride = frm->linesize[0];
> +            h->dec_frame.i_stridec = frm->linesize[1];
> +            uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
> +            if (h->dec_frame.dec_stats == AVS2_TYPE_DECODED) {
> +                *got_frame = 1;
> +                frm->pts = h->dec_frame.pts;
> +                frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
> +            }
> +        }
> +        return 0;
> +    }
> +
> +    buf_ptr = buf;
> +    buf_end = buf + buf_size;
> +
> +    while (finish == 0) {
>
while (!finish) {

> +        if (find_next_start_code(buf_ptr, buf_end - buf_ptr,
> &left_bytes)) {
> +            h->dec_frame.bs_len = buf_end - buf_ptr - left_bytes;
> +        } else {
> +            h->dec_frame.bs_len = buf_end - buf_ptr;
> +            finish = 1;
> +        }
> +        h->dec_frame.bs_buf = (uint8_t*)buf_ptr;
> +        h->dec_frame.pts = avpkt->pts;
> +
> +        buf_ptr += h->dec_frame.bs_len;
> +
> +        if (h->got_seqhdr && frm->data[0]== NULL && (ret =
> ff_get_buffer(avctx, frm, 0)) < 0) {
>
use () to let the code readable.

> +            return ret;
> +        }
> +        h->dec_frame.p_buf_y = frm->data[0];
> +        h->dec_frame.p_buf_u = frm->data[1];
> +        h->dec_frame.p_buf_v = frm->data[2];
> +        h->dec_frame.i_stride = frm->linesize[0];
> +        h->dec_frame.i_stridec = frm->linesize[1];
> +
> +        uavs2d_lib_decode(h->dec_handle, &h->dec_frame);
> +
> +        switch (h->dec_frame.dec_stats) {
> +        case AVS2_TYPE_DECODED:   /* decode one frame */
> +            *got_frame = 1;
> +            finish = 1;
> +            frm->pts = h->dec_frame.pts;
> +            frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
> +            break;
> +        case AVS2_TYPE_ERROR:     /* error, current or next frame was not
> decoded */
> +            av_log(h->avctx, AV_LOG_WARNING, "decode error\n");
> +            break;
> +        case AVS2_TYPE_DROP:     /* error, current or next frame was not
> decoded */
> +            av_log(h->avctx, AV_LOG_WARNING, "DROP non-RA frame\n");
> +            break;
> +        case AVS2_TYPE_SEQ:       /* sequence header was decoded */
> +            if (avctx->width != h->dec_frame.info.img_width ||
> avctx->height != h->dec_frame.info.img_height) {
> +                static const int avs2_fps_num[8] = { 240000, 24, 25,
> 30000, 30, 50, 60000, 60 };
> +                static const int avs2_fps_den[8] = {   1001,  1,  1,
> 1001,  1,  1,  1001,  1 };
> +                av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d ->
> %dx%d\n", avctx->width, avctx->height, h->dec_frame.info.img_width,
> h->dec_frame.info.img_height);
> +                ret = ff_set_dimensions(avctx,
> h->dec_frame.info.img_width, h->dec_frame.info.img_height);
> +
> +                if (ret < 0) {
> +                    return ret;
> +                }
> +                avctx->framerate.num = avs2_fps_num[h->dec_frame.
> info.frame_rate_code];
> +                avctx->framerate.den = avs2_fps_den[h->dec_frame.
> info.frame_rate_code];
> +            }
> +            h->got_seqhdr = 1;
> +        }
> +     }
> +
> +    return buf_ptr - buf;
> +}
> +
> +AVCodec ff_libuavs2d_decoder = {
> +    .name           = "uavs2d",
> +    .long_name      = NULL_IF_CONFIG_SMALL("Decoder for Chinese AVS2"),
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_CAVS2,
> +    .priv_data_size = sizeof(UAVS2DContext),
> +    .init           = ff_uavs2d_init,
> +    .close          = ff_uavs2d_end,
> +    .decode         = uavs2d_decode_frame,
> +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
> +    .flush          = uavs2d_flush,
> +    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
> +                                                     AV_PIX_FMT_NONE },
> +};
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 6a216ef..7f7a755 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -95,6 +95,7 @@ void av_register_all(void)
>      REGISTER_DEMUXER (C93,              c93);
>      REGISTER_MUXDEMUX(CAF,              caf);
>      REGISTER_MUXDEMUX(CAVSVIDEO,        cavsvideo);
> +    REGISTER_MUXDEMUX(CAVS2VIDEO,       cavs2video);
>      REGISTER_DEMUXER (CDG,              cdg);
>      REGISTER_DEMUXER (CDXL,             cdxl);
>      REGISTER_DEMUXER (CINE,             cine);
> diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c
> index b4da58e..8d6325d 100644
> --- a/libavformat/cavsvideodec.c
> +++ b/libavformat/cavsvideodec.c
> @@ -19,6 +19,7 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
>   */
>
> +#include <ctype.h>
>  #include "avformat.h"
>  #include "rawdec.h"
>  #include "libavcodec/internal.h"
> @@ -66,4 +67,50 @@ static int cavsvideo_probe(AVProbeData *p)
>      return 0;
>  }
>
> +static int cavs2video_probe(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 < CAVS_SEQ_START_CODE) {
> +                /* slices have to be consecutive */
> +                if(code < slice_pos)
> +                    return 0;
> +                slice_pos = code;
> +            } else {
> +                slice_pos = 0;
> +            }
> +            if (code == CAVS_SEQ_START_CODE) {
> +                seq++;
> +                /* check for the only currently supported profile */
> +                if (*ptr != CAVS_PROFILE_JIZHUN)
> +                    return 0;
> +            } else if ((code == CAVS_PIC_I_START_CODE) ||
> +                       (code == CAVS_PIC_PB_START_CODE)) {
> +                pic++;
> +            } else if ((code == CAVS_UNDEF_START_CODE) ||
> +                       (code >  CAVS_VIDEO_EDIT_CODE)) {
> +                return 0;
> +            }
> +        }
> +    }
> +    if(seq && pic) {
> +        const char *str = p->filename + strlen(p->filename) - 5;
> +        if (tolower(str[0]) == 'c' && tolower(str[1]) == 'a' &&
> tolower(str[2]) == 'v' &&tolower(str[3]) == 's' && str[4] == '2') {
> +            ret = AVPROBE_SCORE_EXTENSION+2;
> +        }
> +    }
> +    return ret;
> +}
> +
> +
> +
>  FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video
> Standard)", cavsvideo_probe, NULL, AV_CODEC_ID_CAVS)
> +
> +FF_DEF_RAWVIDEO_DEMUXER(cavs2video, "raw Chinese AVS2 (Audio Video
> Standard)", cavs2video_probe, "cavs2", AV_CODEC_ID_CAVS2)
> +
> diff --git a/libavformat/flv.h b/libavformat/flv.h
>
Adobe have no specific to support AVS in flv, i don't know if it can mux in
FLV, Other reviewer attention please.

> index df5ce3d..78ff1b3 100644
> --- a/libavformat/flv.h
> +++ b/libavformat/flv.h
> @@ -109,6 +109,7 @@ enum {
>      FLV_CODECID_H264    = 7,
>      FLV_CODECID_REALH263= 8,
>      FLV_CODECID_MPEG4   = 9,
> +    FLV_CODECID_CAVS2   = 10,
>  };
>
>  enum {
> diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
> index e53c345..e85fcbc 100644
> --- a/libavformat/flvdec.c
> +++ b/libavformat/flvdec.c
> @@ -281,6 +281,8 @@ static int flv_same_video_codec(AVCodecParameters
> *vpar, int flags)
>          return vpar->codec_id == AV_CODEC_ID_VP6A;
>      case FLV_CODECID_H264:
>          return vpar->codec_id == AV_CODEC_ID_H264;
> +    case FLV_CODECID_CAVS2:
> +        return vpar->codec_id == AV_CODEC_ID_CAVS2;
>      default:
>          return vpar->codec_tag == flv_codecid;
>      }
> @@ -325,6 +327,9 @@ static int flv_set_video_codec(AVFormatContext *s,
> AVStream *vstream,
>      case FLV_CODECID_MPEG4:
>          par->codec_id = AV_CODEC_ID_MPEG4;
>          return 3;
> +    case FLV_CODECID_CAVS2:
> +        par->codec_id = AV_CODEC_ID_CAVS2;
> +        break;
>      default:
>          avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
>          par->codec_tag = flv_codecid;
> diff --git a/libavformat/isom.c b/libavformat/isom.c
> index 1fa46bd..b0bb8c3 100644
> --- a/libavformat/isom.c
> +++ b/libavformat/isom.c
> @@ -36,6 +36,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
>      { AV_CODEC_ID_MPEG4       , 0x20 },
>      { AV_CODEC_ID_H264        , 0x21 },
>      { AV_CODEC_ID_HEVC        , 0x23 },
> +    { AV_CODEC_ID_CAVS2       , 0x24 },
>      { AV_CODEC_ID_AAC         , 0x40 },
>      { AV_CODEC_ID_MP4ALS      , 0x40 }, /* 14496-3 ALS */
>      { AV_CODEC_ID_MPEG2VIDEO  , 0x61 }, /* MPEG-2 Main */
> @@ -244,6 +245,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
>
>      { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */
>      { AV_CODEC_ID_CAVS, MKTAG('a', 'v', 's', '2') },
> +    { AV_CODEC_ID_CAVS2, MKTAG('c', 'a', 'v', '2') },
>
>      { AV_CODEC_ID_DIRAC,     MKTAG('d', 'r', 'a', 'c') },
>      { AV_CODEC_ID_DNXHD,     MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */
> diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h
> index 617e36c..faa875e 100644
> --- a/libavformat/mpeg.h
> +++ b/libavformat/mpeg.h
> @@ -56,6 +56,7 @@
>  #define STREAM_TYPE_VIDEO_MPEG4     0x10
>  #define STREAM_TYPE_VIDEO_H264      0x1b
>  #define STREAM_TYPE_VIDEO_CAVS      0x42
> +#define STREAM_TYPE_VIDEO_CAVS2     0x52
>
>  #define STREAM_TYPE_AUDIO_AC3       0x81
>
> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
> index fad10c6..2dbd460 100644
> --- a/libavformat/mpegts.c
> +++ b/libavformat/mpegts.c
> @@ -705,6 +705,7 @@ static const StreamType ISO_types[] = {
>      { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000   },
>      { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC       },
>      { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS       },
> +    { 0x52, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS2      },
>      { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC      },
>      { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1        },
>      { 0 },
> diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
> index 272e2be..d0f7033 100644
> --- a/libavformat/mpegts.h
> +++ b/libavformat/mpegts.h
> @@ -55,6 +55,7 @@
>  #define STREAM_TYPE_VIDEO_H264      0x1b
>  #define STREAM_TYPE_VIDEO_HEVC      0x24
>  #define STREAM_TYPE_VIDEO_CAVS      0x42
> +#define STREAM_TYPE_VIDEO_CAVS2     0x52
>  #define STREAM_TYPE_VIDEO_VC1       0xea
>  #define STREAM_TYPE_VIDEO_DIRAC     0xd1
>
> diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
> index 730e99a..bd0d415 100644
> --- a/libavformat/rawenc.c
> +++ b/libavformat/rawenc.c
> @@ -104,6 +104,19 @@ AVOutputFormat ff_cavsvideo_muxer = {
>  };
>  #endif
>
> +#if CONFIG_CAVS2VIDEO_MUXER
> +AVOutputFormat ff_cavs2video_muxer = {
> +    .name              = "cavs2video",
> +    .long_name         = NULL_IF_CONFIG_SMALL("raw Chinese AVS2 (Audio
> Video Standard) video"),
> +    .extensions        = "cavs2",
> +    .audio_codec       = AV_CODEC_ID_NONE,
> +    .video_codec       = AV_CODEC_ID_CAVS2,
> +    .write_header      = force_one_stream,
> +    .write_packet      = ff_raw_write_packet,
> +    .flags             = AVFMT_NOTIMESTAMPS,
> +};
> +#endif
> +
>  #if CONFIG_DATA_MUXER
>  AVOutputFormat ff_data_muxer = {
>      .name              = "data",
> diff --git a/libavformat/riff.c b/libavformat/riff.c
> index 3c5a37c..ec2d1cf 100644
> --- a/libavformat/riff.c
> +++ b/libavformat/riff.c
> @@ -362,6 +362,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
>      { AV_CODEC_ID_ZMBV,         MKTAG('Z', 'M', 'B', 'V') },
>      { AV_CODEC_ID_KMVC,         MKTAG('K', 'M', 'V', 'C') },
>      { AV_CODEC_ID_CAVS,         MKTAG('C', 'A', 'V', 'S') },
> +    { AV_CODEC_ID_CAVS2,        MKTAG('C', 'A', 'V', '2') },
>      { AV_CODEC_ID_JPEG2000,     MKTAG('m', 'j', 'p', '2') },
>      { AV_CODEC_ID_JPEG2000,     MKTAG('M', 'J', '2', 'C') },
>      { AV_CODEC_ID_JPEG2000,     MKTAG('L', 'J', '2', 'C') },
> --
> 2.7.4
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Patch hide | download patch | download mbox

diff --git a/configure b/configure
index 87b06f1..76f00ed 100755
--- a/configure
+++ b/configure
@@ -269,6 +269,7 @@  External library support:
   --enable-libx264         enable H.264 encoding via x264 [no]
   --enable-libx265         enable HEVC encoding via x265 [no]
   --enable-libxavs         enable AVS encoding via xavs [no]
+  --enable-libuavs2d       enable AVS2 decoding via uavs2d [no]
   --enable-libxcb          enable X11 grabbing using XCB [autodetect]
   --enable-libxcb-shm      enable X11 grabbing shm communication [autodetect]
   --enable-libxcb-xfixes   enable X11 grabbing mouse rendering [autodetect]
@@ -1535,6 +1536,7 @@  EXTERNAL_LIBRARY_LIST="
     libx264
     libx265
     libxavs
+    libuavs2d
     libxcb
     libxcb_shm
     libxcb_shape
@@ -2833,6 +2835,7 @@  libx264rgb_encoder_deps="libx264 x264_csp_bgr"
 libx264rgb_encoder_select="libx264_encoder"
 libx265_encoder_deps="libx265"
 libxavs_encoder_deps="libxavs"
+libuavs2d_decoder_deps="libuavs2d"
 libxvid_encoder_deps="libxvid"
 libzvbi_teletext_decoder_deps="libzvbi"
 videotoolbox_deps="VideoToolbox_VideoToolbox_h"
@@ -5787,6 +5790,7 @@  enabled libx265           && require_pkg_config x265 x265.h x265_api_get &&
                              { check_cpp_condition x265.h "X265_BUILD >= 68" ||
                                die "ERROR: libx265 version must be >= 68."; }
 enabled libxavs           && require libxavs xavs.h xavs_encoder_encode -lxavs
+enabled libuavs2d         && require libuavs2d uavs2d.h uavs2d_lib_decode -luavs2d
 enabled libxvid           && require libxvid xvid.h xvid_global -lxvidcore
 enabled libzimg           && require_pkg_config zimg zimg.h zimg_get_api_version
 enabled libzmq            && require_pkg_config libzmq zmq.h zmq_ctx_new
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index f1d5bf1..ca9282d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -910,6 +910,7 @@  OBJS-$(CONFIG_LIBX262_ENCODER)            += libx264.o
 OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
 OBJS-$(CONFIG_LIBX265_ENCODER)            += libx265.o
 OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
+OBJS-$(CONFIG_LIBUAVS2D_DECODER)          += libuavs2d.o
 OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
 OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o ass.o
 
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index ada9481..9afa3e8 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -622,6 +622,7 @@  void avcodec_register_all(void)
     REGISTER_ENCODER(LIBX264RGB,        libx264rgb);
     REGISTER_ENCODER(LIBX265,           libx265);
     REGISTER_ENCODER(LIBXAVS,           libxavs);
+    REGISTER_DECODER(LIBUAVS2D,         libuavs2d);
     REGISTER_ENCODER(LIBXVID,           libxvid);
     REGISTER_DECODER(LIBZVBI_TELETEXT,  libzvbi_teletext);
 
@@ -670,6 +671,7 @@  void avcodec_register_all(void)
     REGISTER_PARSER(ADX,                adx);
     REGISTER_PARSER(BMP,                bmp);
     REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
+    REGISTER_PARSER(CAVS2VIDEO,         cavs2video);
     REGISTER_PARSER(COOK,               cook);
     REGISTER_PARSER(DCA,                dca);
     REGISTER_PARSER(DIRAC,              dirac);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 211112f..9c0a4bf 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -282,6 +282,7 @@  enum AVCodecID {
     AV_CODEC_ID_KMVC,
     AV_CODEC_ID_FLASHSV,
     AV_CODEC_ID_CAVS,
+    AV_CODEC_ID_CAVS2,
     AV_CODEC_ID_JPEG2000,
     AV_CODEC_ID_VMNC,
     AV_CODEC_ID_VP5,
diff --git a/libavcodec/cavs_parser.c b/libavcodec/cavs_parser.c
index 6067a39..a2cef8b 100644
--- a/libavcodec/cavs_parser.c
+++ b/libavcodec/cavs_parser.c
@@ -104,3 +104,12 @@  AVCodecParser ff_cavsvideo_parser = {
     .parser_close   = ff_parse_close,
     .split          = ff_mpeg4video_split,
 };
+
+AVCodecParser ff_cavs2video_parser = {
+    .codec_ids      = { AV_CODEC_ID_CAVS2 },
+    .priv_data_size = sizeof(ParseContext),
+    .parser_parse   = cavsvideo_parse,
+    .parser_close   = ff_parse_close,
+    .split          = ff_mpeg4video_split,
+};
+
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 9dbe2dc..c510a4d 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -601,6 +601,13 @@  static const AVCodecDescriptor codec_descriptors[] = {
         .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
     },
     {
+        .id        = AV_CODEC_ID_CAVS2,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "cavs2",
+        .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS2 (Audio Video Standard)"),
+        .props     = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
+    },
+    {
         .id        = AV_CODEC_ID_JPEG2000,
         .type      = AVMEDIA_TYPE_VIDEO,
         .name      = "jpeg2000",
diff --git a/libavcodec/libuavs2d.c b/libavcodec/libuavs2d.c
new file mode 100644
index 0000000..0e80afd
--- /dev/null
+++ b/libavcodec/libuavs2d.c
@@ -0,0 +1,218 @@ 
+/*
+ * AVS2 decoding using the uavs2d library
+ * Copyright (C) 2016 uavs2d project, 
+ * National Engineering Laboratory for Video Technology(Shenzhen), 
+ * Digital Media R&D Center at Peking University Shenzhen Graduate School, China
+ * 
+ * Z.Y. Wang <wangzhenyu@pkusz.edu.cn>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "libavutil/avassert.h"
+#include "libavutil/common.h"
+#include "libavutil/avutil.h"
+#include "avcodec.h"
+#include "uavs2d.h"
+#include "libavutil/imgutils.h"
+#include "internal.h"
+
+
+const enum AVPictureType IMGTYPE[8] = {
+    AV_PICTURE_TYPE_NONE,
+    AV_PICTURE_TYPE_I,
+    AV_PICTURE_TYPE_NONE,
+    AV_PICTURE_TYPE_NONE,
+    AV_PICTURE_TYPE_NONE,
+    AV_PICTURE_TYPE_P,
+    AV_PICTURE_TYPE_P,
+    AV_PICTURE_TYPE_B
+};
+
+typedef struct UAVS2DContext {
+    AVCodecContext *avctx;
+    void *dec_handle;
+    avs2_frame_t dec_frame;
+    int got_seqhdr;
+} UAVS2DContext;
+
+
+static int 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) != 0xB1010000)) { /* sequence end */
+        data_ptr++;
+        count--;
+    }
+
+    if (count >= 4) {
+        *left = count;
+        return 1;
+    }
+
+    return 0;
+}
+
+
+static int ff_uavs2d_init(AVCodecContext *avctx)
+{
+    UAVS2DContext *h = avctx->priv_data;
+    h->dec_handle = uavs2d_lib_create(1, 1);
+    h->dec_frame.i_output_type = AVS2_OUT_I420;
+    h->got_seqhdr = 0;
+
+    avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
+    return 0;
+}
+
+static int ff_uavs2d_end(AVCodecContext *avctx)
+{
+    UAVS2DContext *h = avctx->priv_data;
+    uavs2d_lib_destroy(h->dec_handle);
+    h->got_seqhdr = 0;
+    return 0;
+}
+
+static void uavs2d_flush(AVCodecContext * avctx)
+{
+    UAVS2DContext *h = avctx->priv_data;
+    h->dec_frame.bs_len = -1;
+
+    do {
+        uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
+    } while (h->dec_frame.dec_stats == AVS2_TYPE_DECODED);
+
+    h->got_seqhdr = 0;
+
+    uavs2d_lib_destroy(h->dec_handle);
+    h->got_seqhdr = 0;
+    h->dec_handle = uavs2d_lib_create(1, 1);
+    h->dec_frame.i_output_type = AVS2_OUT_I420;
+}
+
+static int uavs2d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
+{
+    UAVS2DContext *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;
+
+    if (buf_size == 0) {
+        if (h->got_seqhdr) {
+            if (frm->data[0] == NULL && (ret = ff_get_buffer(avctx, frm, 0)) < 0) {
+                return ret;
+            }
+            h->dec_frame.bs_len = -1;
+            h->dec_frame.p_buf_y = frm->data[0];
+            h->dec_frame.p_buf_u = frm->data[1];
+            h->dec_frame.p_buf_v = frm->data[2];
+            h->dec_frame.i_stride = frm->linesize[0];
+            h->dec_frame.i_stridec = frm->linesize[1];
+            uavs2d_lib_flush(h->dec_handle, &h->dec_frame);
+            if (h->dec_frame.dec_stats == AVS2_TYPE_DECODED) {
+                *got_frame = 1;
+                frm->pts = h->dec_frame.pts;
+                frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
+            }
+        }
+        return 0;
+    }
+
+    buf_ptr = buf;
+    buf_end = buf + buf_size;
+
+    while (finish == 0) {
+        if (find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) {
+            h->dec_frame.bs_len = buf_end - buf_ptr - left_bytes;
+        } else {
+            h->dec_frame.bs_len = buf_end - buf_ptr;
+            finish = 1;
+        }
+        h->dec_frame.bs_buf = (uint8_t*)buf_ptr;
+        h->dec_frame.pts = avpkt->pts;
+		
+        buf_ptr += h->dec_frame.bs_len;
+
+        if (h->got_seqhdr && frm->data[0]== NULL && (ret = ff_get_buffer(avctx, frm, 0)) < 0) {
+            return ret;
+        }
+        h->dec_frame.p_buf_y = frm->data[0];
+        h->dec_frame.p_buf_u = frm->data[1];
+        h->dec_frame.p_buf_v = frm->data[2];
+        h->dec_frame.i_stride = frm->linesize[0];
+        h->dec_frame.i_stridec = frm->linesize[1];
+
+        uavs2d_lib_decode(h->dec_handle, &h->dec_frame);
+
+        switch (h->dec_frame.dec_stats) {
+        case AVS2_TYPE_DECODED:   /* decode one frame */
+            *got_frame = 1;
+            finish = 1; 
+            frm->pts = h->dec_frame.pts;
+            frm->pict_type = IMGTYPE[h->dec_frame.frm_type];
+            break;
+        case AVS2_TYPE_ERROR:     /* error, current or next frame was not decoded */
+            av_log(h->avctx, AV_LOG_WARNING, "decode error\n");
+            break;
+        case AVS2_TYPE_DROP:     /* error, current or next frame was not decoded */
+            av_log(h->avctx, AV_LOG_WARNING, "DROP non-RA frame\n");
+            break;
+        case AVS2_TYPE_SEQ:       /* sequence header was decoded */
+            if (avctx->width != h->dec_frame.info.img_width || avctx->height != h->dec_frame.info.img_height) {
+                static const int avs2_fps_num[8] = { 240000, 24, 25, 30000, 30, 50, 60000, 60 };
+                static const int avs2_fps_den[8] = {   1001,  1,  1,  1001,  1,  1,  1001,  1 };
+                av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", avctx->width, avctx->height, h->dec_frame.info.img_width, h->dec_frame.info.img_height);
+                ret = ff_set_dimensions(avctx, h->dec_frame.info.img_width, h->dec_frame.info.img_height);
+				
+                if (ret < 0) {
+                    return ret;
+                }
+                avctx->framerate.num = avs2_fps_num[h->dec_frame.info.frame_rate_code];
+                avctx->framerate.den = avs2_fps_den[h->dec_frame.info.frame_rate_code];
+            }
+            h->got_seqhdr = 1;
+        }
+     }
+	
+    return buf_ptr - buf;
+}
+
+AVCodec ff_libuavs2d_decoder = {
+    .name           = "uavs2d",
+    .long_name      = NULL_IF_CONFIG_SMALL("Decoder for Chinese AVS2"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_CAVS2,
+    .priv_data_size = sizeof(UAVS2DContext),
+    .init           = ff_uavs2d_init,
+    .close          = ff_uavs2d_end,
+    .decode         = uavs2d_decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+    .flush          = uavs2d_flush,
+    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
+                                                     AV_PIX_FMT_NONE },
+};
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 6a216ef..7f7a755 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -95,6 +95,7 @@  void av_register_all(void)
     REGISTER_DEMUXER (C93,              c93);
     REGISTER_MUXDEMUX(CAF,              caf);
     REGISTER_MUXDEMUX(CAVSVIDEO,        cavsvideo);
+    REGISTER_MUXDEMUX(CAVS2VIDEO,       cavs2video);
     REGISTER_DEMUXER (CDG,              cdg);
     REGISTER_DEMUXER (CDXL,             cdxl);
     REGISTER_DEMUXER (CINE,             cine);
diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c
index b4da58e..8d6325d 100644
--- a/libavformat/cavsvideodec.c
+++ b/libavformat/cavsvideodec.c
@@ -19,6 +19,7 @@ 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <ctype.h>
 #include "avformat.h"
 #include "rawdec.h"
 #include "libavcodec/internal.h"
@@ -66,4 +67,50 @@  static int cavsvideo_probe(AVProbeData *p)
     return 0;
 }
 
+static int cavs2video_probe(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 < CAVS_SEQ_START_CODE) {
+                /* slices have to be consecutive */
+                if(code < slice_pos)
+                    return 0;
+                slice_pos = code;
+            } else {
+                slice_pos = 0;
+            }
+            if (code == CAVS_SEQ_START_CODE) {
+                seq++;
+                /* check for the only currently supported profile */
+                if (*ptr != CAVS_PROFILE_JIZHUN)
+                    return 0;
+            } else if ((code == CAVS_PIC_I_START_CODE) ||
+                       (code == CAVS_PIC_PB_START_CODE)) {
+                pic++;
+            } else if ((code == CAVS_UNDEF_START_CODE) ||
+                       (code >  CAVS_VIDEO_EDIT_CODE)) {
+                return 0;
+            }
+        }
+    }
+    if(seq && pic) {
+        const char *str = p->filename + strlen(p->filename) - 5;
+        if (tolower(str[0]) == 'c' && tolower(str[1]) == 'a' && tolower(str[2]) == 'v' &&tolower(str[3]) == 's' && str[4] == '2') {
+            ret = AVPROBE_SCORE_EXTENSION+2;
+        }
+    }
+    return ret;
+}
+
+
+
 FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video Standard)", cavsvideo_probe, NULL, AV_CODEC_ID_CAVS)
+
+FF_DEF_RAWVIDEO_DEMUXER(cavs2video, "raw Chinese AVS2 (Audio Video Standard)", cavs2video_probe, "cavs2", AV_CODEC_ID_CAVS2)
+
diff --git a/libavformat/flv.h b/libavformat/flv.h
index df5ce3d..78ff1b3 100644
--- a/libavformat/flv.h
+++ b/libavformat/flv.h
@@ -109,6 +109,7 @@  enum {
     FLV_CODECID_H264    = 7,
     FLV_CODECID_REALH263= 8,
     FLV_CODECID_MPEG4   = 9,
+    FLV_CODECID_CAVS2   = 10,
 };
 
 enum {
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index e53c345..e85fcbc 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -281,6 +281,8 @@  static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
         return vpar->codec_id == AV_CODEC_ID_VP6A;
     case FLV_CODECID_H264:
         return vpar->codec_id == AV_CODEC_ID_H264;
+    case FLV_CODECID_CAVS2:
+        return vpar->codec_id == AV_CODEC_ID_CAVS2;
     default:
         return vpar->codec_tag == flv_codecid;
     }
@@ -325,6 +327,9 @@  static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
     case FLV_CODECID_MPEG4:
         par->codec_id = AV_CODEC_ID_MPEG4;
         return 3;
+    case FLV_CODECID_CAVS2:
+        par->codec_id = AV_CODEC_ID_CAVS2;
+        break;
     default:
         avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
         par->codec_tag = flv_codecid;
diff --git a/libavformat/isom.c b/libavformat/isom.c
index 1fa46bd..b0bb8c3 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -36,6 +36,7 @@  const AVCodecTag ff_mp4_obj_type[] = {
     { AV_CODEC_ID_MPEG4       , 0x20 },
     { AV_CODEC_ID_H264        , 0x21 },
     { AV_CODEC_ID_HEVC        , 0x23 },
+    { AV_CODEC_ID_CAVS2       , 0x24 },
     { AV_CODEC_ID_AAC         , 0x40 },
     { AV_CODEC_ID_MP4ALS      , 0x40 }, /* 14496-3 ALS */
     { AV_CODEC_ID_MPEG2VIDEO  , 0x61 }, /* MPEG-2 Main */
@@ -244,6 +245,7 @@  const AVCodecTag ff_codec_movvideo_tags[] = {
 
     { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */
     { AV_CODEC_ID_CAVS, MKTAG('a', 'v', 's', '2') },
+    { AV_CODEC_ID_CAVS2, MKTAG('c', 'a', 'v', '2') },
 
     { AV_CODEC_ID_DIRAC,     MKTAG('d', 'r', 'a', 'c') },
     { AV_CODEC_ID_DNXHD,     MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */
diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h
index 617e36c..faa875e 100644
--- a/libavformat/mpeg.h
+++ b/libavformat/mpeg.h
@@ -56,6 +56,7 @@ 
 #define STREAM_TYPE_VIDEO_MPEG4     0x10
 #define STREAM_TYPE_VIDEO_H264      0x1b
 #define STREAM_TYPE_VIDEO_CAVS      0x42
+#define STREAM_TYPE_VIDEO_CAVS2     0x52
 
 #define STREAM_TYPE_AUDIO_AC3       0x81
 
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index fad10c6..2dbd460 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -705,6 +705,7 @@  static const StreamType ISO_types[] = {
     { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000   },
     { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC       },
     { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS       },
+    { 0x52, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS2      },
     { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC      },
     { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1        },
     { 0 },
diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
index 272e2be..d0f7033 100644
--- a/libavformat/mpegts.h
+++ b/libavformat/mpegts.h
@@ -55,6 +55,7 @@ 
 #define STREAM_TYPE_VIDEO_H264      0x1b
 #define STREAM_TYPE_VIDEO_HEVC      0x24
 #define STREAM_TYPE_VIDEO_CAVS      0x42
+#define STREAM_TYPE_VIDEO_CAVS2     0x52
 #define STREAM_TYPE_VIDEO_VC1       0xea
 #define STREAM_TYPE_VIDEO_DIRAC     0xd1
 
diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
index 730e99a..bd0d415 100644
--- a/libavformat/rawenc.c
+++ b/libavformat/rawenc.c
@@ -104,6 +104,19 @@  AVOutputFormat ff_cavsvideo_muxer = {
 };
 #endif
 
+#if CONFIG_CAVS2VIDEO_MUXER
+AVOutputFormat ff_cavs2video_muxer = {
+    .name              = "cavs2video",
+    .long_name         = NULL_IF_CONFIG_SMALL("raw Chinese AVS2 (Audio Video Standard) video"),
+    .extensions        = "cavs2",
+    .audio_codec       = AV_CODEC_ID_NONE,
+    .video_codec       = AV_CODEC_ID_CAVS2,
+    .write_header      = force_one_stream,
+    .write_packet      = ff_raw_write_packet,
+    .flags             = AVFMT_NOTIMESTAMPS,
+};
+#endif
+
 #if CONFIG_DATA_MUXER
 AVOutputFormat ff_data_muxer = {
     .name              = "data",
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 3c5a37c..ec2d1cf 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -362,6 +362,7 @@  const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_ZMBV,         MKTAG('Z', 'M', 'B', 'V') },
     { AV_CODEC_ID_KMVC,         MKTAG('K', 'M', 'V', 'C') },
     { AV_CODEC_ID_CAVS,         MKTAG('C', 'A', 'V', 'S') },
+    { AV_CODEC_ID_CAVS2,        MKTAG('C', 'A', 'V', '2') },
     { AV_CODEC_ID_JPEG2000,     MKTAG('m', 'j', 'p', '2') },
     { AV_CODEC_ID_JPEG2000,     MKTAG('M', 'J', '2', 'C') },
     { AV_CODEC_ID_JPEG2000,     MKTAG('L', 'J', '2', 'C') },