MartinEesmaa

Patch of FFmpeg LAVFilters (21.05.2026)

Sep 27th, 2026
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 26.71 KB | None | 0 0
  1. From c39f153f94b884394db412051727a6da07af5e5f Mon Sep 17 00:00:00 2001
  2. From: Thomas Siedel <[email protected]>
  3. Date: Mon, 2 Jun 2025 11:44:14 +0200
  4. Subject: [PATCH v7] avcodec: add external dec libvvdec for H266/VVC
  5.  
  6. Add external decoder VVdeC for H266/VVC decoding.
  7. Register new decoder libvvdec.
  8. Add libvvdec to wrap the vvdec interface.
  9. Enable decoder by adding --enable-libvvdec in configure step.
  10.  
  11. Co-authored-by: Christian Bartnik <[email protected]>
  12. ---
  13. configure              | 5 +++++
  14.  libavcodec/Makefile    | 1 +
  15.  libavcodec/allcodecs.c | 1 +
  16.  3 files changed, 7 insertions(+)
  17.  
  18. diff --git a/configure b/configure
  19. index f61128bce6..e54f9b5a75 100755
  20. --- a/configure
  21. +++ b/configure
  22. @@ -295,6 +295,7 @@ External library support:
  23.                             native implementation exists [no]
  24.    --enable-libvpx          enable VP8 and VP9 de/encoding via libvpx [no]
  25.    --enable-libvvenc        enable H.266/VVC encoding via vvenc [no]
  26. +  --enable-libvvdec        enable H.266/VVC decoding via vvdec [no]
  27.    --enable-libwebp         enable WebP encoding via libwebp [no]
  28.    --enable-libx264         enable H.264 encoding via x264 [no]
  29.    --enable-libx265         enable HEVC encoding via x265 [no]
  30. @@ -1988,6 +1989,7 @@ EXTERNAL_LIBRARY_LIST="
  31.      libvorbis
  32.      libvpx
  33.      libvvenc
  34. +    libvvdec
  35.      libwebp
  36.      libxevd
  37.      libxeve
  38. @@ -3628,6 +3630,8 @@ libvpx_vp8_encoder_deps="libvpx"
  39.  libvpx_vp9_decoder_deps="libvpx"
  40.  libvpx_vp9_encoder_deps="libvpx"
  41.  libvvenc_encoder_deps="libvvenc"
  42. +libvvdec_decoder_deps="libvvdec"
  43. +libvvdec_decoder_select="vvc_mp4toannexb_bsf"
  44.  libwebp_encoder_deps="libwebp"
  45.  libwebp_anim_encoder_deps="libwebp"
  46.  libx262_encoder_deps="libx262"
  47. @@ -7118,6 +7122,7 @@ enabled libvpx            && {
  48.  }
  49.  
  50.  enabled libvvenc          && require_pkg_config libvvenc "libvvenc >= 1.6.1" "vvenc/vvenc.h" vvenc_get_version
  51. +enabled libvvdec          && require_pkg_config libvvdec "libvvdec >= 1.6.0" "vvdec/vvdec.h" vvdec_get_version
  52.  enabled libwebp           && {
  53.      enabled libwebp_encoder      && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion
  54.      enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; }
  55. diff --git a/libavcodec/Makefile b/libavcodec/Makefile
  56. index 5e052140db..ba56f8ea9a 100644
  57. --- a/libavcodec/Makefile
  58. +++ b/libavcodec/Makefile
  59. @@ -1181,6 +1181,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_ENCODER)         += libvpxenc.o
  60.  OBJS-$(CONFIG_LIBVPX_VP9_DECODER)         += libvpxdec.o
  61.  OBJS-$(CONFIG_LIBVPX_VP9_ENCODER)         += libvpxenc.o
  62.  OBJS-$(CONFIG_LIBVVENC_ENCODER)           += libvvenc.o
  63. +OBJS-$(CONFIG_LIBVVDEC_DECODER)           += libvvdec.o
  64.  OBJS-$(CONFIG_LIBWEBP_ENCODER)            += libwebpenc_common.o libwebpenc.o
  65.  OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER)       += libwebpenc_common.o libwebpenc_animencoder.o
  66.  OBJS-$(CONFIG_LIBX262_ENCODER)            += libx264.o
  67. diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
  68. index cd4f6ecd59..d2ccaffed1 100644
  69. --- a/libavcodec/allcodecs.c
  70. +++ b/libavcodec/allcodecs.c
  71. @@ -811,6 +811,7 @@ extern const FFCodec ff_libvpx_vp8_decoder;
  72.  extern FFCodec ff_libvpx_vp9_encoder;
  73.  extern const FFCodec ff_libvpx_vp9_decoder;
  74.  extern const FFCodec ff_libvvenc_encoder;
  75. +extern const FFCodec ff_libvvdec_decoder;
  76.  /* preferred over libwebp */
  77.  extern const FFCodec ff_libwebp_anim_encoder;
  78.  extern const FFCodec ff_libwebp_encoder;
  79. diff --git a/libavcodec/libvvdec.c b/libavcodec/libvvdec.c
  80. new file mode 100644
  81. index 0000000000..7cb62db28f
  82. --- /dev/null
  83. +++ b/libavcodec/libvvdec.c
  84. @@ -0,0 +1,624 @@
  85. +/*
  86. + * H.266 decoding using the VVdeC library
  87. + *
  88. + * Copyright (C) 2022, Thomas Siedel
  89. + *
  90. + * This file is part of FFmpeg.
  91. + *
  92. + * FFmpeg is free software; you can redistribute it and/or
  93. + * modify it under the terms of the GNU Lesser General Public
  94. + * License as published by the Free Software Foundation; either
  95. + * version 2.1 of the License, or (at your option) any later version.
  96. + *
  97. + * FFmpeg is distributed in the hope that it will be useful,
  98. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  99. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  100. + * Lesser General Public License for more details.
  101. + *
  102. + * You should have received a copy of the GNU Lesser General Public
  103. + * License along with FFmpeg; if not, write to the Free Software
  104. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  105. + */
  106. +
  107. +#include <vvdec/vvdec.h>
  108. +#include <vvdec/version.h>
  109. +
  110. +#include "libavutil/avutil.h"
  111. +#include "libavutil/common.h"
  112. +#include "libavutil/frame.h"
  113. +#include "libavutil/imgutils.h"
  114. +#include "libavutil/log.h"
  115. +#include "libavutil/mastering_display_metadata.h"
  116. +#include "libavutil/opt.h"
  117. +#include "libavutil/pixdesc.h"
  118. +
  119. +#include "avcodec.h"
  120. +#include "cbs_h266.h"
  121. +#include "codec_internal.h"
  122. +#include "decode.h"
  123. +#include "internal.h"
  124. +#include "profiles.h"
  125. +
  126. +#define VVDEC_VERSION_INT  AV_VERSION_INT(VVDEC_VERSION_MAJOR, \
  127. +                                          VVDEC_VERSION_MINOR, \
  128. +                                          VVDEC_VERSION_PATCH)
  129. +
  130. +typedef struct VVdeCContext {
  131. +    AVClass      *av_class;
  132. +    vvdecDecoder *decoder;
  133. +    vvdecParams   params;
  134. +    bool          flush;
  135. +    AVBufferPool *pools[3];     /** Pools for each data plane. */
  136. +    int           pool_size[3];
  137. +    CodedBitstreamContext *cbc;
  138. +    CodedBitstreamFragment current_frame;
  139. +#if VVDEC_VERSION_INT > AV_VERSION_INT(2,3,0)
  140. +    bool          filmgrain;
  141. +#endif
  142. +} VVdeCContext;
  143. +
  144. +
  145. +static void vvdec_log_callback(void *avctx, int level, const char *fmt,
  146. +                               va_list args)
  147. +{
  148. +    vfprintf(level == 1 ? stderr : stdout, fmt, args);
  149. +}
  150. +
  151. +static void *vvdec_buffer_allocator(void *ctx, vvdecComponentType comp,
  152. +                                    uint32_t size, uint32_t alignment,
  153. +                                    void **allocator)
  154. +{
  155. +    AVBufferRef *buf;
  156. +    VVdeCContext *s = ctx;
  157. +    int plane = (int)comp;
  158. +    uint32_t alignedsize = FFALIGN(size, alignment);
  159. +
  160. +    if (plane < 0 || plane > 3)
  161. +        return NULL;
  162. +
  163. +    if (alignedsize != s->pool_size[plane]) {
  164. +        av_buffer_pool_uninit(&s->pools[plane]);
  165. +        s->pools[plane] = av_buffer_pool_init(alignedsize, NULL);
  166. +        if (!s->pools[plane]) {
  167. +            s->pool_size[plane] = 0;
  168. +            return NULL;
  169. +        }
  170. +        s->pool_size[plane] = alignedsize;
  171. +    }
  172. +
  173. +    buf = av_buffer_pool_get(s->pools[plane]);
  174. +    if (!buf)
  175. +        return NULL;
  176. +
  177. +    *allocator = (void *) buf;
  178. +    return buf->data;
  179. +}
  180. +
  181. +static void vvdec_buffer_unref(void *ctx, void *allocator)
  182. +{
  183. +    AVBufferRef *buf = allocator;
  184. +    av_buffer_unref(&buf);
  185. +}
  186. +
  187. +static void vvdec_printParameterInfo(AVCodecContext *avctx, vvdecParams *params)
  188. +{
  189. +    av_log(avctx, AV_LOG_DEBUG, "Version info: vvdec %s ( threads %d)\n",
  190. +           vvdec_get_version(), params->threads);
  191. +}
  192. +
  193. +static int vvdec_set_pix_fmt(AVCodecContext *avctx, vvdecFrame *frame)
  194. +{
  195. +    if (NULL != frame->picAttributes && NULL != frame->picAttributes->vui &&
  196. +        frame->picAttributes->vui->colourDescriptionPresentFlag) {
  197. +        avctx->color_trc       = frame->picAttributes->vui->transferCharacteristics;
  198. +        avctx->color_primaries = frame->picAttributes->vui->colourPrimaries;
  199. +        avctx->colorspace      = frame->picAttributes->vui->matrixCoefficients;
  200. +    } else {
  201. +        avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
  202. +        avctx->color_trc       = AVCOL_TRC_UNSPECIFIED;
  203. +        avctx->colorspace      = AVCOL_SPC_UNSPECIFIED;
  204. +    }
  205. +
  206. +    if (NULL != frame->picAttributes && NULL != frame->picAttributes->vui &&
  207. +        frame->picAttributes->vui->videoSignalTypePresentFlag) {
  208. +        avctx->color_range = frame->picAttributes->vui->videoFullRangeFlag ?
  209. +                             AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
  210. +    } else {
  211. +        avctx->color_range = AVCOL_RANGE_MPEG;
  212. +    }
  213. +
  214. +    switch (frame->colorFormat) {
  215. +    case VVDEC_CF_YUV420_PLANAR:
  216. +    case VVDEC_CF_YUV400_PLANAR:
  217. +        if (frame->bitDepth == 8) {
  218. +            avctx->pix_fmt = frame->numPlanes == 1 ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_YUV420P;
  219. +            avctx->profile = AV_PROFILE_VVC_MAIN_10;
  220. +            return 0;
  221. +        } else if (frame->bitDepth == 10) {
  222. +            avctx->pix_fmt = frame->numPlanes == 1 ? AV_PIX_FMT_GRAY10 : AV_PIX_FMT_YUV420P10;
  223. +            avctx->profile = AV_PROFILE_VVC_MAIN_10;
  224. +            return 0;
  225. +        } else {
  226. +            return AVERROR_INVALIDDATA;
  227. +        }
  228. +    case VVDEC_CF_YUV422_PLANAR:
  229. +    case VVDEC_CF_YUV444_PLANAR:
  230. +        if (frame->bitDepth == 8) {
  231. +            avctx->pix_fmt = frame->colorFormat == VVDEC_CF_YUV444_PLANAR ?
  232. +                             AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUV422P;
  233. +            if (avctx->profile != AV_PROFILE_VVC_MAIN_10_444)
  234. +                avctx->profile = AV_PROFILE_VVC_MAIN_10_444;
  235. +            return 0;
  236. +        } else if (frame->bitDepth == 10) {
  237. +            avctx->pix_fmt = frame->colorFormat == VVDEC_CF_YUV444_PLANAR ?
  238. +                             AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
  239. +            if (avctx->profile != AV_PROFILE_VVC_MAIN_10_444)
  240. +                avctx->profile = AV_PROFILE_VVC_MAIN_10_444;
  241. +            return 0;
  242. +        } else {
  243. +            return AVERROR_INVALIDDATA;
  244. +        }
  245. +    default:
  246. +        return AVERROR_INVALIDDATA;
  247. +    }
  248. +}
  249. +
  250. +static int set_side_data(AVCodecContext *avctx, AVFrame *avframe,
  251. +                         vvdecFrame *frame)
  252. +{
  253. +    vvdecSEI *sei;
  254. +    VVdeCContext *s = avctx->priv_data;
  255. +
  256. +    sei = vvdec_find_frame_sei(s->decoder, VVDEC_MASTERING_DISPLAY_COLOUR_VOLUME, frame);
  257. +    if (sei) {
  258. +        /* VVC uses a g,b,r ordering, which we convert to a more natural r,g,b */
  259. +        const int mapping[3] = { 2, 0, 1 };
  260. +        const int chroma_den = 50000;
  261. +        const int luma_den = 10000;
  262. +        int i;
  263. +        vvdecSEIMasteringDisplayColourVolume *p;
  264. +        AVMasteringDisplayMetadata *metadata =
  265. +            av_mastering_display_metadata_create_side_data(avframe);
  266. +        p = (vvdecSEIMasteringDisplayColourVolume *) (sei->payload);
  267. +        if (p && metadata) {
  268. +            for (i = 0; i < 3; i++) {
  269. +                const int j = mapping[i];
  270. +                metadata->display_primaries[i][0].num = p->primaries[j][0];
  271. +                metadata->display_primaries[i][0].den = chroma_den;
  272. +                metadata->display_primaries[i][1].num = p->primaries[j][1];
  273. +                metadata->display_primaries[i][1].den = chroma_den;
  274. +            }
  275. +            metadata->white_point[0].num = p->whitePoint[0];
  276. +            metadata->white_point[0].den = chroma_den;
  277. +            metadata->white_point[1].num = p->whitePoint[1];
  278. +            metadata->white_point[1].den = chroma_den;
  279. +
  280. +            metadata->max_luminance.num = p->maxLuminance;
  281. +            metadata->max_luminance.den = luma_den;
  282. +            metadata->min_luminance.num = p->minLuminance;
  283. +            metadata->min_luminance.den = luma_den;
  284. +            metadata->has_luminance = 1;
  285. +            metadata->has_primaries = 1;
  286. +
  287. +            av_log(avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n");
  288. +            av_log(avctx, AV_LOG_DEBUG,
  289. +                   "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n",
  290. +                   av_q2d(metadata->display_primaries[0][0]),
  291. +                   av_q2d(metadata->display_primaries[0][1]),
  292. +                   av_q2d(metadata->display_primaries[1][0]),
  293. +                   av_q2d(metadata->display_primaries[1][1]),
  294. +                   av_q2d(metadata->display_primaries[2][0]),
  295. +                   av_q2d(metadata->display_primaries[2][1]),
  296. +                   av_q2d(metadata->white_point[0]),
  297. +                   av_q2d(metadata->white_point[1]));
  298. +            av_log(avctx, AV_LOG_DEBUG, "min_luminance=%f, max_luminance=%f\n",
  299. +                   av_q2d(metadata->min_luminance),
  300. +                   av_q2d(metadata->max_luminance));
  301. +        }
  302. +        return 0;
  303. +    }
  304. +
  305. +    sei = vvdec_find_frame_sei(s->decoder, VVDEC_CONTENT_LIGHT_LEVEL_INFO,
  306. +                               frame);
  307. +    if (sei) {
  308. +        vvdecSEIContentLightLevelInfo *p = NULL;
  309. +        AVContentLightMetadata *light = av_content_light_metadata_create_side_data(avframe);
  310. +        p = (vvdecSEIContentLightLevelInfo *) (sei->payload);
  311. +        if (p && light) {
  312. +            light->MaxCLL  = p->maxContentLightLevel;
  313. +            light->MaxFALL = p->maxPicAverageLightLevel;
  314. +        }
  315. +
  316. +        av_log(avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n");
  317. +        av_log(avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", light->MaxCLL, light->MaxFALL);
  318. +    }
  319. +
  320. +    return 0;
  321. +}
  322. +
  323. +static int set_pixel_format(AVCodecContext *avctx, const H266RawSPS *sps)
  324. +{
  325. +    enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
  326. +    const AVPixFmtDescriptor *desc;
  327. +    switch (sps->sps_bitdepth_minus8 + 8) {
  328. +    case 8:
  329. +        if (sps->sps_chroma_format_idc == 0)
  330. +            pix_fmt = AV_PIX_FMT_GRAY8;
  331. +        if (sps->sps_chroma_format_idc == 1)
  332. +            pix_fmt = AV_PIX_FMT_YUV420P;
  333. +        if (sps->sps_chroma_format_idc == 2)
  334. +            pix_fmt = AV_PIX_FMT_YUV422P;
  335. +        if (sps->sps_chroma_format_idc == 3)
  336. +            pix_fmt = AV_PIX_FMT_YUV444P;
  337. +        break;
  338. +    case 9:
  339. +        if (sps->sps_chroma_format_idc == 0)
  340. +            pix_fmt = AV_PIX_FMT_GRAY9;
  341. +        if (sps->sps_chroma_format_idc == 1)
  342. +            pix_fmt = AV_PIX_FMT_YUV420P9;
  343. +        if (sps->sps_chroma_format_idc == 2)
  344. +            pix_fmt = AV_PIX_FMT_YUV422P9;
  345. +        if (sps->sps_chroma_format_idc == 3)
  346. +            pix_fmt = AV_PIX_FMT_YUV444P9;
  347. +        break;
  348. +    case 10:
  349. +        if (sps->sps_chroma_format_idc == 0)
  350. +            pix_fmt = AV_PIX_FMT_GRAY10;
  351. +        if (sps->sps_chroma_format_idc == 1)
  352. +            pix_fmt = AV_PIX_FMT_YUV420P10;
  353. +        if (sps->sps_chroma_format_idc == 2)
  354. +            pix_fmt = AV_PIX_FMT_YUV422P10;
  355. +        if (sps->sps_chroma_format_idc == 3)
  356. +            pix_fmt = AV_PIX_FMT_YUV444P10;
  357. +        break;
  358. +    case 12:
  359. +        if (sps->sps_chroma_format_idc == 0)
  360. +            pix_fmt = AV_PIX_FMT_GRAY12;
  361. +        if (sps->sps_chroma_format_idc == 1)
  362. +            pix_fmt = AV_PIX_FMT_YUV420P12;
  363. +        if (sps->sps_chroma_format_idc == 2)
  364. +            pix_fmt = AV_PIX_FMT_YUV422P12;
  365. +        if (sps->sps_chroma_format_idc == 3)
  366. +            pix_fmt = AV_PIX_FMT_YUV444P12;
  367. +        break;
  368. +    default:
  369. +        av_log(avctx, AV_LOG_ERROR,
  370. +               "The following bit-depths are currently specified: 8, 9, 10 and 12 bits, "
  371. +               "sps_chroma_format_idc is %d, depth is %d\n",
  372. +               sps->sps_chroma_format_idc, sps->sps_bitdepth_minus8 + 8);
  373. +        return AVERROR_INVALIDDATA;
  374. +    }
  375. +
  376. +    desc = av_pix_fmt_desc_get(pix_fmt);
  377. +    if (!desc)
  378. +        return AVERROR(EINVAL);
  379. +
  380. +    avctx->pix_fmt = pix_fmt;
  381. +
  382. +    return 0;
  383. +}
  384. +
  385. +static void export_stream_params(AVCodecContext *avctx, const H266RawSPS *sps)
  386. +{
  387. +    avctx->coded_width  = sps->sps_pic_width_max_in_luma_samples;
  388. +    avctx->coded_height = sps->sps_pic_height_max_in_luma_samples;
  389. +    avctx->width        = sps->sps_pic_width_max_in_luma_samples -
  390. +                          sps->sps_conf_win_left_offset -
  391. +                          sps->sps_conf_win_right_offset;
  392. +    avctx->height       = sps->sps_pic_height_max_in_luma_samples -
  393. +                          sps->sps_conf_win_top_offset -
  394. +                          sps->sps_conf_win_bottom_offset;
  395. +    avctx->has_b_frames = sps->sps_max_sublayers_minus1 + 1;
  396. +    avctx->profile      = sps->profile_tier_level.general_profile_idc;
  397. +    avctx->level        = sps->profile_tier_level.general_level_idc;
  398. +
  399. +    set_pixel_format( avctx, sps);
  400. +
  401. +    avctx->color_range = sps->vui.vui_full_range_flag ? AVCOL_RANGE_JPEG :
  402. +                         AVCOL_RANGE_MPEG;
  403. +
  404. +    if (sps->vui.vui_colour_description_present_flag) {
  405. +        avctx->color_primaries = sps->vui.vui_colour_primaries;
  406. +        avctx->color_trc       = sps->vui.vui_transfer_characteristics;
  407. +        avctx->colorspace      = sps->vui.vui_matrix_coeffs;
  408. +    } else {
  409. +        avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
  410. +        avctx->color_trc       = AVCOL_TRC_UNSPECIFIED;
  411. +        avctx->colorspace      = AVCOL_SPC_UNSPECIFIED;
  412. +    }
  413. +
  414. +    avctx->chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED;
  415. +    if (sps->sps_chroma_format_idc == 1) {
  416. +        if (sps->vui.vui_chroma_loc_info_present_flag) {
  417. +            if (sps->vui.vui_chroma_sample_loc_type_top_field <= 5)
  418. +                avctx->chroma_sample_location =
  419. +                    sps->vui.vui_chroma_sample_loc_type_top_field + 1;
  420. +        } else
  421. +            avctx->chroma_sample_location = AVCHROMA_LOC_LEFT;
  422. +    }
  423. +
  424. +    if (sps->sps_timing_hrd_params_present_flag &&
  425. +        sps->sps_general_timing_hrd_parameters.num_units_in_tick &&
  426. +        sps->sps_general_timing_hrd_parameters.time_scale) {
  427. +        av_reduce(&avctx->framerate.den, &avctx->framerate.num,
  428. +                  sps->sps_general_timing_hrd_parameters.num_units_in_tick,
  429. +                  sps->sps_general_timing_hrd_parameters.time_scale, INT_MAX);
  430. +    }
  431. +}
  432. +
  433. +static av_cold int vvdec_dec_init(AVCodecContext *avctx)
  434. +{
  435. +    int i, loglevel, ret;
  436. +    VVdeCContext *s = avctx->priv_data;
  437. +
  438. +    vvdec_params_default(&s->params);
  439. +    s->params.logLevel = VVDEC_DETAILS;
  440. +
  441. +    loglevel = av_log_get_level();
  442. +    if (loglevel >= AV_LOG_DEBUG)
  443. +        s->params.logLevel = VVDEC_DETAILS;
  444. +    else if (loglevel >= AV_LOG_VERBOSE)
  445. +        s->params.logLevel = VVDEC_INFO;
  446. +    else if (loglevel >= AV_LOG_INFO)
  447. +        s->params.logLevel = VVDEC_WARNING;
  448. +    else
  449. +        s->params.logLevel = VVDEC_SILENT;
  450. +
  451. +    if (avctx->thread_count > 0)
  452. +        s->params.threads = avctx->thread_count;
  453. +    else
  454. +        s->params.threads = -1; /* get max cpus */
  455. +
  456. +#if VVDEC_VERSION_INT > AV_VERSION_INT(2,3,0)
  457. +    s->params.filmGrainSynthesis = s->filmgrain;
  458. +#endif
  459. +
  460. +    vvdec_printParameterInfo(avctx, &s->params);
  461. +
  462. +    /* using buffer allocation by using AVBufferPool */
  463. +    s->params.opaque = avctx->priv_data;
  464. +    s->decoder = vvdec_decoder_open_with_allocator(&s->params, vvdec_buffer_allocator, vvdec_buffer_unref);
  465. +    if (!s->decoder) {
  466. +        av_log(avctx, AV_LOG_ERROR, "cannot init vvdec decoder\n");
  467. +        return AVERROR_EXTERNAL;
  468. +    }
  469. +
  470. +    vvdec_set_logging_callback(s->decoder, vvdec_log_callback);
  471. +
  472. +    s->flush = false;
  473. +
  474. +    for (i = 0; i < FF_ARRAY_ELEMS(s->pools); i++) {
  475. +        s->pools[i] = NULL;
  476. +        s->pool_size[i] = 0;
  477. +    }
  478. +
  479. +    ret = ff_cbs_init(&s->cbc, AV_CODEC_ID_VVC, avctx);
  480. +    if (ret)
  481. +        return ret;
  482. +
  483. +    if (!avctx->internal->is_copy) {
  484. +        if (avctx->extradata_size > 0 && avctx->extradata) {
  485. +            const CodedBitstreamH266Context *h266 = s->cbc->priv_data;
  486. +            ff_cbs_fragment_reset(&s->current_frame);
  487. +            ret = ff_cbs_read_extradata_from_codec(s->cbc, &s->current_frame, avctx);
  488. +            if (ret < 0)
  489. +                return ret;
  490. +
  491. +            if (h266->sps[0] != NULL)
  492. +                export_stream_params(avctx, h266->sps[0]);
  493. +        }
  494. +    }
  495. +
  496. +    return 0;
  497. +}
  498. +
  499. +static av_cold int vvdec_dec_close(AVCodecContext *avctx)
  500. +{
  501. +    VVdeCContext *s = avctx->priv_data;
  502. +
  503. +    for (int i = 0; i < FF_ARRAY_ELEMS(s->pools); i++) {
  504. +        av_buffer_pool_uninit(&s->pools[i]);
  505. +        s->pool_size[i] = 0;
  506. +    }
  507. +
  508. +    ff_cbs_fragment_free(&s->current_frame);
  509. +    ff_cbs_close(&s->cbc);
  510. +
  511. +    s->flush = false;
  512. +
  513. +    if (0 != vvdec_decoder_close(s->decoder))
  514. +        return AVERROR_EXTERNAL;
  515. +
  516. +    return 0;
  517. +}
  518. +
  519. +static av_cold int vvdec_dec_frame(AVCodecContext *avctx, AVFrame *data,
  520. +                                   int *got_frame, AVPacket *avpkt)
  521. +{
  522. +    VVdeCContext *s = avctx->priv_data;
  523. +    AVFrame *avframe = data;
  524. +
  525. +    int ret = 0;
  526. +    vvdecFrame *frame = NULL;
  527. +
  528. +    if (avframe) {
  529. +        if (!avpkt->size && !s->flush)
  530. +            s->flush = true;
  531. +
  532. +        if (s->flush)
  533. +            ret = vvdec_flush(s->decoder, &frame);
  534. +        else {
  535. +            vvdecAccessUnit accessUnit;
  536. +            vvdec_accessUnit_default(&accessUnit);
  537. +            accessUnit.payload = avpkt->data;
  538. +            accessUnit.payloadSize = avpkt->size;
  539. +            accessUnit.payloadUsedSize = avpkt->size;
  540. +
  541. +            accessUnit.cts = avpkt->pts;
  542. +            accessUnit.ctsValid = true;
  543. +            accessUnit.dts = avpkt->dts;
  544. +            accessUnit.dtsValid = true;
  545. +
  546. +            ret = vvdec_decode(s->decoder, &accessUnit, &frame);
  547. +        }
  548. +
  549. +        if (ret < 0) {
  550. +            if (ret == VVDEC_EOF)
  551. +                s->flush = true;
  552. +            else if (ret != VVDEC_TRY_AGAIN) {
  553. +                av_log(avctx, AV_LOG_ERROR, "error in vvdec_decode - ret:%d - %s %s\n", ret,
  554. +                       vvdec_get_last_error(s->decoder), vvdec_get_last_additional_error( s->decoder));
  555. +                ret = AVERROR_EXTERNAL;
  556. +                goto fail;
  557. +            }
  558. +        } else if (NULL != frame) {
  559. +            const uint8_t *src_data[4] = { frame->planes[0].ptr,
  560. +                                           frame->planes[1].ptr,
  561. +                                           frame->planes[2].ptr, NULL
  562. +                                         };
  563. +            const int src_linesizes[4] = { (int) frame->planes[0].stride,
  564. +                                           (int) frame->planes[1].stride,
  565. +                                           (int) frame->planes[2].stride, 0
  566. +                                         };
  567. +
  568. +            if ((ret = vvdec_set_pix_fmt(avctx, frame)) < 0) {
  569. +                av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n",
  570. +                       frame->colorFormat, frame->bitDepth);
  571. +                goto fail;
  572. +            }
  573. +
  574. +            if ((int) frame->width != avctx->width ||
  575. +                (int) frame->height != avctx->height) {
  576. +                av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n",
  577. +                       avctx->width, avctx->height, frame->width, frame->height);
  578. +
  579. +                ret = ff_set_dimensions(avctx, frame->width, frame->height);
  580. +                if (ret < 0)
  581. +                    goto fail;
  582. +            }
  583. +
  584. +            if (frame->planes[0].allocator)
  585. +                avframe->buf[0] =
  586. +                    av_buffer_ref((AVBufferRef *) frame->planes[0].allocator);
  587. +            if (frame->planes[1].allocator)
  588. +                avframe->buf[1] =
  589. +                    av_buffer_ref((AVBufferRef *) frame->planes[1].allocator);
  590. +            if (frame->planes[2].allocator)
  591. +                avframe->buf[2] =
  592. +                    av_buffer_ref((AVBufferRef *) frame->planes[2].allocator);
  593. +
  594. +            for (int i = 0; i < 4; i++) {
  595. +                avframe->data[i] = (uint8_t *) src_data[i];
  596. +                avframe->linesize[i] = src_linesizes[i];
  597. +            }
  598. +
  599. +            ret = ff_decode_frame_props(avctx, avframe);
  600. +            if (ret < 0)
  601. +                goto fail;
  602. +
  603. +            if (frame->picAttributes) {
  604. +                if (frame->picAttributes->isRefPic)
  605. +                    avframe->flags |= AV_FRAME_FLAG_KEY;
  606. +                else
  607. +                    avframe->flags &= ~AV_FRAME_FLAG_KEY;
  608. +
  609. +                avframe->pict_type = (frame->picAttributes->sliceType != VVDEC_SLICETYPE_UNKNOWN) ?
  610. +                                     frame->picAttributes->sliceType + 1 : AV_PICTURE_TYPE_NONE;
  611. +            }
  612. +
  613. +            if (frame->ctsValid)
  614. +                avframe->pts = frame->cts;
  615. +
  616. +            ret = set_side_data(avctx, avframe, frame);
  617. +            if (ret < 0)
  618. +                goto fail;
  619. +
  620. +            if (0 != vvdec_frame_unref(s->decoder, frame))
  621. +                av_log(avctx, AV_LOG_ERROR, "cannot free picture memory\n");
  622. +
  623. +            *got_frame = 1;
  624. +        }
  625. +    }
  626. +
  627. +    return avpkt->size;
  628. +
  629. +fail:
  630. +    if (frame) {
  631. +        if (frame->planes[0].allocator)
  632. +            av_buffer_unref((AVBufferRef **) &frame->planes[0].allocator);
  633. +        if (frame->planes[1].allocator)
  634. +            av_buffer_unref((AVBufferRef **) &frame->planes[1].allocator);
  635. +        if (frame->planes[2].allocator)
  636. +            av_buffer_unref((AVBufferRef **) &frame->planes[2].allocator);
  637. +
  638. +        vvdec_frame_unref(s->decoder, frame);
  639. +    }
  640. +    return ret;
  641. +}
  642. +
  643. +static av_cold void vvdec_dec_flush(AVCodecContext *avctx)
  644. +{
  645. +    VVdeCContext *s = avctx->priv_data;
  646. +
  647. +    if (0 != vvdec_decoder_close(s->decoder))
  648. +        av_log(avctx, AV_LOG_ERROR, "cannot close during flush\n");
  649. +
  650. +    s->decoder = vvdec_decoder_open_with_allocator(&s->params, vvdec_buffer_allocator, vvdec_buffer_unref);
  651. +    if (!s->decoder)
  652. +        av_log(avctx, AV_LOG_ERROR, "cannot reinit during flush\n");
  653. +
  654. +    vvdec_set_logging_callback(s->decoder, vvdec_log_callback);
  655. +
  656. +    s->flush = false;
  657. +}
  658. +
  659. +static const enum AVPixelFormat pix_fmts_vvdec[] = {
  660. +    AV_PIX_FMT_GRAY8,
  661. +    AV_PIX_FMT_GRAY10,
  662. +    AV_PIX_FMT_YUV420P,
  663. +    AV_PIX_FMT_YUV422P,
  664. +    AV_PIX_FMT_YUV444P,
  665. +    AV_PIX_FMT_YUV420P10,
  666. +    AV_PIX_FMT_YUV422P10,
  667. +    AV_PIX_FMT_YUV444P10,
  668. +    AV_PIX_FMT_NONE
  669. +};
  670. +
  671. +#if VVDEC_VERSION_INT > AV_VERSION_INT(2,3,0)
  672. +
  673. +#define OFFSET(x) offsetof(VVdeCContext, x)
  674. +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  675. +static const AVOption options[] = {
  676. +    { "filmgrain",    "set usage of filemgrain SEI", OFFSET(filmgrain), AV_OPT_TYPE_BOOL, {.i64 = 1},  0, 1, VE},
  677. +    {NULL}
  678. +};
  679. +
  680. +#endif
  681. +
  682. +static const AVClass class = {
  683. +    .class_name = "libvvdec",
  684. +    .item_name  = av_default_item_name,
  685. +#if VVDEC_VERSION_INT > AV_VERSION_INT(2,3,0)
  686. +    .option     = options,
  687. +#endif
  688. +    .version    = LIBAVUTIL_VERSION_INT,
  689. +};
  690. +
  691. +const FFCodec ff_libvvdec_decoder = {
  692. +    .p.name         = "libvvdec",
  693. +    CODEC_LONG_NAME("libvvdec H.266 / VVC"),
  694. +    .p.type         = AVMEDIA_TYPE_VIDEO,
  695. +    .p.id           = AV_CODEC_ID_VVC,
  696. +    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
  697. +    .p.profiles     = NULL_IF_CONFIG_SMALL(ff_vvc_profiles),
  698. +    .p.priv_class   = &class,
  699. +    .p.wrapper_name = "libvvdec",
  700. +    .priv_data_size = sizeof(VVdeCContext),
  701. +    .p.pix_fmts     = pix_fmts_vvdec,
  702. +    .init           = vvdec_dec_init,
  703. +    FF_CODEC_DECODE_CB(vvdec_dec_frame),
  704. +    .close          = vvdec_dec_close,
  705. +    .flush          = vvdec_dec_flush,
  706. +    .bsfs           = "vvc_mp4toannexb",
  707. +    .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
  708. +};
  709. --
  710. 2.43.0
  711.  
Advertisement
Add Comment
Please, Sign In to add comment