ffmpeg-cvslog
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
February 2026
- 1 participants
- 201 discussions
This is an automated email from the git hooks/post-receive script.
Git pushed a change to branch master
in repository ffmpeg.
from 00d3417b71 avcodec/d3d12va_encode: Add H264 entropy coder parameter support
new 86d2fae59f avcodec: use int instead of enum for AVOption fields
new fddf881c06 avformat: use int instead of enum for AVOption fields
new 6b949407cb avfilter: use int instead of enum for AVOption fields
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
libavcodec/amfenc.h | 6 ++++--
libavcodec/bsf/filter_units.c | 3 ++-
libavcodec/hap.h | 3 ++-
libavcodec/huffyuvenc.c | 3 ++-
libavfilter/af_loudnorm.c | 3 ++-
libavfilter/vf_blend.c | 3 ++-
libavfilter/vf_blend_vulkan.c | 3 ++-
libavfilter/vf_colorspace.c | 9 ++++++---
libavfilter/vf_colorspace_cuda.c | 3 ++-
libavfilter/vf_displace.c | 3 ++-
libavfilter/vf_framepack.c | 3 ++-
libavfilter/vf_libplacebo.c | 3 ++-
libavfilter/vf_minterpolate.c | 3 ++-
libavfilter/vf_tiltandshift.c | 4 ++--
libavfilter/vf_tonemap.c | 3 ++-
libavfilter/vf_tonemap_opencl.c | 3 ++-
libavfilter/vsrc_perlin.c | 3 ++-
libavfilter/vsrc_testsrc_vulkan.c | 3 ++-
libavformat/chromaprint.c | 3 ++-
libavformat/libsrt.c | 3 ++-
20 files changed, 46 insertions(+), 24 deletions(-)
2
3
[ffmpeg] avcodec/d3d12va_encode: Add H264 entropy coder parameter support (branch master)
by Ling, Edison 26 Feb '26
by Ling, Edison 26 Feb '26
26 Feb '26
This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 00d3417b71 avcodec/d3d12va_encode: Add H264 entropy coder parameter support
00d3417b71 is described below
commit 00d3417b716e9dabcbf6a00aea08384f91b9cbb0
Author: Ling, Edison <Edison.Ling+amdeng(a)amd.com>
AuthorDate: Fri Jan 9 16:49:33 2026 -0500
Commit: Tong Wu <wutong1208(a)outlook.com>
CommitDate: Thu Feb 26 02:19:21 2026 +0000
avcodec/d3d12va_encode: Add H264 entropy coder parameter support
Add parameter `coder` for users to select entropy coding in D3D12 H264
encoding.
Named constants `cabac` (1) and `cavlc` (0) are supported.
Default is CABAC (1). If the driver does not support CABAC, a warning is
logged and encoding falls back to CAVLC.
Usage:
CABAC (default): `-coder cabac` or `-coder 1`
CAVLC: `-coder cavlc` or `-coder 0`
Sample command line:
```
ffmpeg -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v h264_d3d12va -coder cavlc -y output.mp4
```
---
libavcodec/d3d12va_encode_h264.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/libavcodec/d3d12va_encode_h264.c b/libavcodec/d3d12va_encode_h264.c
index bd15856f0e..dd745c6895 100644
--- a/libavcodec/d3d12va_encode_h264.c
+++ b/libavcodec/d3d12va_encode_h264.c
@@ -294,11 +294,6 @@ static int d3d12va_encode_h264_get_encoder_caps(AVCodecContext *avctx)
config->ConfigurationFlags = D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_NONE;
- if (h264_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_CABAC_ENCODING_SUPPORT) {
- config->ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_ENABLE_CABAC_ENCODING;
- priv->unit_opts.cabac = 1;
- }
-
// Deblocking filter configuration
if (priv->deblock == 1) {
if (h264_caps.DisableDeblockingFilterSupportedModes & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_SLICES_DEBLOCKING_MODE_FLAG_0_ALL_LUMA_CHROMA_SLICE_BLOCK_EDGES_ALWAYS_FILTERED) {
@@ -316,6 +311,16 @@ static int d3d12va_encode_h264_get_encoder_caps(AVCodecContext *avctx)
}
}
+ // Entropy coder configuration
+ if (priv->unit_opts.cabac) {
+ if (h264_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_CABAC_ENCODING_SUPPORT) {
+ config->ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_ENABLE_CABAC_ENCODING;
+ } else {
+ av_log(avctx, AV_LOG_WARNING, "CABAC entropy coding is not supported by the driver, falling back to CAVLC.\n");
+ priv->unit_opts.cabac = 0;
+ }
+ }
+
base_ctx->surface_width = FFALIGN(avctx->width, 16);
base_ctx->surface_height = FFALIGN(avctx->height, 16);
@@ -643,6 +648,11 @@ static const AVOption d3d12va_encode_h264_options[] = {
{ "deblock", "Deblocking filter mode",
OFFSET(deblock), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, FLAGS },
+ { "coder", "Entropy coder type",
+ OFFSET(unit_opts.cabac), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "coder" },
+ { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" },
+ { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" },
+
{ NULL },
};
1
0
25 Feb '26
This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 5ba2525c7a avcodec/libsvtav1: enable 2-pass encoding
5ba2525c7a is described below
commit 5ba2525c7affc29cbd99e6266946b382d3fffe8b
Author: Werner Robitza <werner.robitza(a)gmail.com>
AuthorDate: Wed Feb 25 16:43:53 2026 +0100
Commit: Werner Robitza <werner.robitza(a)gmail.com>
CommitDate: Wed Feb 25 16:43:53 2026 +0100
avcodec/libsvtav1: enable 2-pass encoding
This patch enables two-pass encoding for libsvtav1 by implementing
support for AV_CODEC_FLAG_PASS1 and AV_CODEC_FLAG_PASS2.
Previously, users requiring two-pass encoding with SVT-AV1 had to use
the standalone SvtAv1EncApp tool. This patch allows 2-pass encoding
directly through FFmpeg.
Based on patch by Fredrik Lundkvist, with review feedback from James
Almer and Andreas Rheinhardt.
See: https://ffmpeg.org/pipermail/ffmpeg-devel/2024-May/327452.html
Changes:
- Use AV_BASE64_DECODE_SIZE macro for buffer size calculation
- Allocate own buffer for rc_stats_buffer (non-ownership pointer)
- Error handling with buffer cleanup
Signed-off-by: Werner Robitza <werner.robitza(a)gmail.com>
---
libavcodec/libsvtav1.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 80 insertions(+), 3 deletions(-)
diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
index 90c61b98a1..fec2ed596e 100644
--- a/libavcodec/libsvtav1.c
+++ b/libavcodec/libsvtav1.c
@@ -21,6 +21,7 @@
*/
#include <stdint.h>
+#include <inttypes.h>
#include <EbSvtAv1ErrorCodes.h>
#include <EbSvtAv1Enc.h>
#include <EbSvtAv1Metadata.h>
@@ -28,6 +29,7 @@
#include "libavutil/common.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"
+#include "libavutil/base64.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mastering_display_metadata.h"
#include "libavutil/mem.h"
@@ -65,6 +67,8 @@ typedef struct SvtContext {
DOVIContext dovi;
+ uint8_t *stats_buf;
+
// User options.
AVDictionary *svtav1_opts;
int enc_mode;
@@ -341,6 +345,42 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param,
return AVERROR(ENOSYS);
}
#endif
+ if (avctx->flags & AV_CODEC_FLAG_PASS2) {
+ int stats_sz;
+
+ if (!avctx->stats_in) {
+ av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
+ return AVERROR(EINVAL);
+ }
+
+ stats_sz = AV_BASE64_DECODE_SIZE(strlen(avctx->stats_in));
+ if (stats_sz <= 0) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid stats file size\n");
+ return AVERROR(EINVAL);
+ }
+
+ svt_enc->stats_buf = av_malloc(stats_sz);
+ if (!svt_enc->stats_buf) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate stats buffer\n");
+ return AVERROR(ENOMEM);
+ }
+
+ stats_sz = av_base64_decode(svt_enc->stats_buf, avctx->stats_in, stats_sz);
+ if (stats_sz < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to decode stats file\n");
+ av_freep(&svt_enc->stats_buf);
+ return AVERROR(EINVAL);
+ }
+
+ param->rc_stats_buffer.buf = svt_enc->stats_buf;
+ param->rc_stats_buffer.sz = stats_sz;
+ param->pass = 2;
+
+ av_log(avctx, AV_LOG_VERBOSE, "Using %d bytes of 2-pass stats\n", stats_sz);
+ } else if (avctx->flags & AV_CODEC_FLAG_PASS1) {
+ param->pass = 1;
+ av_log(avctx, AV_LOG_VERBOSE, "Starting first pass\n");
+ }
param->source_width = avctx->width;
param->source_height = avctx->height;
@@ -618,9 +658,45 @@ static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
#if SVT_AV1_CHECK_VERSION(2, 0, 0)
if (headerPtr->flags & EB_BUFFERFLAG_EOS) {
- svt_enc->eos_flag = EOS_RECEIVED;
- svt_av1_enc_release_out_buffer(&headerPtr);
- return AVERROR_EOF;
+ if (avctx->flags & AV_CODEC_FLAG_PASS1) {
+ SvtAv1FixedBuf first_pass_stats = { 0 };
+ EbErrorType svt_ret_stats;
+ int b64_size;
+
+ svt_ret_stats = svt_av1_enc_get_stream_info(
+ svt_enc->svt_handle,
+ SVT_AV1_STREAM_INFO_FIRST_PASS_STATS_OUT,
+ &first_pass_stats);
+
+ if (svt_ret_stats != EB_ErrorNone) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to get first pass stats\n");
+ svt_av1_enc_release_out_buffer(&headerPtr);
+ return AVERROR_EXTERNAL;
+ }
+
+ if (first_pass_stats.sz > 0 && first_pass_stats.buf) {
+ b64_size = AV_BASE64_SIZE(first_pass_stats.sz);
+ avctx->stats_out = av_malloc(b64_size);
+ if (!avctx->stats_out) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to allocate stats output buffer\n");
+ svt_av1_enc_release_out_buffer(&headerPtr);
+ return AVERROR(ENOMEM);
+ }
+
+ av_base64_encode(avctx->stats_out, b64_size,
+ first_pass_stats.buf, first_pass_stats.sz);
+
+ av_log(avctx, AV_LOG_VERBOSE,
+ "First pass stats: %"PRIu64" bytes, encoded to %d bytes\n",
+ first_pass_stats.sz, b64_size);
+ }
+ }
+
+ svt_enc->eos_flag = EOS_RECEIVED;
+ svt_av1_enc_release_out_buffer(&headerPtr);
+ return AVERROR_EOF;
}
#endif
@@ -688,6 +764,7 @@ static av_cold int eb_enc_close(AVCodecContext *avctx)
av_buffer_pool_uninit(&svt_enc->pool);
av_frame_free(&svt_enc->frame);
ff_dovi_ctx_unref(&svt_enc->dovi);
+ av_freep(&svt_enc->stats_buf);
return 0;
}
1
0
This is an automated email from the git hooks/post-receive script.
Git pushed a change to branch master
in repository ffmpeg.
from dc65dcec22 avcodec/vvc/inter: Combine offsets early
new 34cf7790ef tests/checkasm/h264chroma: Fix initialization, range of values
new e9c2f19e01 tests/checkasm/h264chroma: Add bit depth to error output
new 13e95746ea tests/checkasm/h264chroma: Don't overalign
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
tests/checkasm/h264chroma.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
2
3
25 Feb '26
This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new dc65dcec22 avcodec/vvc/inter: Combine offsets early
dc65dcec22 is described below
commit dc65dcec220d33ecbdb3442dfaf00f17f2dc2b0c
Author: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
AuthorDate: Fri Feb 20 18:24:24 2026 +0100
Commit: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
CommitDate: Wed Feb 25 12:08:33 2026 +0100
avcodec/vvc/inter: Combine offsets early
For bi-predicted weighted averages, only the sum
of the two offsets is ever used, so add the two early.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/aarch64/vvc/dsp_init.c | 4 ++--
libavcodec/riscv/vvc/dsp_init.c | 2 +-
libavcodec/riscv/vvc/mc_rvv.S | 2 --
libavcodec/vvc/dsp.h | 2 +-
libavcodec/vvc/inter.c | 10 +++++-----
libavcodec/vvc/inter_template.c | 4 ++--
libavcodec/x86/vvc/dsp_init.c | 2 +-
libavcodec/x86/vvc/mc.asm | 5 ++---
tests/checkasm/vvc_mc.c | 8 ++++----
9 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/libavcodec/aarch64/vvc/dsp_init.c b/libavcodec/aarch64/vvc/dsp_init.c
index bc2677945e..570070a28c 100644
--- a/libavcodec/aarch64/vvc/dsp_init.c
+++ b/libavcodec/aarch64/vvc/dsp_init.c
@@ -107,10 +107,10 @@ void ff_vvc_w_avg_12_neon(uint8_t *_dst, ptrdiff_t _dst_stride,
#define W_AVG_FUN(bit_depth) \
static void vvc_w_avg_ ## bit_depth(uint8_t *dst, ptrdiff_t dst_stride, \
const int16_t *src0, const int16_t *src1, int width, int height, \
- int denom, int w0, int w1, int o0, int o1) \
+ int denom, int w0, int w1, int o) \
{ \
int shift = denom + FFMAX(3, 15 - bit_depth); \
- int offset = ((o0 + o1) * (1 << (bit_depth - 8)) + 1) * (1 << (shift - 1)); \
+ int offset = (o * (1 << (bit_depth - 8)) + 1) * (1 << (shift - 1)); \
uintptr_t w0_w1 = ((uintptr_t)w0 << 32) | (uint32_t)w1; \
uintptr_t offset_shift = ((uintptr_t)offset << 32) | (uint32_t)shift; \
ff_vvc_w_avg_ ## bit_depth ## _neon(dst, dst_stride, src0, src1, width, height, w0_w1, offset_shift); \
diff --git a/libavcodec/riscv/vvc/dsp_init.c b/libavcodec/riscv/vvc/dsp_init.c
index d7a89f4779..f8fde41529 100644
--- a/libavcodec/riscv/vvc/dsp_init.c
+++ b/libavcodec/riscv/vvc/dsp_init.c
@@ -34,7 +34,7 @@ void bf(ff_vvc_avg, bd, opt)(uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *src0, const int16_t *src1, int width, int height); \
void bf(ff_vvc_w_avg, bd, opt)(uint8_t *dst, ptrdiff_t dst_stride, \
const int16_t *src0, const int16_t *src1, int width, int height, \
- int denom, int w0, int w1, int o0, int o1);
+ int denom, int w0, int w1, int o);
AVG_PROTOTYPES(8, rvv_128)
AVG_PROTOTYPES(8, rvv_256)
diff --git a/libavcodec/riscv/vvc/mc_rvv.S b/libavcodec/riscv/vvc/mc_rvv.S
index e6b2aadafe..a612290e3a 100644
--- a/libavcodec/riscv/vvc/mc_rvv.S
+++ b/libavcodec/riscv/vvc/mc_rvv.S
@@ -163,9 +163,7 @@ func ff_vvc_w_avg_8_rvv_\vlen\(), zve32x, zbb, zba
addi t6, a6, 7
ld t3, (sp)
ld t4, 8(sp)
- ld t5, 16(sp)
addi t4, t4, 1 // o0 + o1 + 1
- add t4, t4, t5
addi t5, t6, -1 // shift - 1
sll t4, t4, t5
POW2_J \vlen, 2, a4
diff --git a/libavcodec/vvc/dsp.h b/libavcodec/vvc/dsp.h
index ae22900931..29cdd7e8f4 100644
--- a/libavcodec/vvc/dsp.h
+++ b/libavcodec/vvc/dsp.h
@@ -75,7 +75,7 @@ typedef struct VVCInterDSPContext {
void (*w_avg)(uint8_t *_dst, const ptrdiff_t _dst_stride,
const int16_t *src0, const int16_t *src1, int width, int height,
- int denom, int w0, int w1, int o0, int o1);
+ int denom, int w0, int w1, int o);
void (*put_ciip)(uint8_t *dst, ptrdiff_t dst_stride, int width, int height,
const uint8_t *inter, ptrdiff_t inter_stride, int inter_weight);
diff --git a/libavcodec/vvc/inter.c b/libavcodec/vvc/inter.c
index 85e0665a75..7d6e79e49b 100644
--- a/libavcodec/vvc/inter.c
+++ b/libavcodec/vvc/inter.c
@@ -232,22 +232,22 @@ static void apply_averaging(uint8_t *dst, const ptrdiff_t dst_stride,
return;
}
- int denom, w0, w1, o1, o2;
+ int denom, w0, w1, o;
if (bcw_idx) {
denom = 2;
w1 = bcw_w_lut[bcw_idx];
w0 = 8 - w1;
- o1 = o2 = 0;
+ o = 0;
} else {
const PredWeightTable *w = pps->r->pps_wp_info_in_ph_flag ? &fc->ps.ph.pwt : &sh->pwt;
denom = w->log2_denom[c_idx > 0];
w0 = w->weight[L0][c_idx][mvf->ref_idx[L0]];
w1 = w->weight[L1][c_idx][mvf->ref_idx[L1]];
- o1 = w->offset[L0][c_idx][mvf->ref_idx[L0]];
- o2 = w->offset[L1][c_idx][mvf->ref_idx[L1]];
+ o = w->offset[L0][c_idx][mvf->ref_idx[L0]]
+ + w->offset[L1][c_idx][mvf->ref_idx[L1]];
}
- fc->vvcdsp.inter.w_avg(dst, dst_stride, src0, src1, width, height, denom, w0, w1, o1, o2);
+ fc->vvcdsp.inter.w_avg(dst, dst_stride, src0, src1, width, height, denom, w0, w1, o);
}
#define INTER_FILTER(t, frac) (is_chroma ? ff_vvc_inter_chroma_filters[t][frac] : ff_vvc_inter_luma_filters[t][frac])
diff --git a/libavcodec/vvc/inter_template.c b/libavcodec/vvc/inter_template.c
index aee4994c17..efa432d1fd 100644
--- a/libavcodec/vvc/inter_template.c
+++ b/libavcodec/vvc/inter_template.c
@@ -201,12 +201,12 @@ static void FUNC(avg)(uint8_t *_dst, const ptrdiff_t _dst_stride,
static void FUNC(w_avg)(uint8_t *_dst, const ptrdiff_t _dst_stride,
const int16_t *src0, const int16_t *src1, const int width, const int height,
- const int denom, const int w0, const int w1, const int o0, const int o1)
+ const int denom, const int w0, const int w1, const int o)
{
pixel *dst = (pixel*)_dst;
const ptrdiff_t dst_stride = _dst_stride / sizeof(pixel);
const int shift = denom + FFMAX(3, 15 - BIT_DEPTH);
- const int offset = ((o0 + o1) * (1 << (BIT_DEPTH - 8)) + 1) * (1 << (shift - 1));
+ const int offset = (o * (1 << (BIT_DEPTH - 8)) + 1) * (1 << (shift - 1));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
diff --git a/libavcodec/x86/vvc/dsp_init.c b/libavcodec/x86/vvc/dsp_init.c
index cd3d02c0fb..37ddbcb73b 100644
--- a/libavcodec/x86/vvc/dsp_init.c
+++ b/libavcodec/x86/vvc/dsp_init.c
@@ -231,7 +231,7 @@ void bf(ff_vvc_avg, bd, opt)(uint8_t *dst, ptrdiff_t dst_stride, \
const int16_t *src0, const int16_t *src1, int width, int height);\
void bf(ff_vvc_w_avg, bd, opt)(uint8_t *dst, ptrdiff_t dst_stride, \
const int16_t *src0, const int16_t *src1, int width, int height, \
- int denom, int w0, int w1, int o0, int o1); \
+ int denom, int w0, int w1, int o); \
c->inter.avg = bf(ff_vvc_avg, bd, opt); \
c->inter.w_avg = bf(ff_vvc_w_avg, bd, opt); \
} while (0)
diff --git a/libavcodec/x86/vvc/mc.asm b/libavcodec/x86/vvc/mc.asm
index 8ba493aebd..4f078ea8d0 100644
--- a/libavcodec/x86/vvc/mc.asm
+++ b/libavcodec/x86/vvc/mc.asm
@@ -244,7 +244,7 @@ cglobal vvc_avg_%2, 4, 7, 5, dst, stride, src0, src1, w, h
;void ff_vvc_w_avg_%2_avx(uint8_t *dst, ptrdiff_t dst_stride,
; const int16_t *src0, const int16_t *src1, int width, int height,
-; int denom, intptr_t w0, int w1, int o0, int o1);
+; int denom, intptr_t w0, int w1, int o);
%macro VVC_W_AVG_AVX2 3
cglobal vvc_w_avg_%2, 4, 7+2*UNIX64, 6+2*(%1 != 8), dst, stride, src0, src1, w, h
%if UNIX64
@@ -256,8 +256,7 @@ cglobal vvc_w_avg_%2, 4, 7+2*UNIX64, 6+2*(%1 != 8), dst, stride, src0, src1, w,
%endif
mov t1d, r6m ; denom
- mov t0d, r9m ; o0
- add t0d, r10m ; o1
+ mov t0d, r9m ; o0 + o1
movifnidn t2d, r8m ; w1
add t1d, 15-%2
%if %2 != 8
diff --git a/tests/checkasm/vvc_mc.c b/tests/checkasm/vvc_mc.c
index 754cf19065..623b6142f1 100644
--- a/tests/checkasm/vvc_mc.c
+++ b/tests/checkasm/vvc_mc.c
@@ -306,7 +306,7 @@ static void check_avg(void)
{
declare_func(void, uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *src0, const int16_t *src1, int width, int height,
- int denom, int w0, int w1, int o0, int o1);
+ int denom, int w0, int w1, int o);
{
const int denom = rnd() % 8;
const int w0 = rnd() % 256 - 128;
@@ -317,12 +317,12 @@ static void check_avg(void)
memset(dst0, 0, AVG_DST_BUF_SIZE);
memset(dst1, 0, AVG_DST_BUF_SIZE);
- call_ref(dst0, MAX_CTU_SIZE * SIZEOF_PIXEL, src00, src01, w, h, denom, w0, w1, o0, o1);
- call_new(dst1, MAX_CTU_SIZE * SIZEOF_PIXEL, src10, src11, w, h, denom, w0, w1, o0, o1);
+ call_ref(dst0, MAX_CTU_SIZE * SIZEOF_PIXEL, src00, src01, w, h, denom, w0, w1, o0 + o1);
+ call_new(dst1, MAX_CTU_SIZE * SIZEOF_PIXEL, src10, src11, w, h, denom, w0, w1, o0 + o1);
if (memcmp(dst0, dst1, DST_BUF_SIZE))
fail();
if (w == h)
- bench_new(dst0, MAX_CTU_SIZE * SIZEOF_PIXEL, src00, src01, w, h, denom, w0, w1, o0, o1);
+ bench_new(dst0, MAX_CTU_SIZE * SIZEOF_PIXEL, src00, src01, w, h, denom, w0, w1, o0 + o1);
}
}
}
1
0
[ffmpeg] avcodec/d3d12va_encode: add detailed ValidationFlags error reporting for video encoders check feature support (branch master)
by stevxiao 25 Feb '26
by stevxiao 25 Feb '26
25 Feb '26
This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new fc7c38f9da avcodec/d3d12va_encode: add detailed ValidationFlags error reporting for video encoders check feature support
fc7c38f9da is described below
commit fc7c38f9da4a9262beedd0fd8bf69d5c0f32d923
Author: stevxiao <steven.xiao(a)amd.com>
AuthorDate: Mon Dec 8 17:56:43 2025 -0500
Commit: Tong Wu <wutong1208(a)outlook.com>
CommitDate: Wed Feb 25 08:47:14 2026 +0000
avcodec/d3d12va_encode: add detailed ValidationFlags error reporting for video encoders check feature support
Improves error diagnostics for D3D12 video encoders check feature support by adding
detailed ValidationFlags reporting when driver validation fails.
This made it easy for users to identify which specific feature was
unsupported without manually decoding the flags.
Signed-off-by: younengxiao <steven.xiao(a)amd.com>
---
libavcodec/d3d12va_encode.c | 23 +++++++++++++++++++++++
libavcodec/d3d12va_encode.h | 3 +++
libavcodec/d3d12va_encode_av1.c | 3 ++-
libavcodec/d3d12va_encode_h264.c | 3 ++-
libavcodec/d3d12va_encode_hevc.c | 3 ++-
5 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c
index 14efe633ae..2cca179b83 100644
--- a/libavcodec/d3d12va_encode.c
+++ b/libavcodec/d3d12va_encode.c
@@ -39,6 +39,29 @@ const AVCodecHWConfigInternal *const ff_d3d12va_encode_hw_configs[] = {
NULL,
};
+void ff_d3d12va_encode_check_encoder_feature_flags(void *log_ctx,
+ D3D12_VIDEO_ENCODER_VALIDATION_FLAGS flags)
+{
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_CODEC_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Codec not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_INPUT_FORMAT_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Input format not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_CODEC_CONFIGURATION_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Codec configuration not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_RATE_CONTROL_MODE_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Rate control mode not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_RATE_CONTROL_CONFIGURATION_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Rate control configuration not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_INTRA_REFRESH_MODE_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Intra refresh mode not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_SUBREGION_LAYOUT_MODE_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - Subregion layout mode not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_RESOLUTION_NOT_SUPPORTED_IN_LIST)
+ av_log(log_ctx, AV_LOG_ERROR, " - Resolution not supported\n");
+ if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_GOP_STRUCTURE_NOT_SUPPORTED)
+ av_log(log_ctx, AV_LOG_ERROR, " - GOP structure not supported\n");
+}
+
static int d3d12va_fence_completion(AVD3D12VASyncContext *psync_ctx)
{
uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->fence);
diff --git a/libavcodec/d3d12va_encode.h b/libavcodec/d3d12va_encode.h
index 7eecdb6eb8..f059ae9806 100644
--- a/libavcodec/d3d12va_encode.h
+++ b/libavcodec/d3d12va_encode.h
@@ -371,6 +371,9 @@ int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
int ff_d3d12va_encode_init(AVCodecContext *avctx);
int ff_d3d12va_encode_close(AVCodecContext *avctx);
+void ff_d3d12va_encode_check_encoder_feature_flags(void *log_ctx,
+ D3D12_VIDEO_ENCODER_VALIDATION_FLAGS flags);
+
#define D3D12VA_ENCODE_INTRA_REFRESH_MODE(name, mode, desc) \
{ #name, desc, 0, AV_OPT_TYPE_CONST, { .i64 = D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_ ## mode }, \
0, 0, FLAGS, .unit = "intra_refresh_mode" }
diff --git a/libavcodec/d3d12va_encode_av1.c b/libavcodec/d3d12va_encode_av1.c
index 912f411547..8d2edec491 100644
--- a/libavcodec/d3d12va_encode_av1.c
+++ b/libavcodec/d3d12va_encode_av1.c
@@ -580,8 +580,9 @@ static int d3d12va_encode_av1_init_sequence_params(AVCodecContext *avctx)
}
if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
- av_log(avctx, AV_LOG_ERROR, "Driver does not support some request D3D12VA AV1 features. %#x\n",
+ av_log(avctx, AV_LOG_ERROR, "Driver does not support requested features. ValidationFlags: %#x\n",
support.ValidationFlags);
+ ff_d3d12va_encode_check_encoder_feature_flags(avctx, support.ValidationFlags);
return AVERROR(EINVAL);
}
diff --git a/libavcodec/d3d12va_encode_h264.c b/libavcodec/d3d12va_encode_h264.c
index eae97e1f23..bd15856f0e 100644
--- a/libavcodec/d3d12va_encode_h264.c
+++ b/libavcodec/d3d12va_encode_h264.c
@@ -202,8 +202,9 @@ static int d3d12va_encode_h264_init_sequence_params(AVCodecContext *avctx)
}
if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
- av_log(avctx, AV_LOG_ERROR, "Driver does not support some request features. %#x\n",
+ av_log(avctx, AV_LOG_ERROR, "Driver does not support requested features. ValidationFlags: %#x\n",
support.ValidationFlags);
+ ff_d3d12va_encode_check_encoder_feature_flags(avctx, support.ValidationFlags);
return AVERROR(EINVAL);
}
diff --git a/libavcodec/d3d12va_encode_hevc.c b/libavcodec/d3d12va_encode_hevc.c
index 45038bbad6..8cae7a8b66 100644
--- a/libavcodec/d3d12va_encode_hevc.c
+++ b/libavcodec/d3d12va_encode_hevc.c
@@ -273,8 +273,9 @@ static int d3d12va_encode_hevc_init_sequence_params(AVCodecContext *avctx)
}
if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
- av_log(avctx, AV_LOG_ERROR, "Driver does not support some request features. %#x\n",
+ av_log(avctx, AV_LOG_ERROR, "Driver does not support requested features. ValidationFlags: %#x\n",
support.ValidationFlags);
+ ff_d3d12va_encode_check_encoder_feature_flags(avctx, support.ValidationFlags);
return AVERROR(EINVAL);
}
1
0
This is an automated email from the git hooks/post-receive script.
Git pushed a change to branch master
in repository ffmpeg.
from dc4c798970 avformat: Use ff_*_muxer directly
new 35ccd5f3de avformat/tls_mbedtls: add dtls support
new 55f5cfafeb avformat/tls_mbedtls: set dtls remote addr in listen mode
new 659892cda6 avformat/tls_mbedtls: generate self-signed cert and key when none is provided in listen mode
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
configure | 4 +-
libavformat/tls_mbedtls.c | 447 +++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 429 insertions(+), 22 deletions(-)
2
3
This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new dc4c798970 avformat: Use ff_*_muxer directly
dc4c798970 is described below
commit dc4c7989704a204dc81eb381261dd5be59930cdb
Author: Jack Lau <jacklau1222gm(a)gmail.com>
AuthorDate: Mon Feb 23 07:54:18 2026 +0800
Commit: Jack Lau <jacklau1222gm(a)gmail.com>
CommitDate: Wed Feb 25 02:55:43 2026 +0000
avformat: Use ff_*_muxer directly
These muxers already set hard dependencies in
configure so they cannot be enabled unless the
dependencies are enabled.
So these error handling is unreachable.
Directly Using ff_*_muxer is simpler than calling
av_guess_format()
Refer to 289cb3beff
Signed-off-by: Jack Lau <jacklau1222gm(a)gmail.com>
---
libavformat/hdsenc.c | 9 +++------
libavformat/hlsenc.c | 14 +++++++-------
libavformat/rtpenc_mpegts.c | 11 +++++------
libavformat/smoothstreamingenc.c | 9 +++------
libavformat/webm_chunk.c | 8 +++-----
libavformat/whip.c | 11 ++++-------
6 files changed, 25 insertions(+), 37 deletions(-)
diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c
index 01efa1f8da..d3292a8342 100644
--- a/libavformat/hdsenc.c
+++ b/libavformat/hdsenc.c
@@ -29,6 +29,7 @@
#include "mux.h"
#include "os_support.h"
+#include "libavutil/attributes_internal.h"
#include "libavutil/avstring.h"
#include "libavutil/base64.h"
#include "libavutil/intreadwrite.h"
@@ -311,7 +312,6 @@ static void close_file(AVFormatContext *s, OutputStream *os)
static int hds_write_header(AVFormatContext *s)
{
HDSContext *c = s->priv_data;
- const AVOutputFormat *oformat;
int ret = 0, i;
if (mkdir(s->url, 0777) == -1 && errno != EEXIST) {
@@ -319,10 +319,6 @@ static int hds_write_header(AVFormatContext *s)
return AVERROR(errno);
}
- oformat = av_guess_format("flv", NULL, NULL);
- if (!oformat) {
- return AVERROR_MUXER_NOT_FOUND;
- }
c->streams = av_calloc(s->nb_streams, sizeof(*c->streams));
if (!c->streams) {
@@ -363,7 +359,8 @@ static int hds_write_header(AVFormatContext *s)
return AVERROR(ENOMEM);
}
os->ctx = ctx;
- ctx->oformat = oformat;
+ EXTERN const FFOutputFormat ff_flv_muxer;
+ ctx->oformat = &ff_flv_muxer.p;
ctx->interrupt_callback = s->interrupt_callback;
ctx->flags = s->flags;
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index dcf5da9bb8..957b9a5ddd 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -28,6 +28,7 @@
#include <unistd.h>
#endif
+#include "libavutil/attributes_internal.h"
#include "libavutil/avassert.h"
#include "libavutil/mathematics.h"
#include "libavutil/avstring.h"
@@ -2972,12 +2973,12 @@ static int hls_init(AVFormatContext *s)
if (vs->has_video > 1)
av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
if (hls->segment_type == SEGMENT_TYPE_FMP4) {
- vs->oformat = av_guess_format("mp4", NULL, NULL);
+ EXTERN const FFOutputFormat ff_mp4_muxer;
+ vs->oformat = &ff_mp4_muxer.p;
} else {
- vs->oformat = av_guess_format("mpegts", NULL, NULL);
+ EXTERN const FFOutputFormat ff_mpegts_muxer;
+ vs->oformat = &ff_mpegts_muxer.p;
}
- if (!vs->oformat)
- return AVERROR_MUXER_NOT_FOUND;
if (hls->segment_filename) {
ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
@@ -3054,9 +3055,8 @@ static int hls_init(AVFormatContext *s)
return ret;
if (vs->has_subtitle) {
- vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
- if (!vs->vtt_oformat)
- return AVERROR_MUXER_NOT_FOUND;
+ EXTERN const FFOutputFormat ff_webvtt_muxer;
+ vs->vtt_oformat = &ff_webvtt_muxer.p;
p = strrchr(vs->m3u8_name, '.');
if (p)
diff --git a/libavformat/rtpenc_mpegts.c b/libavformat/rtpenc_mpegts.c
index f9ff7e99cd..897db10f76 100644
--- a/libavformat/rtpenc_mpegts.c
+++ b/libavformat/rtpenc_mpegts.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/attributes_internal.h"
#include "libavutil/mathematics.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
@@ -58,22 +59,19 @@ static int rtp_mpegts_write_header(AVFormatContext *s)
{
MuxChain *chain = s->priv_data;
AVFormatContext *mpegts_ctx = NULL, *rtp_ctx = NULL;
- const AVOutputFormat *mpegts_format = av_guess_format("mpegts", NULL, NULL);
- const AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
int i, ret = AVERROR(ENOMEM);
AVStream *st;
AVDictionary *mpegts_muxer_options = NULL;
AVDictionary *rtp_muxer_options = NULL;
- if (!mpegts_format || !rtp_format)
- return AVERROR(ENOSYS);
mpegts_ctx = avformat_alloc_context();
if (!mpegts_ctx)
return AVERROR(ENOMEM);
chain->pkt = av_packet_alloc();
if (!chain->pkt)
goto fail;
- mpegts_ctx->oformat = mpegts_format;
+ EXTERN const FFOutputFormat ff_mpegts_muxer;
+ mpegts_ctx->oformat = &ff_mpegts_muxer.p;
mpegts_ctx->max_delay = s->max_delay;
av_dict_copy(&mpegts_ctx->metadata, s->metadata, 0);
for (i = 0; i < s->nb_streams; i++) {
@@ -106,7 +104,8 @@ static int rtp_mpegts_write_header(AVFormatContext *s)
ret = AVERROR(ENOMEM);
goto fail;
}
- rtp_ctx->oformat = rtp_format;
+ EXTERN const FFOutputFormat ff_rtp_muxer;
+ rtp_ctx->oformat = &ff_rtp_muxer.p;
st = avformat_new_stream(rtp_ctx, NULL);
if (!st) {
ret = AVERROR(ENOMEM);
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index adf3008003..3a4c1e0413 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -31,6 +31,7 @@
#include "avc.h"
#include "url.h"
+#include "libavutil/attributes_internal.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "libavutil/avstring.h"
@@ -283,17 +284,12 @@ static int ism_write_header(AVFormatContext *s)
{
SmoothStreamingContext *c = s->priv_data;
int ret = 0, i;
- const AVOutputFormat *oformat;
if (mkdir(s->url, 0777) == -1 && errno != EEXIST) {
av_log(s, AV_LOG_ERROR, "mkdir failed\n");
return AVERROR(errno);
}
- oformat = av_guess_format("ismv", NULL, NULL);
- if (!oformat) {
- return AVERROR_MUXER_NOT_FOUND;
- }
c->streams = av_calloc(s->nb_streams, sizeof(*c->streams));
if (!c->streams) {
@@ -325,7 +321,8 @@ static int ism_write_header(AVFormatContext *s)
}
if ((ret = ff_copy_whiteblacklists(ctx, s)) < 0)
return ret;
- ctx->oformat = oformat;
+ EXTERN const FFOutputFormat ff_ismv_muxer;
+ ctx->oformat = &ff_ismv_muxer.p;
ctx->interrupt_callback = s->interrupt_callback;
if (!(st = avformat_new_stream(ctx, NULL))) {
diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c
index 57329f1788..19506faebe 100644
--- a/libavformat/webm_chunk.c
+++ b/libavformat/webm_chunk.c
@@ -30,6 +30,7 @@
#include "internal.h"
#include "mux.h"
+#include "libavutil/attributes_internal.h"
#include "libavutil/bprint.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
@@ -51,7 +52,6 @@ typedef struct WebMChunkContext {
static int webm_chunk_init(AVFormatContext *s)
{
WebMChunkContext *wc = s->priv_data;
- const AVOutputFormat *oformat;
AVFormatContext *oc;
AVStream *st, *ost = s->streams[0];
AVDictionary *dict = NULL;
@@ -68,11 +68,9 @@ static int webm_chunk_init(AVFormatContext *s)
wc->prev_pts = AV_NOPTS_VALUE;
- oformat = av_guess_format("webm", s->url, "video/webm");
- if (!oformat)
- return AVERROR_MUXER_NOT_FOUND;
+ EXTERN const FFOutputFormat ff_webm_muxer;
- ret = avformat_alloc_output_context2(&wc->avf, oformat, NULL, NULL);
+ ret = avformat_alloc_output_context2(&wc->avf, &ff_webm_muxer.p, NULL, NULL);
if (ret < 0)
return ret;
oc = wc->avf;
diff --git a/libavformat/whip.c b/libavformat/whip.c
index 08bd19d9c7..8306296b20 100644
--- a/libavformat/whip.c
+++ b/libavformat/whip.c
@@ -21,6 +21,8 @@
#include "libavcodec/h264.h"
#include "libavcodec/startcode.h"
+
+#include "libavutil/attributes_internal.h"
#include "libavutil/avassert.h"
#include "libavutil/base64.h"
#include "libavutil/bprint.h"
@@ -1540,12 +1542,6 @@ static int create_rtp_muxer(AVFormatContext *s)
WHIPContext *whip = s->priv_data;
whip->udp->flags |= AVIO_FLAG_NONBLOCK;
- const AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
- if (!rtp_format) {
- av_log(whip, AV_LOG_ERROR, "Failed to guess rtp muxer\n");
- ret = AVERROR(ENOSYS);
- goto end;
- }
/* The UDP buffer size, may greater than MTU. */
buffer_size = MAX_UDP_BUFFER_SIZE;
@@ -1559,7 +1555,8 @@ static int create_rtp_muxer(AVFormatContext *s)
goto end;
}
- rtp_ctx->oformat = rtp_format;
+ EXTERN const FFOutputFormat ff_rtp_muxer;
+ rtp_ctx->oformat = &ff_rtp_muxer.p;
if (!avformat_new_stream(rtp_ctx, NULL)) {
ret = AVERROR(ENOMEM);
goto end;
1
0
This is an automated email from the git hooks/post-receive script.
Git pushed a change to branch master
in repository ffmpeg.
from 145f6e5878 avcodec/cbs_h2645: split into separate files per module
new c7c8c31302 swscale/tests/sws_ops: print range values in the output
new 9fbb03f428 swscale/tests/sws_ops: don't print unused components in the output
new c9977acbc6 swscale/ops: clear range values SWS_OP_{MIN,MAX}
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
libswscale/graph.c | 4 ++--
libswscale/ops.c | 56 +++++++++++++++++++++++++++++++++------------
libswscale/ops.h | 3 ++-
libswscale/tests/sws_ops.c | 2 +-
tests/ref/fate/sws-ops-list | 2 +-
5 files changed, 47 insertions(+), 20 deletions(-)
2
3
[ffmpeg] avcodec/cbs_h2645: split into separate files per module (branch master)
by James Almer 24 Feb '26
by James Almer 24 Feb '26
24 Feb '26
This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 145f6e5878 avcodec/cbs_h2645: split into separate files per module
145f6e5878 is described below
commit 145f6e5878591f77a1054381143ca1431fce8156
Author: James Almer <jamrial(a)gmail.com>
AuthorDate: Sun Feb 22 16:36:23 2026 -0300
Commit: James Almer <jamrial(a)gmail.com>
CommitDate: Tue Feb 24 10:32:20 2026 -0300
avcodec/cbs_h2645: split into separate files per module
This file is becoming too bloated and hard to read, so split it into separate
files, each having codec specific methods.
This will also speed up compilation when using several concurrent jobs.
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
libavcodec/Makefile | 6 +-
libavcodec/cbs_h264.c | 788 +++++++++++++
libavcodec/cbs_h2645.c | 2010 +--------------------------------
libavcodec/cbs_h2645.h | 44 +
libavcodec/cbs_h265.c | 828 ++++++++++++++
libavcodec/cbs_h265_syntax_template.c | 4 +-
libavcodec/cbs_h266.c | 809 +++++++++++++
libavcodec/cbs_h266_syntax_template.c | 4 +-
libavcodec/cbs_sei.c | 320 ++++++
libavcodec/cbs_sei.h | 12 +
libavcodec/cbs_sei_syntax_template.c | 6 +-
11 files changed, 2830 insertions(+), 2001 deletions(-)
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 50ac7d712b..7d3e4aa1b4 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -88,9 +88,9 @@ OBJS-$(CONFIG_CABAC) += cabac.o
OBJS-$(CONFIG_CBS) += cbs.o cbs_bsf.o
OBJS-$(CONFIG_CBS_APV) += cbs_apv.o
OBJS-$(CONFIG_CBS_AV1) += cbs_av1.o
-OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o cbs_sei.o h2645_parse.o
-OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o cbs_sei.o h2645_parse.o
-OBJS-$(CONFIG_CBS_H266) += cbs_h2645.o cbs_sei.o h2645_parse.o
+OBJS-$(CONFIG_CBS_H264) += cbs_h264.o cbs_h2645.o cbs_sei.o h2645_parse.o
+OBJS-$(CONFIG_CBS_H265) += cbs_h265.o cbs_h2645.o cbs_sei.o h2645_parse.o
+OBJS-$(CONFIG_CBS_H266) += cbs_h266.o cbs_h2645.o cbs_sei.o h2645_parse.o
OBJS-$(CONFIG_CBS_JPEG) += cbs_jpeg.o
OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o
OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o
diff --git a/libavcodec/cbs_h264.c b/libavcodec/cbs_h264.c
new file mode 100644
index 0000000000..8b5a7c71fa
--- /dev/null
+++ b/libavcodec/cbs_h264.c
@@ -0,0 +1,788 @@
+/*
+ * 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/mem.h"
+#include "libavutil/refstruct.h"
+#include "bytestream.h"
+#include "cbs.h"
+#include "cbs_internal.h"
+#include "cbs_h2645.h"
+#include "cbs_h264.h"
+#include "cbs_sei.h"
+#include "get_bits.h"
+
+#define HEADER(name) do { \
+ ff_cbs_trace_header(ctx, name); \
+ } while (0)
+
+#define CHECK(call) do { \
+ err = (call); \
+ if (err < 0) \
+ return err; \
+ } while (0)
+
+#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
+#define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name)
+#define FUNC_NAME2_EXPORT(rw, codec, name) ff_cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1_EXPORT(rw, codec, name) FUNC_NAME2_EXPORT(rw, codec, name)
+#define FUNC_SEI(name) FUNC_NAME1_EXPORT(READWRITE, sei, name)
+
+#define SEI_FUNC(name, args) \
+static int FUNC_H264(name) args; \
+static int FUNC_H264(name ## _internal)(CodedBitstreamContext *ctx, \
+ RWContext *rw, void *cur, \
+ SEIMessageState *state) \
+{ \
+ return FUNC_H264(name)(ctx, rw, cur, state); \
+} \
+static int FUNC_H264(name) args
+
+#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
+
+#define u(width, name, range_min, range_max) \
+ xu(width, name, current->name, range_min, range_max, 0, )
+#define flag(name) ub(1, name)
+#define ue(name, range_min, range_max) \
+ xue(name, current->name, range_min, range_max, 0, )
+#define i(width, name, range_min, range_max) \
+ xi(width, name, current->name, range_min, range_max, 0, )
+#define ib(width, name) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
+#define se(name, range_min, range_max) \
+ xse(name, current->name, range_min, range_max, 0, )
+
+#define us(width, name, range_min, range_max, subs, ...) \
+ xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ubs(width, name, subs, ...) \
+ xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
+#define flags(name, subs, ...) \
+ xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
+#define ues(name, range_min, range_max, subs, ...) \
+ xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define is(width, name, range_min, range_max, subs, ...) \
+ xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ibs(width, name, subs, ...) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
+#define ses(name, range_min, range_max, subs, ...) \
+ xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+
+#define fixed(width, name, value) do { \
+ av_unused uint32_t fixed_value = value; \
+ xu(width, name, fixed_value, value, value, 0, ); \
+ } while (0)
+
+
+#define READ
+#define READWRITE read
+#define RWContext GetBitContext
+
+#define ub(width, name) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
+ &value)); \
+ current->name = value; \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+
+
+#define infer(name, value) do { \
+ current->name = value; \
+ } while (0)
+
+#define more_rbsp_data(var) ((var) = ff_cbs_h2645_read_more_rbsp_data(rw))
+
+#define bit_position(rw) (get_bits_count(rw))
+#define byte_alignment(rw) (get_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ name ## _ref = av_buffer_allocz(size + \
+ AV_INPUT_BUFFER_PADDING_SIZE); \
+ if (!name ## _ref) \
+ return AVERROR(ENOMEM); \
+ name = name ## _ref->data; \
+ } while (0)
+
+#define FUNC(name) FUNC_H264(name)
+#include "cbs_h264_syntax_template.c"
+#undef FUNC
+
+
+#undef READ
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+#undef allocate_struct
+
+
+#define WRITE
+#define READWRITE write
+#define RWContext PutBitContext
+
+#define ub(width, name) do { \
+ uint32_t value = current->name; \
+ CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
+ value)); \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+
+#define infer(name, value) do { \
+ if (current->name != (value)) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, \
+ "%s does not match inferred value: " \
+ "%"PRId64", but should be %"PRId64".\n", \
+ #name, (int64_t)current->name, (int64_t)(value)); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define more_rbsp_data(var) (var)
+
+#define bit_position(rw) (put_bits_count(rw))
+#define byte_alignment(rw) (put_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ if (!name) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
+ "for writing.\n", #name); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define FUNC(name) FUNC_H264(name)
+#include "cbs_h264_syntax_template.c"
+#undef FUNC
+
+#undef WRITE
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef u
+#undef i
+#undef flag
+#undef ue
+#undef se
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+
+
+
+static int cbs_h264_split_fragment(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *frag,
+ int header)
+{
+ enum AVCodecID codec_id = ctx->codec->codec_id;
+ CodedBitstreamH264Context *priv = ctx->priv_data;
+ CodedBitstreamH2645Context *h2645 = &priv->common;
+ GetByteContext gbc;
+ int err;
+
+ av_assert0(frag->data && frag->nb_units == 0);
+ if (frag->data_size == 0)
+ return 0;
+
+ if (header && frag->data[0]) {
+ // AVCC header.
+ size_t size, start, end;
+ int i, count, version;
+
+ h2645->mp4 = 1;
+
+ bytestream2_init(&gbc, frag->data, frag->data_size);
+
+ if (bytestream2_get_bytes_left(&gbc) < 6)
+ return AVERROR_INVALIDDATA;
+
+ version = bytestream2_get_byte(&gbc);
+ if (version != 1) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid AVCC header: "
+ "first byte %u.\n", version);
+ return AVERROR_INVALIDDATA;
+ }
+
+ bytestream2_skip(&gbc, 3);
+ h2645->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1;
+
+ // SPS array.
+ count = bytestream2_get_byte(&gbc) & 0x1f;
+ start = bytestream2_tell(&gbc);
+ for (i = 0; i < count; i++) {
+ if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i))
+ return AVERROR_INVALIDDATA;
+ size = bytestream2_get_be16(&gbc);
+ if (bytestream2_get_bytes_left(&gbc) < size)
+ return AVERROR_INVALIDDATA;
+ bytestream2_skip(&gbc, size);
+ }
+ end = bytestream2_tell(&gbc);
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data + start, end - start,
+ ctx->log_ctx, 2, AV_CODEC_ID_H264,
+ H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
+ if (err < 0) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC SPS array.\n");
+ return err;
+ }
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+
+ // PPS array.
+ count = bytestream2_get_byte(&gbc);
+ start = bytestream2_tell(&gbc);
+ for (i = 0; i < count; i++) {
+ if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i))
+ return AVERROR_INVALIDDATA;
+ size = bytestream2_get_be16(&gbc);
+ if (bytestream2_get_bytes_left(&gbc) < size)
+ return AVERROR_INVALIDDATA;
+ bytestream2_skip(&gbc, size);
+ }
+ end = bytestream2_tell(&gbc);
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data + start, end - start,
+ ctx->log_ctx, 2, AV_CODEC_ID_H264,
+ H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
+ if (err < 0) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC PPS array.\n");
+ return err;
+ }
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+
+ if (bytestream2_get_bytes_left(&gbc) > 0) {
+ av_log(ctx->log_ctx, AV_LOG_WARNING, "%u bytes left at end of AVCC "
+ "header.\n", bytestream2_get_bytes_left(&gbc));
+ }
+ } else {
+ int flags = (H2645_FLAG_IS_NALFF * !!h2645->mp4) | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF;
+ // Annex B, or later MP4 with already-known parameters.
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data, frag->data_size,
+ ctx->log_ctx,
+ h2645->nal_length_size,
+ codec_id, flags);
+ if (err < 0)
+ return err;
+
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+#define cbs_h2645_replace_ps(ps_name, ps_var, id_element) \
+static int cbs_h264_replace_ ## ps_var(CodedBitstreamContext *ctx, \
+ CodedBitstreamUnit *unit) \
+{ \
+ CodedBitstreamH264Context *priv = ctx->priv_data; \
+ H264Raw ## ps_name *ps_var = unit->content; \
+ unsigned int id = ps_var->id_element; \
+ int err = ff_cbs_make_unit_refcounted(ctx, unit); \
+ if (err < 0) \
+ return err; \
+ if (priv->ps_var[id] == priv->active_ ## ps_var) \
+ priv->active_ ## ps_var = NULL ; \
+ av_assert0(unit->content_ref); \
+ av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
+ return 0; \
+}
+
+cbs_h2645_replace_ps(SPS, sps, seq_parameter_set_id)
+cbs_h2645_replace_ps(PPS, pps, pic_parameter_set_id)
+
+static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit)
+{
+ GetBitContext gbc;
+ int err;
+
+ err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
+ if (err < 0)
+ return err;
+
+ err = ff_cbs_alloc_unit_content(ctx, unit);
+ if (err < 0)
+ return err;
+
+ switch (unit->type) {
+ case H264_NAL_SPS:
+ {
+ H264RawSPS *sps = unit->content;
+
+ err = cbs_h264_read_sps(ctx, &gbc, sps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h264_replace_sps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_SPS_EXT:
+ {
+ err = cbs_h264_read_sps_extension(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_PPS:
+ {
+ H264RawPPS *pps = unit->content;
+
+ err = cbs_h264_read_pps(ctx, &gbc, pps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h264_replace_pps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_SLICE:
+ case H264_NAL_IDR_SLICE:
+ case H264_NAL_AUXILIARY_SLICE:
+ {
+ H264RawSlice *slice = unit->content;
+ int pos, len;
+
+ err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header);
+ if (err < 0)
+ return err;
+
+ if (!ff_cbs_h2645_read_more_rbsp_data(&gbc))
+ return AVERROR_INVALIDDATA;
+
+ pos = get_bits_count(&gbc);
+ len = unit->data_size;
+
+ slice->data_size = len - pos / 8;
+ slice->data_ref = av_buffer_ref(unit->data_ref);
+ if (!slice->data_ref)
+ return AVERROR(ENOMEM);
+ slice->data = unit->data + pos / 8;
+ slice->data_bit_start = pos % 8;
+ }
+ break;
+
+ case H264_NAL_AUD:
+ {
+ err = cbs_h264_read_aud(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_SEI:
+ {
+ err = cbs_h264_read_sei(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_FILLER_DATA:
+ {
+ err = cbs_h264_read_filler(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_END_SEQUENCE:
+ case H264_NAL_END_STREAM:
+ {
+ err = (unit->type == H264_NAL_END_SEQUENCE ?
+ cbs_h264_read_end_of_sequence :
+ cbs_h264_read_end_of_stream)(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ default:
+ return AVERROR(ENOSYS);
+ }
+
+ return 0;
+}
+
+static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit,
+ PutBitContext *pbc)
+{
+ int err;
+
+ switch (unit->type) {
+ case H264_NAL_SPS:
+ {
+ H264RawSPS *sps = unit->content;
+
+ err = cbs_h264_write_sps(ctx, pbc, sps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h264_replace_sps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_SPS_EXT:
+ {
+ H264RawSPSExtension *sps_ext = unit->content;
+
+ err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_PPS:
+ {
+ H264RawPPS *pps = unit->content;
+
+ err = cbs_h264_write_pps(ctx, pbc, pps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h264_replace_pps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_SLICE:
+ case H264_NAL_IDR_SLICE:
+ case H264_NAL_AUXILIARY_SLICE:
+ {
+ H264RawSlice *slice = unit->content;
+
+ err = cbs_h264_write_slice_header(ctx, pbc, &slice->header);
+ if (err < 0)
+ return err;
+
+ if (slice->data) {
+ err = ff_cbs_h2645_write_slice_data(ctx, pbc, slice->data,
+ slice->data_size,
+ slice->data_bit_start);
+ if (err < 0)
+ return err;
+ } else {
+ // No slice data - that was just the header.
+ // (Bitstream may be unaligned!)
+ }
+ }
+ break;
+
+ case H264_NAL_AUD:
+ {
+ err = cbs_h264_write_aud(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_SEI:
+ {
+ err = cbs_h264_write_sei(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_FILLER_DATA:
+ {
+ err = cbs_h264_write_filler(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_END_SEQUENCE:
+ {
+ err = cbs_h264_write_end_of_sequence(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case H264_NAL_END_STREAM:
+ {
+ err = cbs_h264_write_end_of_stream(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ default:
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
+ "NAL unit type %"PRIu32".\n", unit->type);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ return 0;
+}
+
+static int cbs_h264_discarded_nal_unit(CodedBitstreamContext *ctx,
+ const CodedBitstreamUnit *unit,
+ enum AVDiscard skip)
+{
+ H264RawNALUnitHeader *header;
+ H264RawSliceHeader *slice;
+ int slice_type_i, slice_type_b, slice_type_si;
+
+ if (skip <= AVDISCARD_DEFAULT)
+ return 0;
+
+ // keep non-VCL
+ if (unit->type != H264_NAL_SLICE &&
+ unit->type != H264_NAL_IDR_SLICE &&
+ unit->type != H264_NAL_AUXILIARY_SLICE)
+ return 0;
+
+ if (skip >= AVDISCARD_ALL)
+ return 1;
+
+ if (skip >= AVDISCARD_NONKEY && unit->type != H264_NAL_IDR_SLICE)
+ return 1;
+
+ header = (H264RawNALUnitHeader *)unit->content;
+ if (!header) {
+ av_log(ctx->log_ctx, AV_LOG_WARNING,
+ "h264 nal unit header is null, missing decompose?\n");
+ return 0;
+ }
+
+ if (skip >= AVDISCARD_NONREF && !header->nal_ref_idc)
+ return 1;
+
+ slice = (H264RawSliceHeader *)unit->content;
+ if (!slice) {
+ av_log(ctx->log_ctx, AV_LOG_WARNING,
+ "h264 slice header is null, missing decompose?\n");
+ return 0;
+ }
+
+ slice_type_i = slice->slice_type % 5 == 2;
+ slice_type_b = slice->slice_type % 5 == 1;
+ slice_type_si = slice->slice_type % 5 == 4;
+
+ if (skip >= AVDISCARD_BIDIR && slice_type_b)
+ return 1;
+ if (skip >= AVDISCARD_NONINTRA && !slice_type_i && !slice_type_si)
+ return 1;
+
+ return 0;
+}
+
+static av_cold void cbs_h264_flush(CodedBitstreamContext *ctx)
+{
+ CodedBitstreamH264Context *h264 = ctx->priv_data;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++)
+ av_refstruct_unref(&h264->sps[i]);
+ for (int i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++)
+ av_refstruct_unref(&h264->pps[i]);
+
+ h264->active_sps = NULL;
+ h264->active_pps = NULL;
+ h264->last_slice_nal_unit_type = 0;
+}
+
+static av_cold void cbs_h264_close(CodedBitstreamContext *ctx)
+{
+ CodedBitstreamH264Context *h264 = ctx->priv_data;
+ int i;
+
+ ff_h2645_packet_uninit(&h264->common.read_packet);
+
+ for (i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++)
+ av_refstruct_unref(&h264->sps[i]);
+ for (i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++)
+ av_refstruct_unref(&h264->pps[i]);
+}
+
+static void cbs_h264_free_sei(AVRefStructOpaque unused, void *content)
+{
+ H264RawSEI *sei = content;
+ ff_cbs_sei_free_message_list(&sei->message_list);
+}
+
+static CodedBitstreamUnitTypeDescriptor cbs_h264_unit_types[] = {
+ CBS_UNIT_TYPE_POD(H264_NAL_SPS, H264RawSPS),
+ CBS_UNIT_TYPE_POD(H264_NAL_SPS_EXT, H264RawSPSExtension),
+
+ CBS_UNIT_TYPE_INTERNAL_REF(H264_NAL_PPS, H264RawPPS, slice_group_id),
+
+ CBS_UNIT_TYPES_INTERNAL_REF((H264_NAL_IDR_SLICE,
+ H264_NAL_SLICE,
+ H264_NAL_AUXILIARY_SLICE), H264RawSlice, data),
+
+ CBS_UNIT_TYPE_POD(H264_NAL_AUD, H264RawAUD),
+ CBS_UNIT_TYPE_POD(H264_NAL_FILLER_DATA, H264RawFiller),
+ CBS_UNIT_TYPE_POD(H264_NAL_END_SEQUENCE, H264RawNALUnitHeader),
+ CBS_UNIT_TYPE_POD(H264_NAL_END_STREAM, H264RawNALUnitHeader),
+
+ CBS_UNIT_TYPE_COMPLEX(H264_NAL_SEI, H264RawSEI, &cbs_h264_free_sei),
+
+ CBS_UNIT_TYPE_END_OF_LIST
+};
+
+const CodedBitstreamType ff_cbs_type_h264 = {
+ .codec_id = AV_CODEC_ID_H264,
+
+ .priv_data_size = sizeof(CodedBitstreamH264Context),
+
+ .unit_types = cbs_h264_unit_types,
+
+ .split_fragment = &cbs_h264_split_fragment,
+ .read_unit = &cbs_h264_read_nal_unit,
+ .write_unit = &cbs_h264_write_nal_unit,
+ .discarded_unit = &cbs_h264_discarded_nal_unit,
+ .assemble_fragment = &ff_cbs_h2645_assemble_fragment,
+
+ .flush = &cbs_h264_flush,
+ .close = &cbs_h264_close,
+};
+
+// Macro for the read/write pair.
+#define SEI_MESSAGE_RW(codec, name) \
+ .read = cbs_ ## codec ## _read_ ## name ## _internal, \
+ .write = cbs_ ## codec ## _write_ ## name ## _internal
+
+const SEIMessageTypeDescriptor ff_cbs_sei_h264_types[] = {
+ {
+ SEI_TYPE_BUFFERING_PERIOD,
+ 1, 0,
+ sizeof(H264RawSEIBufferingPeriod),
+ SEI_MESSAGE_RW(h264, sei_buffering_period),
+ },
+ {
+ SEI_TYPE_PIC_TIMING,
+ 1, 0,
+ sizeof(H264RawSEIPicTiming),
+ SEI_MESSAGE_RW(h264, sei_pic_timing),
+ },
+ {
+ SEI_TYPE_PAN_SCAN_RECT,
+ 1, 0,
+ sizeof(H264RawSEIPanScanRect),
+ SEI_MESSAGE_RW(h264, sei_pan_scan_rect),
+ },
+ {
+ SEI_TYPE_RECOVERY_POINT,
+ 1, 0,
+ sizeof(H264RawSEIRecoveryPoint),
+ SEI_MESSAGE_RW(h264, sei_recovery_point),
+ },
+ {
+ SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
+ 1, 0,
+ sizeof(H264RawFilmGrainCharacteristics),
+ SEI_MESSAGE_RW(h264, film_grain_characteristics),
+ },
+ {
+ SEI_TYPE_FRAME_PACKING_ARRANGEMENT,
+ 1, 0,
+ sizeof(H264RawSEIFramePackingArrangement),
+ SEI_MESSAGE_RW(h264, sei_frame_packing_arrangement),
+ },
+ {
+ SEI_TYPE_DISPLAY_ORIENTATION,
+ 1, 0,
+ sizeof(H264RawSEIDisplayOrientation),
+ SEI_MESSAGE_RW(h264, sei_display_orientation),
+ },
+ SEI_MESSAGE_TYPE_END
+};
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 0dd256ada0..bcf6144046 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -23,17 +23,22 @@
#include "bytestream.h"
#include "cbs.h"
#include "cbs_internal.h"
-#include "cbs_h264.h"
-#include "cbs_h265.h"
-#include "cbs_h266.h"
+#include "cbs_h2645.h"
#include "h264.h"
#include "h2645_parse.h"
-#include "libavutil/refstruct.h"
#include "vvc.h"
#include "hevc/hevc.h"
-static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc,
+int ff_cbs_h2645_payload_extension_present(GetBitContext *gbc, uint32_t payload_size,
+ int cur_pos)
+{
+ int bits_left = payload_size * 8 - cur_pos;
+ return (bits_left > 0 &&
+ (bits_left > 7 || show_bits(gbc, bits_left) & MAX_UINT_BITS(bits_left - 1)));
+}
+
+int ff_cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc,
const char *name, const int *subscripts,
uint32_t *write_to,
uint32_t range_min, uint32_t range_max)
@@ -82,7 +87,7 @@ static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc,
return 0;
}
-static int cbs_read_se_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc,
+int ff_cbs_read_se_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc,
const char *name, const int *subscripts,
int32_t *write_to,
int32_t range_min, int32_t range_max)
@@ -137,7 +142,7 @@ static int cbs_read_se_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc,
return 0;
}
-static int cbs_write_ue_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc,
+int ff_cbs_write_ue_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc,
const char *name, const int *subscripts,
uint32_t value,
uint32_t range_min, uint32_t range_max)
@@ -169,7 +174,7 @@ static int cbs_write_ue_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc,
return 0;
}
-static int cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc,
+int ff_cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc,
const char *name, const int *subscripts,
int32_t value,
int32_t range_min, int32_t range_max)
@@ -209,123 +214,7 @@ static int cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc,
return 0;
}
-// payload_extension_present() - true if we are before the last 1-bit
-// in the payload structure, which must be in the last byte.
-static int cbs_h265_payload_extension_present(GetBitContext *gbc, uint32_t payload_size,
- int cur_pos)
-{
- int bits_left = payload_size * 8 - cur_pos;
- return (bits_left > 0 &&
- (bits_left > 7 || show_bits(gbc, bits_left) & MAX_UINT_BITS(bits_left - 1)));
-}
-
-#define HEADER(name) do { \
- ff_cbs_trace_header(ctx, name); \
- } while (0)
-
-#define CHECK(call) do { \
- err = (call); \
- if (err < 0) \
- return err; \
- } while (0)
-
-#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
-#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
-#define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name)
-#define FUNC_H265(name) FUNC_NAME1(READWRITE, h265, name)
-#define FUNC_H266(name) FUNC_NAME1(READWRITE, h266, name)
-#define FUNC_SEI(name) FUNC_NAME1(READWRITE, sei, name)
-
-#define SEI_FUNC(name, args) \
-static int FUNC(name) args; \
-static int FUNC(name ## _internal)(CodedBitstreamContext *ctx, \
- RWContext *rw, void *cur, \
- SEIMessageState *state) \
-{ \
- return FUNC(name)(ctx, rw, cur, state); \
-} \
-static int FUNC(name) args
-
-#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
-
-#define u(width, name, range_min, range_max) \
- xu(width, name, current->name, range_min, range_max, 0, )
-#define flag(name) ub(1, name)
-#define ue(name, range_min, range_max) \
- xue(name, current->name, range_min, range_max, 0, )
-#define i(width, name, range_min, range_max) \
- xi(width, name, current->name, range_min, range_max, 0, )
-#define ib(width, name) \
- xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
-#define se(name, range_min, range_max) \
- xse(name, current->name, range_min, range_max, 0, )
-
-#define us(width, name, range_min, range_max, subs, ...) \
- xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
-#define ubs(width, name, subs, ...) \
- xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
-#define flags(name, subs, ...) \
- xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
-#define ues(name, range_min, range_max, subs, ...) \
- xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
-#define is(width, name, range_min, range_max, subs, ...) \
- xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
-#define ibs(width, name, subs, ...) \
- xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
-#define ses(name, range_min, range_max, subs, ...) \
- xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
-
-#define fixed(width, name, value) do { \
- av_unused uint32_t fixed_value = value; \
- xu(width, name, fixed_value, value, value, 0, ); \
- } while (0)
-
-
-#define READ
-#define READWRITE read
-#define RWContext GetBitContext
-
-#define ub(width, name) do { \
- uint32_t value; \
- CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
- &value)); \
- current->name = value; \
- } while (0)
-#define xu(width, name, var, range_min, range_max, subs, ...) do { \
- uint32_t value; \
- CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- &value, range_min, range_max)); \
- var = value; \
- } while (0)
-#define xue(name, var, range_min, range_max, subs, ...) do { \
- uint32_t value; \
- CHECK(cbs_read_ue_golomb(ctx, rw, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- &value, range_min, range_max)); \
- var = value; \
- } while (0)
-#define xi(width, name, var, range_min, range_max, subs, ...) do { \
- int32_t value; \
- CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- &value, range_min, range_max)); \
- var = value; \
- } while (0)
-#define xse(name, var, range_min, range_max, subs, ...) do { \
- int32_t value; \
- CHECK(cbs_read_se_golomb(ctx, rw, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- &value, range_min, range_max)); \
- var = value; \
- } while (0)
-
-
-#define infer(name, value) do { \
- current->name = value; \
- } while (0)
-
-static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
+int ff_cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
{
int bits_left = get_bits_left(gbc);
if (bits_left > 8)
@@ -337,157 +226,7 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
return 0;
}
-#define more_rbsp_data(var) ((var) = cbs_h2645_read_more_rbsp_data(rw))
-
-#define bit_position(rw) (get_bits_count(rw))
-#define byte_alignment(rw) (get_bits_count(rw) % 8)
-
-/* The CBS SEI code uses the refstruct API for the allocation
- * of its child buffers. */
-#define allocate(name, size) do { \
- name = av_refstruct_allocz(size + \
- AV_INPUT_BUFFER_PADDING_SIZE); \
- if (!name) \
- return AVERROR(ENOMEM); \
- } while (0)
-
-#define FUNC(name) FUNC_SEI(name)
-#include "cbs_sei_syntax_template.c"
-#undef FUNC
-
-#undef allocate
-
-/* The other code uses the refstruct API for the allocation
- * of its child buffers. */
-#define allocate(name, size) do { \
- name ## _ref = av_buffer_allocz(size + \
- AV_INPUT_BUFFER_PADDING_SIZE); \
- if (!name ## _ref) \
- return AVERROR(ENOMEM); \
- name = name ## _ref->data; \
- } while (0)
-
-#define FUNC(name) FUNC_H264(name)
-#include "cbs_h264_syntax_template.c"
-#undef FUNC
-
-#define FUNC(name) FUNC_H265(name)
-#include "cbs_h265_syntax_template.c"
-#undef FUNC
-
-#define FUNC(name) FUNC_H266(name)
-#include "cbs_h266_syntax_template.c"
-#undef FUNC
-
-#undef READ
-#undef READWRITE
-#undef RWContext
-#undef ub
-#undef xu
-#undef xi
-#undef xue
-#undef xse
-#undef infer
-#undef more_rbsp_data
-#undef bit_position
-#undef byte_alignment
-#undef allocate
-
-
-#define WRITE
-#define READWRITE write
-#define RWContext PutBitContext
-
-#define ub(width, name) do { \
- uint32_t value = current->name; \
- CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
- value)); \
- } while (0)
-#define xu(width, name, var, range_min, range_max, subs, ...) do { \
- uint32_t value = var; \
- CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- value, range_min, range_max)); \
- } while (0)
-#define xue(name, var, range_min, range_max, subs, ...) do { \
- uint32_t value = var; \
- CHECK(cbs_write_ue_golomb(ctx, rw, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- value, range_min, range_max)); \
- } while (0)
-#define xi(width, name, var, range_min, range_max, subs, ...) do { \
- int32_t value = var; \
- CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- value, range_min, range_max)); \
- } while (0)
-#define xse(name, var, range_min, range_max, subs, ...) do { \
- int32_t value = var; \
- CHECK(cbs_write_se_golomb(ctx, rw, #name, \
- SUBSCRIPTS(subs, __VA_ARGS__), \
- value, range_min, range_max)); \
- } while (0)
-
-#define infer(name, value) do { \
- if (current->name != (value)) { \
- av_log(ctx->log_ctx, AV_LOG_ERROR, \
- "%s does not match inferred value: " \
- "%"PRId64", but should be %"PRId64".\n", \
- #name, (int64_t)current->name, (int64_t)(value)); \
- return AVERROR_INVALIDDATA; \
- } \
- } while (0)
-
-#define more_rbsp_data(var) (var)
-
-#define bit_position(rw) (put_bits_count(rw))
-#define byte_alignment(rw) (put_bits_count(rw) % 8)
-
-#define allocate(name, size) do { \
- if (!name) { \
- av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
- "for writing.\n", #name); \
- return AVERROR_INVALIDDATA; \
- } \
- } while (0)
-
-#define FUNC(name) FUNC_SEI(name)
-#include "cbs_sei_syntax_template.c"
-#undef FUNC
-
-#define FUNC(name) FUNC_H264(name)
-#include "cbs_h264_syntax_template.c"
-#undef FUNC
-
-#define FUNC(name) FUNC_H265(name)
-#include "cbs_h265_syntax_template.c"
-#undef FUNC
-
-#define FUNC(name) FUNC_H266(name)
-#include "cbs_h266_syntax_template.c"
-#undef FUNC
-
-#undef WRITE
-#undef READWRITE
-#undef RWContext
-#undef ub
-#undef xu
-#undef xi
-#undef xue
-#undef xse
-#undef u
-#undef i
-#undef flag
-#undef ue
-#undef se
-#undef infer
-#undef more_rbsp_data
-#undef bit_position
-#undef byte_alignment
-#undef allocate
-
-
-static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
+int ff_cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag,
const H2645Packet *packet)
{
@@ -523,729 +262,7 @@ static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
return 0;
}
-static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
- CodedBitstreamFragment *frag,
- int header)
-{
- enum AVCodecID codec_id = ctx->codec->codec_id;
- CodedBitstreamH2645Context *priv = ctx->priv_data;
- GetByteContext gbc;
- int err;
-
- av_assert0(frag->data && frag->nb_units == 0);
- if (frag->data_size == 0)
- return 0;
-
- if (header && frag->data[0] && codec_id == AV_CODEC_ID_H264) {
- // AVCC header.
- size_t size, start, end;
- int i, count, version;
-
- priv->mp4 = 1;
-
- bytestream2_init(&gbc, frag->data, frag->data_size);
-
- if (bytestream2_get_bytes_left(&gbc) < 6)
- return AVERROR_INVALIDDATA;
-
- version = bytestream2_get_byte(&gbc);
- if (version != 1) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid AVCC header: "
- "first byte %u.\n", version);
- return AVERROR_INVALIDDATA;
- }
-
- bytestream2_skip(&gbc, 3);
- priv->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1;
-
- // SPS array.
- count = bytestream2_get_byte(&gbc) & 0x1f;
- start = bytestream2_tell(&gbc);
- for (i = 0; i < count; i++) {
- if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i))
- return AVERROR_INVALIDDATA;
- size = bytestream2_get_be16(&gbc);
- if (bytestream2_get_bytes_left(&gbc) < size)
- return AVERROR_INVALIDDATA;
- bytestream2_skip(&gbc, size);
- }
- end = bytestream2_tell(&gbc);
-
- err = ff_h2645_packet_split(&priv->read_packet,
- frag->data + start, end - start,
- ctx->log_ctx, 2, AV_CODEC_ID_H264,
- H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
- if (err < 0) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC SPS array.\n");
- return err;
- }
- err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet);
- if (err < 0)
- return err;
-
- // PPS array.
- count = bytestream2_get_byte(&gbc);
- start = bytestream2_tell(&gbc);
- for (i = 0; i < count; i++) {
- if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i))
- return AVERROR_INVALIDDATA;
- size = bytestream2_get_be16(&gbc);
- if (bytestream2_get_bytes_left(&gbc) < size)
- return AVERROR_INVALIDDATA;
- bytestream2_skip(&gbc, size);
- }
- end = bytestream2_tell(&gbc);
-
- err = ff_h2645_packet_split(&priv->read_packet,
- frag->data + start, end - start,
- ctx->log_ctx, 2, AV_CODEC_ID_H264,
- H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
- if (err < 0) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC PPS array.\n");
- return err;
- }
- err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet);
- if (err < 0)
- return err;
-
- if (bytestream2_get_bytes_left(&gbc) > 0) {
- av_log(ctx->log_ctx, AV_LOG_WARNING, "%u bytes left at end of AVCC "
- "header.\n", bytestream2_get_bytes_left(&gbc));
- }
-
- } else if (header && frag->data[0] && codec_id == AV_CODEC_ID_HEVC) {
- // HVCC header.
- size_t size, start, end;
- int i, j, nb_arrays, nal_unit_type, nb_nals, version;
-
- priv->mp4 = 1;
-
- bytestream2_init(&gbc, frag->data, frag->data_size);
-
- if (bytestream2_get_bytes_left(&gbc) < 23)
- return AVERROR_INVALIDDATA;
-
- version = bytestream2_get_byte(&gbc);
- if (version != 1) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid HVCC header: "
- "first byte %u.\n", version);
- return AVERROR_INVALIDDATA;
- }
-
- bytestream2_skip(&gbc, 20);
- priv->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1;
-
- nb_arrays = bytestream2_get_byte(&gbc);
- for (i = 0; i < nb_arrays; i++) {
- nal_unit_type = bytestream2_get_byte(&gbc) & 0x3f;
- nb_nals = bytestream2_get_be16(&gbc);
-
- start = bytestream2_tell(&gbc);
- for (j = 0; j < nb_nals; j++) {
- if (bytestream2_get_bytes_left(&gbc) < 2)
- return AVERROR_INVALIDDATA;
- size = bytestream2_get_be16(&gbc);
- if (bytestream2_get_bytes_left(&gbc) < size)
- return AVERROR_INVALIDDATA;
- bytestream2_skip(&gbc, size);
- }
- end = bytestream2_tell(&gbc);
-
- err = ff_h2645_packet_split(&priv->read_packet,
- frag->data + start, end - start,
- ctx->log_ctx, 2, AV_CODEC_ID_HEVC,
- H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
- if (err < 0) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split "
- "HVCC array %d (%d NAL units of type %d).\n",
- i, nb_nals, nal_unit_type);
- return err;
- }
- err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet);
- if (err < 0)
- return err;
- }
-
- } else if(header && frag->data[0] && codec_id == AV_CODEC_ID_VVC) {
- // VVCC header.
- int ptl_present_flag, num_arrays;
- int b, i, j;
-
- priv->mp4 = 1;
-
- bytestream2_init(&gbc, frag->data, frag->data_size);
-
- b = bytestream2_get_byte(&gbc);
- priv->nal_length_size = ((b >> 1) & 3) + 1;
- ptl_present_flag = b & 1;
-
- if(ptl_present_flag) {
- int num_sublayers, num_bytes_constraint_info, num_sub_profiles;
- num_sublayers = (bytestream2_get_be16u(&gbc) >> 4) & 7;
- bytestream2_skip(&gbc, 1);
-
- // begin VvcPTLRecord(num_sublayers);
- num_bytes_constraint_info = bytestream2_get_byte(&gbc) & 0x3f;
- bytestream2_skip(&gbc, 2 + num_bytes_constraint_info);
- if(num_sublayers > 1) {
- int count_present_flags = 0;
- b = bytestream2_get_byte(&gbc);
- for(i = num_sublayers - 2; i >= 0; i--) {
- if((b >> (7 - (num_sublayers - 2 - i))) & 0x01)
- count_present_flags++;
- }
- bytestream2_skip(&gbc, count_present_flags);
- }
- num_sub_profiles = bytestream2_get_byte(&gbc);
- bytestream2_skip(&gbc, num_sub_profiles * 4);
- // end VvcPTLRecord(num_sublayers);
-
- bytestream2_skip(&gbc, 3 * 2);
- }
-
- num_arrays = bytestream2_get_byte(&gbc);
- for(j = 0; j < num_arrays; j++) {
- size_t start, end, size;
- int nal_unit_type = bytestream2_get_byte(&gbc) & 0x1f;
- unsigned int num_nalus = 1;
- if(nal_unit_type != VVC_DCI_NUT && nal_unit_type != VVC_OPI_NUT)
- num_nalus = bytestream2_get_be16(&gbc);
-
- start = bytestream2_tell(&gbc);
- for(i = 0; i < num_nalus; i++) {
- if (bytestream2_get_bytes_left(&gbc) < 2)
- return AVERROR_INVALIDDATA;
- size = bytestream2_get_be16(&gbc);
- if (bytestream2_get_bytes_left(&gbc) < size)
- return AVERROR_INVALIDDATA;
- bytestream2_skip(&gbc, size);
- }
- end = bytestream2_tell(&gbc);
-
- err = ff_h2645_packet_split(&priv->read_packet,
- frag->data + start, end - start,
- ctx->log_ctx, 2, AV_CODEC_ID_VVC,
- H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
- if (err < 0) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split "
- "VVCC array %d (%d NAL units of type %d).\n",
- i, num_nalus, nal_unit_type);
- return err;
- }
- err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet);
- if (err < 0)
- return err;
- }
- } else {
- int flags = (H2645_FLAG_IS_NALFF * !!priv->mp4) | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF;
- // Annex B, or later MP4 with already-known parameters.
-
- err = ff_h2645_packet_split(&priv->read_packet,
- frag->data, frag->data_size,
- ctx->log_ctx,
- priv->nal_length_size,
- codec_id, flags);
- if (err < 0)
- return err;
-
- err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-#define cbs_h2645_replace_ps(h26n, ps_name, ps_var, id_element) \
-static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \
- CodedBitstreamUnit *unit) \
-{ \
- CodedBitstreamH26 ## h26n ## Context *priv = ctx->priv_data; \
- H26 ## h26n ## Raw ## ps_name *ps_var = unit->content; \
- unsigned int id = ps_var->id_element; \
- int err = ff_cbs_make_unit_refcounted(ctx, unit); \
- if (err < 0) \
- return err; \
- if (priv->ps_var[id] == priv->active_ ## ps_var) \
- priv->active_ ## ps_var = NULL ; \
- av_assert0(unit->content_ref); \
- av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
- return 0; \
-}
-
-cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id)
-cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id)
-cbs_h2645_replace_ps(5, VPS, vps, vps_video_parameter_set_id)
-cbs_h2645_replace_ps(5, SPS, sps, sps_seq_parameter_set_id)
-cbs_h2645_replace_ps(5, PPS, pps, pps_pic_parameter_set_id)
-
-#define cbs_h266_replace_ps(h26n, ps_name, ps_var, id_element) \
-static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \
- CodedBitstreamUnit *unit) \
-{ \
- CodedBitstreamH26 ## h26n ## Context *priv = ctx->priv_data; \
- H26 ## h26n ## Raw ## ps_name *ps_var = unit->content; \
- unsigned int id = ps_var->id_element; \
- int err = ff_cbs_make_unit_refcounted(ctx, unit); \
- if (err < 0) \
- return err; \
- av_assert0(unit->content_ref); \
- av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
- return 0; \
-}
-
-cbs_h266_replace_ps(6, VPS, vps, vps_video_parameter_set_id)
-cbs_h266_replace_ps(6, PPS, pps, pps_pic_parameter_set_id)
-
-static int cbs_h266_replace_sps(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit)
-{
- CodedBitstreamH266Context *priv = ctx->priv_data;
- H266RawSPS *sps = unit->content;
- unsigned int id = sps->sps_seq_parameter_set_id;
- int err = ff_cbs_make_unit_refcounted(ctx, unit);
- if (err < 0)
- return err;
- av_assert0(unit->content_ref);
- if (priv->sps[id] && memcmp(priv->sps[id], unit->content_ref, sizeof(*priv->sps[id]))) {
- for (unsigned int i = 0; i < VVC_MAX_PPS_COUNT; i++) {
- if (priv->pps[i] && priv->pps[i]->pps_seq_parameter_set_id == id)
- av_refstruct_unref(&priv->pps[i]);
- }
- }
- av_refstruct_replace(&priv->sps[id], unit->content_ref);
- return 0;
-}
-
-static int cbs_h266_replace_ph(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit,
- H266RawPictureHeader *ph)
-{
- CodedBitstreamH266Context *h266 = ctx->priv_data;
- int err;
-
- err = ff_cbs_make_unit_refcounted(ctx, unit);
- if (err < 0)
- return err;
- av_assert0(unit->content_ref);
- av_refstruct_replace(&h266->ph_ref, unit->content_ref);
- h266->ph = ph;
- return 0;
-}
-
-static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit)
-{
- GetBitContext gbc;
- int err;
-
- err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
- if (err < 0)
- return err;
-
- err = ff_cbs_alloc_unit_content(ctx, unit);
- if (err < 0)
- return err;
-
- switch (unit->type) {
- case H264_NAL_SPS:
- {
- H264RawSPS *sps = unit->content;
-
- err = cbs_h264_read_sps(ctx, &gbc, sps);
- if (err < 0)
- return err;
-
- err = cbs_h264_replace_sps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_SPS_EXT:
- {
- err = cbs_h264_read_sps_extension(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_PPS:
- {
- H264RawPPS *pps = unit->content;
-
- err = cbs_h264_read_pps(ctx, &gbc, pps);
- if (err < 0)
- return err;
-
- err = cbs_h264_replace_pps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_SLICE:
- case H264_NAL_IDR_SLICE:
- case H264_NAL_AUXILIARY_SLICE:
- {
- H264RawSlice *slice = unit->content;
- int pos, len;
-
- err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header);
- if (err < 0)
- return err;
-
- if (!cbs_h2645_read_more_rbsp_data(&gbc))
- return AVERROR_INVALIDDATA;
-
- pos = get_bits_count(&gbc);
- len = unit->data_size;
-
- slice->data_size = len - pos / 8;
- slice->data_ref = av_buffer_ref(unit->data_ref);
- if (!slice->data_ref)
- return AVERROR(ENOMEM);
- slice->data = unit->data + pos / 8;
- slice->data_bit_start = pos % 8;
- }
- break;
-
- case H264_NAL_AUD:
- {
- err = cbs_h264_read_aud(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_SEI:
- {
- err = cbs_h264_read_sei(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_FILLER_DATA:
- {
- err = cbs_h264_read_filler(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_END_SEQUENCE:
- case H264_NAL_END_STREAM:
- {
- err = (unit->type == H264_NAL_END_SEQUENCE ?
- cbs_h264_read_end_of_sequence :
- cbs_h264_read_end_of_stream)(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- default:
- return AVERROR(ENOSYS);
- }
-
- return 0;
-}
-
-static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit)
-{
- GetBitContext gbc;
- int err;
-
- err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
- if (err < 0)
- return err;
-
- err = ff_cbs_alloc_unit_content(ctx, unit);
- if (err < 0)
- return err;
-
- switch (unit->type) {
- case HEVC_NAL_VPS:
- {
- H265RawVPS *vps = unit->content;
-
- err = cbs_h265_read_vps(ctx, &gbc, vps);
- if (err < 0)
- return err;
-
- err = cbs_h265_replace_vps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
- case HEVC_NAL_SPS:
- {
- H265RawSPS *sps = unit->content;
-
- err = cbs_h265_read_sps(ctx, &gbc, sps);
- if (err < 0)
- return err;
-
- err = cbs_h265_replace_sps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_PPS:
- {
- H265RawPPS *pps = unit->content;
-
- err = cbs_h265_read_pps(ctx, &gbc, pps);
- if (err < 0)
- return err;
-
- err = cbs_h265_replace_pps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_TRAIL_N:
- case HEVC_NAL_TRAIL_R:
- case HEVC_NAL_TSA_N:
- case HEVC_NAL_TSA_R:
- case HEVC_NAL_STSA_N:
- case HEVC_NAL_STSA_R:
- case HEVC_NAL_RADL_N:
- case HEVC_NAL_RADL_R:
- case HEVC_NAL_RASL_N:
- case HEVC_NAL_RASL_R:
- case HEVC_NAL_BLA_W_LP:
- case HEVC_NAL_BLA_W_RADL:
- case HEVC_NAL_BLA_N_LP:
- case HEVC_NAL_IDR_W_RADL:
- case HEVC_NAL_IDR_N_LP:
- case HEVC_NAL_CRA_NUT:
- {
- H265RawSlice *slice = unit->content;
- int pos, len;
-
- err = cbs_h265_read_slice_segment_header(ctx, &gbc, &slice->header);
- if (err < 0)
- return err;
-
- if (!cbs_h2645_read_more_rbsp_data(&gbc))
- return AVERROR_INVALIDDATA;
-
- pos = get_bits_count(&gbc);
- len = unit->data_size;
-
- slice->data_size = len - pos / 8;
- slice->data_ref = av_buffer_ref(unit->data_ref);
- if (!slice->data_ref)
- return AVERROR(ENOMEM);
- slice->data = unit->data + pos / 8;
- slice->data_bit_start = pos % 8;
- }
- break;
-
- case HEVC_NAL_AUD:
- {
- err = cbs_h265_read_aud(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_FD_NUT:
- {
- err = cbs_h265_read_filler(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_SEI_PREFIX:
- case HEVC_NAL_SEI_SUFFIX:
- {
- err = cbs_h265_read_sei(ctx, &gbc, unit->content,
- unit->type == HEVC_NAL_SEI_PREFIX);
-
- if (err < 0)
- return err;
- }
- break;
-
- default:
- return AVERROR(ENOSYS);
- }
-
- return 0;
-}
-
-static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit)
-{
- GetBitContext gbc;
- int err;
- CodedBitstreamH266Context *h266 = ctx->priv_data;
-
- err = init_get_bits8(&gbc, unit->data, unit->data_size);
- if (err < 0)
- return err;
-
- err = ff_cbs_alloc_unit_content(ctx, unit);
- if (err < 0)
- return err;
-
- switch (unit->type) {
- case VVC_DCI_NUT:
- {
- err = cbs_h266_read_dci(ctx, &gbc, unit->content);
-
- if (err < 0)
- return err;
- }
- break;
- case VVC_OPI_NUT:
- {
- err = cbs_h266_read_opi(ctx, &gbc, unit->content);
-
- if (err < 0)
- return err;
- }
- break;
- case VVC_VPS_NUT:
- {
- H266RawVPS *vps = unit->content;
-
- err = cbs_h266_read_vps(ctx, &gbc, vps);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_vps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
- case VVC_SPS_NUT:
- {
- H266RawSPS *sps = unit->content;
-
- err = cbs_h266_read_sps(ctx, &gbc, sps);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_sps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_PPS_NUT:
- {
- H266RawPPS *pps = unit->content;
-
- err = cbs_h266_read_pps(ctx, &gbc, pps);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_pps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_PREFIX_APS_NUT:
- case VVC_SUFFIX_APS_NUT:
- {
- err = cbs_h266_read_aps(ctx, &gbc, unit->content,
- unit->type == VVC_PREFIX_APS_NUT);
-
- if (err < 0)
- return err;
- }
- break;
- case VVC_PH_NUT:
- {
- H266RawPH *ph = unit->content;
- err = cbs_h266_read_ph(ctx, &gbc, ph);
- if (err < 0)
- return err;
- err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_TRAIL_NUT:
- case VVC_STSA_NUT:
- case VVC_RADL_NUT:
- case VVC_RASL_NUT:
- case VVC_IDR_W_RADL:
- case VVC_IDR_N_LP:
- case VVC_CRA_NUT:
- case VVC_GDR_NUT:
- {
- H266RawSlice *slice = unit->content;
- int pos, len;
-
- err = cbs_h266_read_slice_header(ctx, &gbc, &slice->header);
- if (err < 0)
- return err;
-
- if (!cbs_h2645_read_more_rbsp_data(&gbc))
- return AVERROR_INVALIDDATA;
-
- pos = get_bits_count(&gbc);
- len = unit->data_size;
-
- if (slice->header.sh_picture_header_in_slice_header_flag) {
- err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
- if (err < 0)
- return err;
- slice->ph_ref = NULL;
- } else {
- slice->ph_ref = av_refstruct_ref(h266->ph_ref);
- }
- slice->ph = h266->ph;
- slice->pps = av_refstruct_ref(h266->pps[slice->ph->ph_pic_parameter_set_id]);
- slice->sps = av_refstruct_ref(h266->sps[slice->pps->pps_seq_parameter_set_id]);
-
- slice->header_size = pos / 8;
- slice->data_size = len - pos / 8;
- slice->data_ref = av_buffer_ref(unit->data_ref);
- if (!slice->data_ref)
- return AVERROR(ENOMEM);
- slice->data = unit->data + pos / 8;
- slice->data_bit_start = pos % 8;
- }
- break;
-
- case VVC_AUD_NUT:
- {
- err = cbs_h266_read_aud(ctx, &gbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_PREFIX_SEI_NUT:
- case VVC_SUFFIX_SEI_NUT:
- {
- err = cbs_h266_read_sei(ctx, &gbc, unit->content,
- unit->type == VVC_PREFIX_SEI_NUT);
-
- if (err < 0)
- return err;
- }
- break;
-
- default:
- return AVERROR(ENOSYS);
- }
- return 0;
-}
-
-static int cbs_h2645_write_slice_data(CodedBitstreamContext *ctx,
+int ff_cbs_h2645_write_slice_data(CodedBitstreamContext *ctx,
PutBitContext *pbc, const uint8_t *data,
size_t data_size, int data_bit_start)
{
@@ -1303,518 +320,7 @@ static int cbs_h2645_write_slice_data(CodedBitstreamContext *ctx,
return 0;
}
-static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit,
- PutBitContext *pbc)
-{
- int err;
-
- switch (unit->type) {
- case H264_NAL_SPS:
- {
- H264RawSPS *sps = unit->content;
-
- err = cbs_h264_write_sps(ctx, pbc, sps);
- if (err < 0)
- return err;
-
- err = cbs_h264_replace_sps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_SPS_EXT:
- {
- H264RawSPSExtension *sps_ext = unit->content;
-
- err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_PPS:
- {
- H264RawPPS *pps = unit->content;
-
- err = cbs_h264_write_pps(ctx, pbc, pps);
- if (err < 0)
- return err;
-
- err = cbs_h264_replace_pps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_SLICE:
- case H264_NAL_IDR_SLICE:
- case H264_NAL_AUXILIARY_SLICE:
- {
- H264RawSlice *slice = unit->content;
-
- err = cbs_h264_write_slice_header(ctx, pbc, &slice->header);
- if (err < 0)
- return err;
-
- if (slice->data) {
- err = cbs_h2645_write_slice_data(ctx, pbc, slice->data,
- slice->data_size,
- slice->data_bit_start);
- if (err < 0)
- return err;
- } else {
- // No slice data - that was just the header.
- // (Bitstream may be unaligned!)
- }
- }
- break;
-
- case H264_NAL_AUD:
- {
- err = cbs_h264_write_aud(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_SEI:
- {
- err = cbs_h264_write_sei(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_FILLER_DATA:
- {
- err = cbs_h264_write_filler(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_END_SEQUENCE:
- {
- err = cbs_h264_write_end_of_sequence(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case H264_NAL_END_STREAM:
- {
- err = cbs_h264_write_end_of_stream(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- default:
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
- "NAL unit type %"PRIu32".\n", unit->type);
- return AVERROR_PATCHWELCOME;
- }
-
- return 0;
-}
-
-static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit,
- PutBitContext *pbc)
-{
- int err;
-
- switch (unit->type) {
- case HEVC_NAL_VPS:
- {
- H265RawVPS *vps = unit->content;
-
- err = cbs_h265_write_vps(ctx, pbc, vps);
- if (err < 0)
- return err;
-
- err = cbs_h265_replace_vps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_SPS:
- {
- H265RawSPS *sps = unit->content;
-
- err = cbs_h265_write_sps(ctx, pbc, sps);
- if (err < 0)
- return err;
-
- err = cbs_h265_replace_sps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_PPS:
- {
- H265RawPPS *pps = unit->content;
-
- err = cbs_h265_write_pps(ctx, pbc, pps);
- if (err < 0)
- return err;
-
- err = cbs_h265_replace_pps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_TRAIL_N:
- case HEVC_NAL_TRAIL_R:
- case HEVC_NAL_TSA_N:
- case HEVC_NAL_TSA_R:
- case HEVC_NAL_STSA_N:
- case HEVC_NAL_STSA_R:
- case HEVC_NAL_RADL_N:
- case HEVC_NAL_RADL_R:
- case HEVC_NAL_RASL_N:
- case HEVC_NAL_RASL_R:
- case HEVC_NAL_BLA_W_LP:
- case HEVC_NAL_BLA_W_RADL:
- case HEVC_NAL_BLA_N_LP:
- case HEVC_NAL_IDR_W_RADL:
- case HEVC_NAL_IDR_N_LP:
- case HEVC_NAL_CRA_NUT:
- {
- H265RawSlice *slice = unit->content;
-
- err = cbs_h265_write_slice_segment_header(ctx, pbc, &slice->header);
- if (err < 0)
- return err;
-
- if (slice->data) {
- err = cbs_h2645_write_slice_data(ctx, pbc, slice->data,
- slice->data_size,
- slice->data_bit_start);
- if (err < 0)
- return err;
- } else {
- // No slice data - that was just the header.
- }
- }
- break;
-
- case HEVC_NAL_AUD:
- {
- err = cbs_h265_write_aud(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_FD_NUT:
- {
- err = cbs_h265_write_filler(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case HEVC_NAL_SEI_PREFIX:
- case HEVC_NAL_SEI_SUFFIX:
- {
- err = cbs_h265_write_sei(ctx, pbc, unit->content,
- unit->type == HEVC_NAL_SEI_PREFIX);
-
- if (err < 0)
- return err;
- }
- break;
-
- default:
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
- "NAL unit type %"PRIu32".\n", unit->type);
- return AVERROR_PATCHWELCOME;
- }
-
- return 0;
-}
-
-static int cbs_h264_discarded_nal_unit(CodedBitstreamContext *ctx,
- const CodedBitstreamUnit *unit,
- enum AVDiscard skip)
-{
- H264RawNALUnitHeader *header;
- H264RawSliceHeader *slice;
- int slice_type_i, slice_type_b, slice_type_si;
-
- if (skip <= AVDISCARD_DEFAULT)
- return 0;
-
- // keep non-VCL
- if (unit->type != H264_NAL_SLICE &&
- unit->type != H264_NAL_IDR_SLICE &&
- unit->type != H264_NAL_AUXILIARY_SLICE)
- return 0;
-
- if (skip >= AVDISCARD_ALL)
- return 1;
-
- if (skip >= AVDISCARD_NONKEY && unit->type != H264_NAL_IDR_SLICE)
- return 1;
-
- header = (H264RawNALUnitHeader *)unit->content;
- if (!header) {
- av_log(ctx->log_ctx, AV_LOG_WARNING,
- "h264 nal unit header is null, missing decompose?\n");
- return 0;
- }
-
- if (skip >= AVDISCARD_NONREF && !header->nal_ref_idc)
- return 1;
-
- slice = (H264RawSliceHeader *)unit->content;
- if (!slice) {
- av_log(ctx->log_ctx, AV_LOG_WARNING,
- "h264 slice header is null, missing decompose?\n");
- return 0;
- }
-
- slice_type_i = slice->slice_type % 5 == 2;
- slice_type_b = slice->slice_type % 5 == 1;
- slice_type_si = slice->slice_type % 5 == 4;
-
- if (skip >= AVDISCARD_BIDIR && slice_type_b)
- return 1;
- if (skip >= AVDISCARD_NONINTRA && !slice_type_i && !slice_type_si)
- return 1;
-
- return 0;
-}
-
-static int cbs_h265_discarded_nal_unit(CodedBitstreamContext *ctx,
- const CodedBitstreamUnit *unit,
- enum AVDiscard skip)
-{
- H265RawSliceHeader *slice;
-
- if (skip <= AVDISCARD_DEFAULT)
- return 0;
-
- switch (unit->type) {
- case HEVC_NAL_BLA_W_LP:
- case HEVC_NAL_BLA_W_RADL:
- case HEVC_NAL_BLA_N_LP:
- case HEVC_NAL_IDR_W_RADL:
- case HEVC_NAL_IDR_N_LP:
- case HEVC_NAL_CRA_NUT:
- // IRAP slice
- if (skip < AVDISCARD_ALL)
- return 0;
- break;
-
- case HEVC_NAL_TRAIL_R:
- case HEVC_NAL_TRAIL_N:
- case HEVC_NAL_TSA_N:
- case HEVC_NAL_TSA_R:
- case HEVC_NAL_STSA_N:
- case HEVC_NAL_STSA_R:
- case HEVC_NAL_RADL_N:
- case HEVC_NAL_RADL_R:
- case HEVC_NAL_RASL_N:
- case HEVC_NAL_RASL_R:
- // Slice
- break;
- default:
- // Don't discard non-slice nal.
- return 0;
- }
-
- if (skip >= AVDISCARD_NONKEY)
- return 1;
-
- slice = (H265RawSliceHeader *)unit->content;
- if (!slice) {
- av_log(ctx->log_ctx, AV_LOG_WARNING,
- "h265 slice header is null, missing decompose?\n");
- return 0;
- }
-
- if (skip >= AVDISCARD_NONINTRA && slice->slice_type != HEVC_SLICE_I)
- return 1;
- if (skip >= AVDISCARD_BIDIR && slice->slice_type == HEVC_SLICE_B)
- return 1;
-
- if (skip >= AVDISCARD_NONREF) {
- switch (unit->type) {
- case HEVC_NAL_TRAIL_N:
- case HEVC_NAL_TSA_N:
- case HEVC_NAL_STSA_N:
- case HEVC_NAL_RADL_N:
- case HEVC_NAL_RASL_N:
- case HEVC_NAL_VCL_N10:
- case HEVC_NAL_VCL_N12:
- case HEVC_NAL_VCL_N14:
- // non-ref
- return 1;
- default:
- break;
- }
- }
-
- return 0;
-}
-
-static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx,
- CodedBitstreamUnit *unit,
- PutBitContext *pbc)
-{
- int err;
-
- switch (unit->type) {
- case VVC_DCI_NUT:
- {
- H266RawDCI *dci = unit->content;
-
- err = cbs_h266_write_dci(ctx, pbc, dci);
- if (err < 0)
- return err;
- }
- break;
- case VVC_OPI_NUT:
- {
- H266RawOPI *opi = unit->content;
-
- err = cbs_h266_write_opi(ctx, pbc, opi);
- if (err < 0)
- return err;
- }
- break;
- case VVC_VPS_NUT:
- {
- H266RawVPS *vps = unit->content;
-
- err = cbs_h266_write_vps(ctx, pbc, vps);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_vps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
- case VVC_SPS_NUT:
- {
- H266RawSPS *sps = unit->content;
-
- err = cbs_h266_write_sps(ctx, pbc, sps);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_sps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_PPS_NUT:
- {
- H266RawPPS *pps = unit->content;
-
- err = cbs_h266_write_pps(ctx, pbc, pps);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_pps(ctx, unit);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_PREFIX_APS_NUT:
- case VVC_SUFFIX_APS_NUT:
- {
- err = cbs_h266_write_aps(ctx, pbc, unit->content,
- unit->type == VVC_PREFIX_APS_NUT);
- if (err < 0)
- return err;
- }
- break;
- case VVC_PH_NUT:
- {
- H266RawPH *ph = unit->content;
- err = cbs_h266_write_ph(ctx, pbc, ph);
- if (err < 0)
- return err;
-
- err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_TRAIL_NUT:
- case VVC_STSA_NUT:
- case VVC_RADL_NUT:
- case VVC_RASL_NUT:
- case VVC_IDR_W_RADL:
- case VVC_IDR_N_LP:
- case VVC_CRA_NUT:
- case VVC_GDR_NUT:
- {
- H266RawSlice *slice = unit->content;
-
- err = cbs_h266_write_slice_header(ctx, pbc, &slice->header);
- if (err < 0)
- return err;
-
- if (slice->header.sh_picture_header_in_slice_header_flag) {
- err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
- if (err < 0)
- return err;
- }
-
- if (slice->data) {
- err = cbs_h2645_write_slice_data(ctx, pbc, slice->data,
- slice->data_size,
- slice->data_bit_start);
- if (err < 0)
- return err;
- } else {
- // No slice data - that was just the header.
- }
- }
- break;
-
- case VVC_AUD_NUT:
- {
- err = cbs_h266_write_aud(ctx, pbc, unit->content);
- if (err < 0)
- return err;
- }
- break;
-
- case VVC_PREFIX_SEI_NUT:
- case VVC_SUFFIX_SEI_NUT:
- {
- err = cbs_h266_write_sei(ctx, pbc, unit->content,
- unit->type == VVC_PREFIX_SEI_NUT);
-
- if (err < 0)
- return err;
- }
- break;
-
- default:
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
- "NAL unit type %"PRIu32".\n", unit->type);
- return AVERROR_PATCHWELCOME;
- }
-
- return 0;
-}
-
-static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id,
+int ff_cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id,
CodedBitstreamUnitType type,
int nal_unit_index)
{
@@ -1832,7 +338,7 @@ static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id,
return 0;
}
-static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx,
+int ff_cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag)
{
uint8_t *data;
@@ -1866,7 +372,7 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx,
frag->data_bit_padding = unit->data_bit_padding;
}
- if (cbs_h2645_unit_requires_zero_byte(ctx->codec->codec_id, unit->type, i)) {
+ if (ff_cbs_h2645_unit_requires_zero_byte(ctx->codec->codec_id, unit->type, i)) {
// zero_byte
data[dp++] = 0;
}
@@ -1911,481 +417,3 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx,
return 0;
}
-
-static av_cold void cbs_h264_flush(CodedBitstreamContext *ctx)
-{
- CodedBitstreamH264Context *h264 = ctx->priv_data;
-
- for (int i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++)
- av_refstruct_unref(&h264->sps[i]);
- for (int i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++)
- av_refstruct_unref(&h264->pps[i]);
-
- h264->active_sps = NULL;
- h264->active_pps = NULL;
- h264->last_slice_nal_unit_type = 0;
-}
-
-static av_cold void cbs_h264_close(CodedBitstreamContext *ctx)
-{
- CodedBitstreamH264Context *h264 = ctx->priv_data;
- int i;
-
- ff_h2645_packet_uninit(&h264->common.read_packet);
-
- for (i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++)
- av_refstruct_unref(&h264->sps[i]);
- for (i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++)
- av_refstruct_unref(&h264->pps[i]);
-}
-
-static av_cold void cbs_h265_flush(CodedBitstreamContext *ctx)
-{
- CodedBitstreamH265Context *h265 = ctx->priv_data;
-
- for (int i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++)
- av_refstruct_unref(&h265->vps[i]);
- for (int i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++)
- av_refstruct_unref(&h265->sps[i]);
- for (int i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++)
- av_refstruct_unref(&h265->pps[i]);
-
- h265->active_vps = NULL;
- h265->active_sps = NULL;
- h265->active_pps = NULL;
-}
-
-static av_cold void cbs_h265_close(CodedBitstreamContext *ctx)
-{
- CodedBitstreamH265Context *h265 = ctx->priv_data;
- int i;
-
- ff_h2645_packet_uninit(&h265->common.read_packet);
-
- for (i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++)
- av_refstruct_unref(&h265->vps[i]);
- for (i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++)
- av_refstruct_unref(&h265->sps[i]);
- for (i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++)
- av_refstruct_unref(&h265->pps[i]);
-}
-
-static av_cold void cbs_h266_flush(CodedBitstreamContext *ctx)
-{
- CodedBitstreamH266Context *h266 = ctx->priv_data;
-
- for (int i = 0; i < FF_ARRAY_ELEMS(h266->vps); i++)
- av_refstruct_unref(&h266->vps[i]);
- for (int i = 0; i < FF_ARRAY_ELEMS(h266->sps); i++)
- av_refstruct_unref(&h266->sps[i]);
- for (int i = 0; i < FF_ARRAY_ELEMS(h266->pps); i++)
- av_refstruct_unref(&h266->pps[i]);
- av_refstruct_unref(&h266->ph_ref);
-}
-
-static av_cold void cbs_h266_close(CodedBitstreamContext *ctx)
-{
- CodedBitstreamH266Context *h266 = ctx->priv_data;
-
- cbs_h266_flush(ctx);
- ff_h2645_packet_uninit(&h266->common.read_packet);
- }
-
-static void cbs_h264_free_sei(AVRefStructOpaque unused, void *content)
-{
- H264RawSEI *sei = content;
- ff_cbs_sei_free_message_list(&sei->message_list);
-}
-
-static CodedBitstreamUnitTypeDescriptor cbs_h264_unit_types[] = {
- CBS_UNIT_TYPE_POD(H264_NAL_SPS, H264RawSPS),
- CBS_UNIT_TYPE_POD(H264_NAL_SPS_EXT, H264RawSPSExtension),
-
- CBS_UNIT_TYPE_INTERNAL_REF(H264_NAL_PPS, H264RawPPS, slice_group_id),
-
- CBS_UNIT_TYPES_INTERNAL_REF((H264_NAL_IDR_SLICE,
- H264_NAL_SLICE,
- H264_NAL_AUXILIARY_SLICE), H264RawSlice, data),
-
- CBS_UNIT_TYPE_POD(H264_NAL_AUD, H264RawAUD),
- CBS_UNIT_TYPE_POD(H264_NAL_FILLER_DATA, H264RawFiller),
- CBS_UNIT_TYPE_POD(H264_NAL_END_SEQUENCE, H264RawNALUnitHeader),
- CBS_UNIT_TYPE_POD(H264_NAL_END_STREAM, H264RawNALUnitHeader),
-
- CBS_UNIT_TYPE_COMPLEX(H264_NAL_SEI, H264RawSEI, &cbs_h264_free_sei),
-
- CBS_UNIT_TYPE_END_OF_LIST
-};
-
-static void cbs_h265_free_sei(AVRefStructOpaque unused, void *content)
-{
- H265RawSEI *sei = content;
- ff_cbs_sei_free_message_list(&sei->message_list);
-}
-
-static CodedBitstreamUnitTypeDescriptor cbs_h265_unit_types[] = {
- CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_VPS, H265RawVPS, extension_data.data),
- CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_SPS, H265RawSPS, extension_data.data),
- CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_PPS, H265RawPPS, extension_data.data),
-
- CBS_UNIT_TYPE_POD(HEVC_NAL_AUD, H265RawAUD),
- CBS_UNIT_TYPE_POD(HEVC_NAL_FD_NUT, H265RawFiller),
-
- // Slices of non-IRAP pictures.
- CBS_UNIT_RANGE_INTERNAL_REF(HEVC_NAL_TRAIL_N, HEVC_NAL_RASL_R,
- H265RawSlice, data),
- // Slices of IRAP pictures.
- CBS_UNIT_RANGE_INTERNAL_REF(HEVC_NAL_BLA_W_LP, HEVC_NAL_CRA_NUT,
- H265RawSlice, data),
-
- CBS_UNIT_TYPES_COMPLEX((HEVC_NAL_SEI_PREFIX, HEVC_NAL_SEI_SUFFIX),
- H265RawSEI, cbs_h265_free_sei),
-
- CBS_UNIT_TYPE_END_OF_LIST
-};
-
-static void cbs_h266_free_slice(AVRefStructOpaque unused, void *content)
-{
- H266RawSlice *slice = content;
- av_buffer_unref(&slice->data_ref);
- av_refstruct_unref(&slice->sps);
- av_refstruct_unref(&slice->pps);
- av_refstruct_unref(&slice->ph_ref);
-}
-
-
-static void cbs_h266_free_sei(AVRefStructOpaque unused, void *content)
-{
- H266RawSEI *sei = content;
- ff_cbs_sei_free_message_list(&sei->message_list);
-}
-
-static CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = {
- CBS_UNIT_TYPE_INTERNAL_REF(VVC_DCI_NUT, H266RawDCI, extension_data.data),
- CBS_UNIT_TYPE_INTERNAL_REF(VVC_OPI_NUT, H266RawOPI, extension_data.data),
- CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data),
- {
- .nb_unit_types = 1,
- .unit_type.list[0] = VVC_SPS_NUT,
- .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS,
- .content_size = sizeof(H266RawSPS),
- .type.ref = {
- .nb_offsets = 2,
- .offsets = { offsetof(H266RawSPS, extension_data.data),
- offsetof(H266RawSPS, vui.extension_data.data) }
- },
- },
- CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data),
- CBS_UNIT_TYPE_INTERNAL_REF(VVC_PREFIX_APS_NUT, H266RawAPS, extension_data.data),
- CBS_UNIT_TYPE_INTERNAL_REF(VVC_SUFFIX_APS_NUT, H266RawAPS, extension_data.data),
-
- CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH),
- CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD),
-
- CBS_UNIT_TYPES_COMPLEX((VVC_TRAIL_NUT, VVC_STSA_NUT, VVC_RADL_NUT),
- H266RawSlice, cbs_h266_free_slice),
- CBS_UNIT_TYPES_COMPLEX((VVC_RASL_NUT, VVC_IDR_W_RADL, VVC_IDR_N_LP),
- H266RawSlice, cbs_h266_free_slice),
- CBS_UNIT_TYPES_COMPLEX((VVC_CRA_NUT, VVC_GDR_NUT),
- H266RawSlice, cbs_h266_free_slice),
-
- CBS_UNIT_TYPES_COMPLEX((VVC_PREFIX_SEI_NUT, VVC_SUFFIX_SEI_NUT),
- H266RawSEI, cbs_h266_free_sei),
-
- CBS_UNIT_TYPE_END_OF_LIST
-};
-
-const CodedBitstreamType ff_cbs_type_h264 = {
- .codec_id = AV_CODEC_ID_H264,
-
- .priv_data_size = sizeof(CodedBitstreamH264Context),
-
- .unit_types = cbs_h264_unit_types,
-
- .split_fragment = &cbs_h2645_split_fragment,
- .read_unit = &cbs_h264_read_nal_unit,
- .write_unit = &cbs_h264_write_nal_unit,
- .discarded_unit = &cbs_h264_discarded_nal_unit,
- .assemble_fragment = &cbs_h2645_assemble_fragment,
-
- .flush = &cbs_h264_flush,
- .close = &cbs_h264_close,
-};
-
-const CodedBitstreamType ff_cbs_type_h265 = {
- .codec_id = AV_CODEC_ID_HEVC,
-
- .priv_data_size = sizeof(CodedBitstreamH265Context),
-
- .unit_types = cbs_h265_unit_types,
-
- .split_fragment = &cbs_h2645_split_fragment,
- .read_unit = &cbs_h265_read_nal_unit,
- .write_unit = &cbs_h265_write_nal_unit,
- .discarded_unit = &cbs_h265_discarded_nal_unit,
- .assemble_fragment = &cbs_h2645_assemble_fragment,
-
- .flush = &cbs_h265_flush,
- .close = &cbs_h265_close,
-};
-
-const CodedBitstreamType ff_cbs_type_h266 = {
- .codec_id = AV_CODEC_ID_VVC,
-
- .priv_data_size = sizeof(CodedBitstreamH266Context),
-
- .unit_types = cbs_h266_unit_types,
-
- .split_fragment = &cbs_h2645_split_fragment,
- .read_unit = &cbs_h266_read_nal_unit,
- .write_unit = &cbs_h266_write_nal_unit,
- .assemble_fragment = &cbs_h2645_assemble_fragment,
-
- .flush = &cbs_h266_flush,
- .close = &cbs_h266_close,
-};
-
-// Macro for the read/write pair.
-#define SEI_MESSAGE_RW(codec, name) \
- .read = cbs_ ## codec ## _read_ ## name ## _internal, \
- .write = cbs_ ## codec ## _write_ ## name ## _internal
-
-static const SEIMessageTypeDescriptor cbs_sei_common_types[] = {
- {
- SEI_TYPE_FILLER_PAYLOAD,
- 1, 1,
- sizeof(SEIRawFillerPayload),
- SEI_MESSAGE_RW(sei, filler_payload),
- },
- {
- SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
- 1, 1,
- sizeof(SEIRawUserDataRegistered),
- SEI_MESSAGE_RW(sei, user_data_registered),
- },
- {
- SEI_TYPE_USER_DATA_UNREGISTERED,
- 1, 1,
- sizeof(SEIRawUserDataUnregistered),
- SEI_MESSAGE_RW(sei, user_data_unregistered),
- },
- {
- SEI_TYPE_FRAME_PACKING_ARRANGEMENT,
- 1, 0,
- sizeof(SEIRawFramePackingArrangement),
- SEI_MESSAGE_RW(sei, frame_packing_arrangement),
- },
- {
- SEI_TYPE_DECODED_PICTURE_HASH,
- 0, 1,
- sizeof(SEIRawDecodedPictureHash),
- SEI_MESSAGE_RW(sei, decoded_picture_hash),
- },
- {
- SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME,
- 1, 0,
- sizeof(SEIRawMasteringDisplayColourVolume),
- SEI_MESSAGE_RW(sei, mastering_display_colour_volume),
- },
- {
- SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
- 1, 0,
- sizeof(SEIRawContentLightLevelInfo),
- SEI_MESSAGE_RW(sei, content_light_level_info),
- },
- {
- SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS,
- 1, 0,
- sizeof(SEIRawAlternativeTransferCharacteristics),
- SEI_MESSAGE_RW(sei, alternative_transfer_characteristics),
- },
- {
- SEI_TYPE_AMBIENT_VIEWING_ENVIRONMENT,
- 1, 0,
- sizeof(SEIRawAmbientViewingEnvironment),
- SEI_MESSAGE_RW(sei, ambient_viewing_environment),
- },
- SEI_MESSAGE_TYPE_END,
-};
-
-static const SEIMessageTypeDescriptor cbs_sei_h264_types[] = {
- {
- SEI_TYPE_BUFFERING_PERIOD,
- 1, 0,
- sizeof(H264RawSEIBufferingPeriod),
- SEI_MESSAGE_RW(h264, sei_buffering_period),
- },
- {
- SEI_TYPE_PIC_TIMING,
- 1, 0,
- sizeof(H264RawSEIPicTiming),
- SEI_MESSAGE_RW(h264, sei_pic_timing),
- },
- {
- SEI_TYPE_PAN_SCAN_RECT,
- 1, 0,
- sizeof(H264RawSEIPanScanRect),
- SEI_MESSAGE_RW(h264, sei_pan_scan_rect),
- },
- {
- SEI_TYPE_RECOVERY_POINT,
- 1, 0,
- sizeof(H264RawSEIRecoveryPoint),
- SEI_MESSAGE_RW(h264, sei_recovery_point),
- },
- {
- SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
- 1, 0,
- sizeof(H264RawFilmGrainCharacteristics),
- SEI_MESSAGE_RW(h264, film_grain_characteristics),
- },
- {
- SEI_TYPE_FRAME_PACKING_ARRANGEMENT,
- 1, 0,
- sizeof(H264RawSEIFramePackingArrangement),
- SEI_MESSAGE_RW(h264, sei_frame_packing_arrangement),
- },
- {
- SEI_TYPE_DISPLAY_ORIENTATION,
- 1, 0,
- sizeof(H264RawSEIDisplayOrientation),
- SEI_MESSAGE_RW(h264, sei_display_orientation),
- },
- SEI_MESSAGE_TYPE_END
-};
-
-static const SEIMessageTypeDescriptor cbs_sei_h265_types[] = {
- {
- SEI_TYPE_BUFFERING_PERIOD,
- 1, 0,
- sizeof(H265RawSEIBufferingPeriod),
- SEI_MESSAGE_RW(h265, sei_buffering_period),
- },
- {
- SEI_TYPE_PIC_TIMING,
- 1, 0,
- sizeof(H265RawSEIPicTiming),
- SEI_MESSAGE_RW(h265, sei_pic_timing),
- },
- {
- SEI_TYPE_PAN_SCAN_RECT,
- 1, 0,
- sizeof(H265RawSEIPanScanRect),
- SEI_MESSAGE_RW(h265, sei_pan_scan_rect),
- },
- {
- SEI_TYPE_RECOVERY_POINT,
- 1, 0,
- sizeof(H265RawSEIRecoveryPoint),
- SEI_MESSAGE_RW(h265, sei_recovery_point),
- },
- {
- SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
- 1, 0,
- sizeof(H265RawFilmGrainCharacteristics),
- SEI_MESSAGE_RW(h265, film_grain_characteristics),
- },
- {
- SEI_TYPE_DISPLAY_ORIENTATION,
- 1, 0,
- sizeof(H265RawSEIDisplayOrientation),
- SEI_MESSAGE_RW(h265, sei_display_orientation),
- },
- {
- SEI_TYPE_ACTIVE_PARAMETER_SETS,
- 1, 0,
- sizeof(H265RawSEIActiveParameterSets),
- SEI_MESSAGE_RW(h265, sei_active_parameter_sets),
- },
- {
- SEI_TYPE_DECODED_PICTURE_HASH,
- 0, 1,
- sizeof(H265RawSEIDecodedPictureHash),
- SEI_MESSAGE_RW(h265, sei_decoded_picture_hash),
- },
- {
- SEI_TYPE_TIME_CODE,
- 1, 0,
- sizeof(H265RawSEITimeCode),
- SEI_MESSAGE_RW(h265, sei_time_code),
- },
- {
- SEI_TYPE_ALPHA_CHANNEL_INFO,
- 1, 0,
- sizeof(H265RawSEIAlphaChannelInfo),
- SEI_MESSAGE_RW(h265, sei_alpha_channel_info),
- },
- {
- SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO,
- 1, 0,
- sizeof(H265RawSEI3DReferenceDisplaysInfo),
- SEI_MESSAGE_RW(h265, sei_3d_reference_displays_info),
- },
- SEI_MESSAGE_TYPE_END
-};
-
-static const SEIMessageTypeDescriptor cbs_sei_h266_types[] = {
- SEI_MESSAGE_TYPE_END
-};
-
-static const SEIMessageTypeDescriptor cbs_sei_h274_types[] = {
- {
- SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
- 1, 0,
- sizeof(SEIRawFilmGrainCharacteristics),
- SEI_MESSAGE_RW(sei, film_grain_characteristics),
- },
- {
- SEI_TYPE_DISPLAY_ORIENTATION,
- 1, 0,
- sizeof(SEIRawDisplayOrientation),
- SEI_MESSAGE_RW(sei, display_orientation)
- },
- {
- SEI_TYPE_FRAME_FIELD_INFO,
- 1, 0,
- sizeof(SEIRawFrameFieldInformation),
- SEI_MESSAGE_RW(sei, frame_field_information)
- },
- SEI_MESSAGE_TYPE_END,
-};
-
-const SEIMessageTypeDescriptor *ff_cbs_sei_find_type(CodedBitstreamContext *ctx,
- int payload_type)
-{
- const SEIMessageTypeDescriptor *codec_list;
- int i;
-
- switch (ctx->codec->codec_id) {
- case AV_CODEC_ID_H264:
- codec_list = cbs_sei_h264_types;
- break;
- case AV_CODEC_ID_H265:
- codec_list = cbs_sei_h265_types;
- break;
- case AV_CODEC_ID_H266:
- codec_list = cbs_sei_h266_types;
- break;
- default:
- return NULL;
- }
-
- for (i = 0; codec_list[i].type >= 0; i++) {
- if (codec_list[i].type == payload_type)
- return &codec_list[i];
- }
-
- if (ctx->codec->codec_id == AV_CODEC_ID_H266) {
- for (i = 0; cbs_sei_h274_types[i].type >= 0; i++) {
- if (cbs_sei_h274_types[i].type == payload_type)
- return &cbs_sei_h274_types[i];
- }
- }
-
- for (i = 0; cbs_sei_common_types[i].type >= 0; i++) {
- if (cbs_sei_common_types[i].type == payload_type)
- return &cbs_sei_common_types[i];
- }
-
- return NULL;
-}
diff --git a/libavcodec/cbs_h2645.h b/libavcodec/cbs_h2645.h
index f4c987a511..2d117ae3e7 100644
--- a/libavcodec/cbs_h2645.h
+++ b/libavcodec/cbs_h2645.h
@@ -19,6 +19,7 @@
#ifndef AVCODEC_CBS_H2645_H
#define AVCODEC_CBS_H2645_H
+#include "cbs.h"
#include "h2645_parse.h"
@@ -32,5 +33,48 @@ typedef struct CodedBitstreamH2645Context {
H2645Packet read_packet;
} CodedBitstreamH2645Context;
+struct GetBitContext;
+struct PutBitContext;
+
+int ff_cbs_read_ue_golomb(CodedBitstreamContext *ctx, struct GetBitContext *gbc,
+ const char *name, const int *subscripts,
+ uint32_t *write_to,
+ uint32_t range_min, uint32_t range_max);
+int ff_cbs_read_se_golomb(CodedBitstreamContext *ctx, struct GetBitContext *gbc,
+ const char *name, const int *subscripts,
+ int32_t *write_to,
+ int32_t range_min, int32_t range_max);
+int ff_cbs_write_ue_golomb(CodedBitstreamContext *ctx, struct PutBitContext *pbc,
+ const char *name, const int *subscripts,
+ uint32_t value,
+ uint32_t range_min, uint32_t range_max);
+int ff_cbs_write_se_golomb(CodedBitstreamContext *ctx, struct PutBitContext *pbc,
+ const char *name, const int *subscripts,
+ int32_t value,
+ int32_t range_min, int32_t range_max);
+
+int ff_cbs_h2645_read_more_rbsp_data(struct GetBitContext *gbc);
+
+int ff_cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *frag,
+ const H2645Packet *packet);
+
+int ff_cbs_h2645_write_slice_data(CodedBitstreamContext *ctx,
+ struct PutBitContext *pbc, const uint8_t *data,
+ size_t data_size, int data_bit_start);
+
+int ff_cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id,
+ CodedBitstreamUnitType type,
+ int nal_unit_index);
+
+int ff_cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *frag);
+
+/**
+ * payload_extension_present() - true if we are before the last 1-bit
+ * in the payload structure, which must be in the last byte.
+ */
+int ff_cbs_h2645_payload_extension_present(struct GetBitContext *gbc, uint32_t payload_size,
+ int cur_pos);
#endif /* AVCODEC_CBS_H2645_H */
diff --git a/libavcodec/cbs_h265.c b/libavcodec/cbs_h265.c
new file mode 100644
index 0000000000..21df609d08
--- /dev/null
+++ b/libavcodec/cbs_h265.c
@@ -0,0 +1,828 @@
+/*
+ * 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/mem.h"
+#include "libavutil/refstruct.h"
+#include "bytestream.h"
+#include "cbs.h"
+#include "cbs_internal.h"
+#include "cbs_h2645.h"
+#include "cbs_h265.h"
+#include "cbs_sei.h"
+#include "get_bits.h"
+
+#define HEADER(name) do { \
+ ff_cbs_trace_header(ctx, name); \
+ } while (0)
+
+#define CHECK(call) do { \
+ err = (call); \
+ if (err < 0) \
+ return err; \
+ } while (0)
+
+#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
+#define FUNC_H265(name) FUNC_NAME1(READWRITE, h265, name)
+#define FUNC_NAME2_EXPORT(rw, codec, name) ff_cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1_EXPORT(rw, codec, name) FUNC_NAME2_EXPORT(rw, codec, name)
+#define FUNC_SEI(name) FUNC_NAME1_EXPORT(READWRITE, sei, name)
+
+#define SEI_FUNC(name, args) \
+static int FUNC_H265(name) args; \
+static int FUNC_H265(name ## _internal)(CodedBitstreamContext *ctx, \
+ RWContext *rw, void *cur, \
+ SEIMessageState *state) \
+{ \
+ return FUNC_H265(name)(ctx, rw, cur, state); \
+} \
+static int FUNC_H265(name) args
+
+#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
+
+#define u(width, name, range_min, range_max) \
+ xu(width, name, current->name, range_min, range_max, 0, )
+#define flag(name) ub(1, name)
+#define ue(name, range_min, range_max) \
+ xue(name, current->name, range_min, range_max, 0, )
+#define i(width, name, range_min, range_max) \
+ xi(width, name, current->name, range_min, range_max, 0, )
+#define ib(width, name) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
+#define se(name, range_min, range_max) \
+ xse(name, current->name, range_min, range_max, 0, )
+
+#define us(width, name, range_min, range_max, subs, ...) \
+ xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ubs(width, name, subs, ...) \
+ xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
+#define flags(name, subs, ...) \
+ xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
+#define ues(name, range_min, range_max, subs, ...) \
+ xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define is(width, name, range_min, range_max, subs, ...) \
+ xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ibs(width, name, subs, ...) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
+#define ses(name, range_min, range_max, subs, ...) \
+ xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+
+#define fixed(width, name, value) do { \
+ av_unused uint32_t fixed_value = value; \
+ xu(width, name, fixed_value, value, value, 0, ); \
+ } while (0)
+
+
+#define READ
+#define READWRITE read
+#define RWContext GetBitContext
+
+#define ub(width, name) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
+ &value)); \
+ current->name = value; \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+
+
+#define infer(name, value) do { \
+ current->name = value; \
+ } while (0)
+
+#define more_rbsp_data(var) ((var) = ff_cbs_h2645_read_more_rbsp_data(rw))
+
+#define bit_position(rw) (get_bits_count(rw))
+#define byte_alignment(rw) (get_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ name ## _ref = av_buffer_allocz(size + \
+ AV_INPUT_BUFFER_PADDING_SIZE); \
+ if (!name ## _ref) \
+ return AVERROR(ENOMEM); \
+ name = name ## _ref->data; \
+ } while (0)
+
+#define FUNC(name) FUNC_H265(name)
+#include "cbs_h265_syntax_template.c"
+#undef FUNC
+
+
+#undef READ
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+#undef allocate_struct
+
+
+#define WRITE
+#define READWRITE write
+#define RWContext PutBitContext
+
+#define ub(width, name) do { \
+ uint32_t value = current->name; \
+ CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
+ value)); \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+
+#define infer(name, value) do { \
+ if (current->name != (value)) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, \
+ "%s does not match inferred value: " \
+ "%"PRId64", but should be %"PRId64".\n", \
+ #name, (int64_t)current->name, (int64_t)(value)); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define more_rbsp_data(var) (var)
+
+#define bit_position(rw) (put_bits_count(rw))
+#define byte_alignment(rw) (put_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ if (!name) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
+ "for writing.\n", #name); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define FUNC(name) FUNC_H265(name)
+#include "cbs_h265_syntax_template.c"
+#undef FUNC
+
+#undef WRITE
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef u
+#undef i
+#undef flag
+#undef ue
+#undef se
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+
+
+
+static int cbs_h265_split_fragment(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *frag,
+ int header)
+{
+ enum AVCodecID codec_id = ctx->codec->codec_id;
+ CodedBitstreamH265Context *priv = ctx->priv_data;
+ CodedBitstreamH2645Context *h2645 = &priv->common;
+ GetByteContext gbc;
+ int err;
+
+ av_assert0(frag->data && frag->nb_units == 0);
+ if (frag->data_size == 0)
+ return 0;
+
+ if (header && frag->data[0]) {
+ // HVCC header.
+ size_t size, start, end;
+ int i, j, nb_arrays, nal_unit_type, nb_nals, version;
+
+ h2645->mp4 = 1;
+
+ bytestream2_init(&gbc, frag->data, frag->data_size);
+
+ if (bytestream2_get_bytes_left(&gbc) < 23)
+ return AVERROR_INVALIDDATA;
+
+ version = bytestream2_get_byte(&gbc);
+ if (version != 1) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid HVCC header: "
+ "first byte %u.\n", version);
+ return AVERROR_INVALIDDATA;
+ }
+
+ bytestream2_skip(&gbc, 20);
+ h2645->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1;
+
+ nb_arrays = bytestream2_get_byte(&gbc);
+ for (i = 0; i < nb_arrays; i++) {
+ nal_unit_type = bytestream2_get_byte(&gbc) & 0x3f;
+ nb_nals = bytestream2_get_be16(&gbc);
+
+ start = bytestream2_tell(&gbc);
+ for (j = 0; j < nb_nals; j++) {
+ if (bytestream2_get_bytes_left(&gbc) < 2)
+ return AVERROR_INVALIDDATA;
+ size = bytestream2_get_be16(&gbc);
+ if (bytestream2_get_bytes_left(&gbc) < size)
+ return AVERROR_INVALIDDATA;
+ bytestream2_skip(&gbc, size);
+ }
+ end = bytestream2_tell(&gbc);
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data + start, end - start,
+ ctx->log_ctx, 2, AV_CODEC_ID_HEVC,
+ H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
+ if (err < 0) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split "
+ "HVCC array %d (%d NAL units of type %d).\n",
+ i, nb_nals, nal_unit_type);
+ return err;
+ }
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+ }
+ } else {
+ int flags = (H2645_FLAG_IS_NALFF * !!h2645->mp4) | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF;
+ // Annex B, or later MP4 with already-known parameters.
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data, frag->data_size,
+ ctx->log_ctx,
+ h2645->nal_length_size,
+ codec_id, flags);
+ if (err < 0)
+ return err;
+
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+#define cbs_h2645_replace_ps(ps_name, ps_var, id_element) \
+static int cbs_h265_replace_ ## ps_var(CodedBitstreamContext *ctx, \
+ CodedBitstreamUnit *unit) \
+{ \
+ CodedBitstreamH265Context *priv = ctx->priv_data; \
+ H265Raw## ps_name *ps_var = unit->content; \
+ unsigned int id = ps_var->id_element; \
+ int err = ff_cbs_make_unit_refcounted(ctx, unit); \
+ if (err < 0) \
+ return err; \
+ if (priv->ps_var[id] == priv->active_ ## ps_var) \
+ priv->active_ ## ps_var = NULL ; \
+ av_assert0(unit->content_ref); \
+ av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
+ return 0; \
+}
+
+cbs_h2645_replace_ps(VPS, vps, vps_video_parameter_set_id)
+cbs_h2645_replace_ps(SPS, sps, sps_seq_parameter_set_id)
+cbs_h2645_replace_ps(PPS, pps, pps_pic_parameter_set_id)
+
+static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit)
+{
+ GetBitContext gbc;
+ int err;
+
+ err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
+ if (err < 0)
+ return err;
+
+ err = ff_cbs_alloc_unit_content(ctx, unit);
+ if (err < 0)
+ return err;
+
+ switch (unit->type) {
+ case HEVC_NAL_VPS:
+ {
+ H265RawVPS *vps = unit->content;
+
+ err = cbs_h265_read_vps(ctx, &gbc, vps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h265_replace_vps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+ case HEVC_NAL_SPS:
+ {
+ H265RawSPS *sps = unit->content;
+
+ err = cbs_h265_read_sps(ctx, &gbc, sps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h265_replace_sps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_PPS:
+ {
+ H265RawPPS *pps = unit->content;
+
+ err = cbs_h265_read_pps(ctx, &gbc, pps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h265_replace_pps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_TRAIL_N:
+ case HEVC_NAL_TRAIL_R:
+ case HEVC_NAL_TSA_N:
+ case HEVC_NAL_TSA_R:
+ case HEVC_NAL_STSA_N:
+ case HEVC_NAL_STSA_R:
+ case HEVC_NAL_RADL_N:
+ case HEVC_NAL_RADL_R:
+ case HEVC_NAL_RASL_N:
+ case HEVC_NAL_RASL_R:
+ case HEVC_NAL_BLA_W_LP:
+ case HEVC_NAL_BLA_W_RADL:
+ case HEVC_NAL_BLA_N_LP:
+ case HEVC_NAL_IDR_W_RADL:
+ case HEVC_NAL_IDR_N_LP:
+ case HEVC_NAL_CRA_NUT:
+ {
+ H265RawSlice *slice = unit->content;
+ int pos, len;
+
+ err = cbs_h265_read_slice_segment_header(ctx, &gbc, &slice->header);
+ if (err < 0)
+ return err;
+
+ if (!ff_cbs_h2645_read_more_rbsp_data(&gbc))
+ return AVERROR_INVALIDDATA;
+
+ pos = get_bits_count(&gbc);
+ len = unit->data_size;
+
+ slice->data_size = len - pos / 8;
+ slice->data_ref = av_buffer_ref(unit->data_ref);
+ if (!slice->data_ref)
+ return AVERROR(ENOMEM);
+ slice->data = unit->data + pos / 8;
+ slice->data_bit_start = pos % 8;
+ }
+ break;
+
+ case HEVC_NAL_AUD:
+ {
+ err = cbs_h265_read_aud(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_FD_NUT:
+ {
+ err = cbs_h265_read_filler(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_SEI_PREFIX:
+ case HEVC_NAL_SEI_SUFFIX:
+ {
+ err = cbs_h265_read_sei(ctx, &gbc, unit->content,
+ unit->type == HEVC_NAL_SEI_PREFIX);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ default:
+ return AVERROR(ENOSYS);
+ }
+
+ return 0;
+}
+
+static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit,
+ PutBitContext *pbc)
+{
+ int err;
+
+ switch (unit->type) {
+ case HEVC_NAL_VPS:
+ {
+ H265RawVPS *vps = unit->content;
+
+ err = cbs_h265_write_vps(ctx, pbc, vps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h265_replace_vps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_SPS:
+ {
+ H265RawSPS *sps = unit->content;
+
+ err = cbs_h265_write_sps(ctx, pbc, sps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h265_replace_sps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_PPS:
+ {
+ H265RawPPS *pps = unit->content;
+
+ err = cbs_h265_write_pps(ctx, pbc, pps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h265_replace_pps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_TRAIL_N:
+ case HEVC_NAL_TRAIL_R:
+ case HEVC_NAL_TSA_N:
+ case HEVC_NAL_TSA_R:
+ case HEVC_NAL_STSA_N:
+ case HEVC_NAL_STSA_R:
+ case HEVC_NAL_RADL_N:
+ case HEVC_NAL_RADL_R:
+ case HEVC_NAL_RASL_N:
+ case HEVC_NAL_RASL_R:
+ case HEVC_NAL_BLA_W_LP:
+ case HEVC_NAL_BLA_W_RADL:
+ case HEVC_NAL_BLA_N_LP:
+ case HEVC_NAL_IDR_W_RADL:
+ case HEVC_NAL_IDR_N_LP:
+ case HEVC_NAL_CRA_NUT:
+ {
+ H265RawSlice *slice = unit->content;
+
+ err = cbs_h265_write_slice_segment_header(ctx, pbc, &slice->header);
+ if (err < 0)
+ return err;
+
+ if (slice->data) {
+ err = ff_cbs_h2645_write_slice_data(ctx, pbc, slice->data,
+ slice->data_size,
+ slice->data_bit_start);
+ if (err < 0)
+ return err;
+ } else {
+ // No slice data - that was just the header.
+ }
+ }
+ break;
+
+ case HEVC_NAL_AUD:
+ {
+ err = cbs_h265_write_aud(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_FD_NUT:
+ {
+ err = cbs_h265_write_filler(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case HEVC_NAL_SEI_PREFIX:
+ case HEVC_NAL_SEI_SUFFIX:
+ {
+ err = cbs_h265_write_sei(ctx, pbc, unit->content,
+ unit->type == HEVC_NAL_SEI_PREFIX);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ default:
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
+ "NAL unit type %"PRIu32".\n", unit->type);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ return 0;
+}
+
+static int cbs_h265_discarded_nal_unit(CodedBitstreamContext *ctx,
+ const CodedBitstreamUnit *unit,
+ enum AVDiscard skip)
+{
+ H265RawSliceHeader *slice;
+
+ if (skip <= AVDISCARD_DEFAULT)
+ return 0;
+
+ switch (unit->type) {
+ case HEVC_NAL_BLA_W_LP:
+ case HEVC_NAL_BLA_W_RADL:
+ case HEVC_NAL_BLA_N_LP:
+ case HEVC_NAL_IDR_W_RADL:
+ case HEVC_NAL_IDR_N_LP:
+ case HEVC_NAL_CRA_NUT:
+ // IRAP slice
+ if (skip < AVDISCARD_ALL)
+ return 0;
+ break;
+
+ case HEVC_NAL_TRAIL_R:
+ case HEVC_NAL_TRAIL_N:
+ case HEVC_NAL_TSA_N:
+ case HEVC_NAL_TSA_R:
+ case HEVC_NAL_STSA_N:
+ case HEVC_NAL_STSA_R:
+ case HEVC_NAL_RADL_N:
+ case HEVC_NAL_RADL_R:
+ case HEVC_NAL_RASL_N:
+ case HEVC_NAL_RASL_R:
+ // Slice
+ break;
+ default:
+ // Don't discard non-slice nal.
+ return 0;
+ }
+
+ if (skip >= AVDISCARD_NONKEY)
+ return 1;
+
+ slice = (H265RawSliceHeader *)unit->content;
+ if (!slice) {
+ av_log(ctx->log_ctx, AV_LOG_WARNING,
+ "h265 slice header is null, missing decompose?\n");
+ return 0;
+ }
+
+ if (skip >= AVDISCARD_NONINTRA && slice->slice_type != HEVC_SLICE_I)
+ return 1;
+ if (skip >= AVDISCARD_BIDIR && slice->slice_type == HEVC_SLICE_B)
+ return 1;
+
+ if (skip >= AVDISCARD_NONREF) {
+ switch (unit->type) {
+ case HEVC_NAL_TRAIL_N:
+ case HEVC_NAL_TSA_N:
+ case HEVC_NAL_STSA_N:
+ case HEVC_NAL_RADL_N:
+ case HEVC_NAL_RASL_N:
+ case HEVC_NAL_VCL_N10:
+ case HEVC_NAL_VCL_N12:
+ case HEVC_NAL_VCL_N14:
+ // non-ref
+ return 1;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static av_cold void cbs_h265_flush(CodedBitstreamContext *ctx)
+{
+ CodedBitstreamH265Context *h265 = ctx->priv_data;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++)
+ av_refstruct_unref(&h265->vps[i]);
+ for (int i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++)
+ av_refstruct_unref(&h265->sps[i]);
+ for (int i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++)
+ av_refstruct_unref(&h265->pps[i]);
+
+ h265->active_vps = NULL;
+ h265->active_sps = NULL;
+ h265->active_pps = NULL;
+}
+
+static av_cold void cbs_h265_close(CodedBitstreamContext *ctx)
+{
+ CodedBitstreamH265Context *h265 = ctx->priv_data;
+ int i;
+
+ ff_h2645_packet_uninit(&h265->common.read_packet);
+
+ for (i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++)
+ av_refstruct_unref(&h265->vps[i]);
+ for (i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++)
+ av_refstruct_unref(&h265->sps[i]);
+ for (i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++)
+ av_refstruct_unref(&h265->pps[i]);
+}
+
+static void cbs_h265_free_sei(AVRefStructOpaque unused, void *content)
+{
+ H265RawSEI *sei = content;
+ ff_cbs_sei_free_message_list(&sei->message_list);
+}
+
+static CodedBitstreamUnitTypeDescriptor cbs_h265_unit_types[] = {
+ CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_VPS, H265RawVPS, extension_data.data),
+ CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_SPS, H265RawSPS, extension_data.data),
+ CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_PPS, H265RawPPS, extension_data.data),
+
+ CBS_UNIT_TYPE_POD(HEVC_NAL_AUD, H265RawAUD),
+ CBS_UNIT_TYPE_POD(HEVC_NAL_FD_NUT, H265RawFiller),
+
+ // Slices of non-IRAP pictures.
+ CBS_UNIT_RANGE_INTERNAL_REF(HEVC_NAL_TRAIL_N, HEVC_NAL_RASL_R,
+ H265RawSlice, data),
+ // Slices of IRAP pictures.
+ CBS_UNIT_RANGE_INTERNAL_REF(HEVC_NAL_BLA_W_LP, HEVC_NAL_CRA_NUT,
+ H265RawSlice, data),
+
+ CBS_UNIT_TYPES_COMPLEX((HEVC_NAL_SEI_PREFIX, HEVC_NAL_SEI_SUFFIX),
+ H265RawSEI, cbs_h265_free_sei),
+
+ CBS_UNIT_TYPE_END_OF_LIST
+};
+
+// Macro for the read/write pair.
+#define SEI_MESSAGE_RW(codec, name) \
+ .read = cbs_ ## codec ## _read_ ## name ## _internal, \
+ .write = cbs_ ## codec ## _write_ ## name ## _internal
+
+const SEIMessageTypeDescriptor ff_cbs_sei_h265_types[] = {
+ {
+ SEI_TYPE_BUFFERING_PERIOD,
+ 1, 0,
+ sizeof(H265RawSEIBufferingPeriod),
+ SEI_MESSAGE_RW(h265, sei_buffering_period),
+ },
+ {
+ SEI_TYPE_PIC_TIMING,
+ 1, 0,
+ sizeof(H265RawSEIPicTiming),
+ SEI_MESSAGE_RW(h265, sei_pic_timing),
+ },
+ {
+ SEI_TYPE_PAN_SCAN_RECT,
+ 1, 0,
+ sizeof(H265RawSEIPanScanRect),
+ SEI_MESSAGE_RW(h265, sei_pan_scan_rect),
+ },
+ {
+ SEI_TYPE_RECOVERY_POINT,
+ 1, 0,
+ sizeof(H265RawSEIRecoveryPoint),
+ SEI_MESSAGE_RW(h265, sei_recovery_point),
+ },
+ {
+ SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
+ 1, 0,
+ sizeof(H265RawFilmGrainCharacteristics),
+ SEI_MESSAGE_RW(h265, film_grain_characteristics),
+ },
+ {
+ SEI_TYPE_DISPLAY_ORIENTATION,
+ 1, 0,
+ sizeof(H265RawSEIDisplayOrientation),
+ SEI_MESSAGE_RW(h265, sei_display_orientation),
+ },
+ {
+ SEI_TYPE_ACTIVE_PARAMETER_SETS,
+ 1, 0,
+ sizeof(H265RawSEIActiveParameterSets),
+ SEI_MESSAGE_RW(h265, sei_active_parameter_sets),
+ },
+ {
+ SEI_TYPE_DECODED_PICTURE_HASH,
+ 0, 1,
+ sizeof(H265RawSEIDecodedPictureHash),
+ SEI_MESSAGE_RW(h265, sei_decoded_picture_hash),
+ },
+ {
+ SEI_TYPE_TIME_CODE,
+ 1, 0,
+ sizeof(H265RawSEITimeCode),
+ SEI_MESSAGE_RW(h265, sei_time_code),
+ },
+ {
+ SEI_TYPE_ALPHA_CHANNEL_INFO,
+ 1, 0,
+ sizeof(H265RawSEIAlphaChannelInfo),
+ SEI_MESSAGE_RW(h265, sei_alpha_channel_info),
+ },
+ {
+ SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO,
+ 1, 0,
+ sizeof(H265RawSEI3DReferenceDisplaysInfo),
+ SEI_MESSAGE_RW(h265, sei_3d_reference_displays_info),
+ },
+ SEI_MESSAGE_TYPE_END
+};
+
+const CodedBitstreamType ff_cbs_type_h265 = {
+ .codec_id = AV_CODEC_ID_HEVC,
+
+ .priv_data_size = sizeof(CodedBitstreamH265Context),
+
+ .unit_types = cbs_h265_unit_types,
+
+ .split_fragment = &cbs_h265_split_fragment,
+ .read_unit = &cbs_h265_read_nal_unit,
+ .write_unit = &cbs_h265_write_nal_unit,
+ .discarded_unit = &cbs_h265_discarded_nal_unit,
+ .assemble_fragment = &ff_cbs_h2645_assemble_fragment,
+
+ .flush = &cbs_h265_flush,
+ .close = &cbs_h265_close,
+};
diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c
index e976c38b8d..2842c40585 100644
--- a/libavcodec/cbs_h265_syntax_template.c
+++ b/libavcodec/cbs_h265_syntax_template.c
@@ -67,7 +67,7 @@ static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw,
GetBitContext start;
uint8_t bit;
start = *rw;
- for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++)
+ for (k = 0; ff_cbs_h2645_read_more_rbsp_data(rw); k++)
skip_bits(rw, 1);
current->bit_length = k;
if (k > 0) {
@@ -1915,7 +1915,7 @@ SEI_FUNC(sei_buffering_period, (CodedBitstreamContext *ctx, RWContext *rw,
#ifdef READ
end_pos = get_bits_count(rw);
- if (cbs_h265_payload_extension_present(rw, sei->payload_size,
+ if (ff_cbs_h2645_payload_extension_present(rw, sei->payload_size,
end_pos - start_pos))
flag(use_alt_cpb_params_flag);
else
diff --git a/libavcodec/cbs_h266.c b/libavcodec/cbs_h266.c
new file mode 100644
index 0000000000..8c92b4f557
--- /dev/null
+++ b/libavcodec/cbs_h266.c
@@ -0,0 +1,809 @@
+/*
+ * 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/intmath.h"
+#include "libavutil/mem.h"
+#include "libavutil/refstruct.h"
+#include "bytestream.h"
+#include "cbs.h"
+#include "cbs_internal.h"
+#include "cbs_h2645.h"
+#include "cbs_h266.h"
+#include "cbs_sei.h"
+#include "get_bits.h"
+
+#define HEADER(name) do { \
+ ff_cbs_trace_header(ctx, name); \
+ } while (0)
+
+#define CHECK(call) do { \
+ err = (call); \
+ if (err < 0) \
+ return err; \
+ } while (0)
+
+#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
+#define FUNC_H266(name) FUNC_NAME1(READWRITE, h266, name)
+#define FUNC_NAME2_EXPORT(rw, codec, name) ff_cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1_EXPORT(rw, codec, name) FUNC_NAME2_EXPORT(rw, codec, name)
+#define FUNC_SEI(name) FUNC_NAME1_EXPORT(READWRITE, sei, name)
+
+#define SEI_FUNC(name, args) \
+static int FUNC_H266(name) args; \
+static int FUNC_H266(name ## _internal)(CodedBitstreamContext *ctx, \
+ RWContext *rw, void *cur, \
+ SEIMessageState *state) \
+{ \
+ return FUNC_H266(name)(ctx, rw, cur, state); \
+} \
+static int FUNC_H266(name) args
+
+#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
+
+#define u(width, name, range_min, range_max) \
+ xu(width, name, current->name, range_min, range_max, 0, )
+#define flag(name) ub(1, name)
+#define ue(name, range_min, range_max) \
+ xue(name, current->name, range_min, range_max, 0, )
+#define i(width, name, range_min, range_max) \
+ xi(width, name, current->name, range_min, range_max, 0, )
+#define ib(width, name) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
+#define se(name, range_min, range_max) \
+ xse(name, current->name, range_min, range_max, 0, )
+
+#define us(width, name, range_min, range_max, subs, ...) \
+ xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ubs(width, name, subs, ...) \
+ xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
+#define flags(name, subs, ...) \
+ xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
+#define ues(name, range_min, range_max, subs, ...) \
+ xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define is(width, name, range_min, range_max, subs, ...) \
+ xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ibs(width, name, subs, ...) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
+#define ses(name, range_min, range_max, subs, ...) \
+ xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+
+#define fixed(width, name, value) do { \
+ av_unused uint32_t fixed_value = value; \
+ xu(width, name, fixed_value, value, value, 0, ); \
+ } while (0)
+
+
+#define READ
+#define READWRITE read
+#define RWContext GetBitContext
+
+#define ub(width, name) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
+ &value)); \
+ current->name = value; \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+
+
+#define infer(name, value) do { \
+ current->name = value; \
+ } while (0)
+
+#define more_rbsp_data(var) ((var) = ff_cbs_h2645_read_more_rbsp_data(rw))
+
+#define bit_position(rw) (get_bits_count(rw))
+#define byte_alignment(rw) (get_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ name ## _ref = av_buffer_allocz(size + \
+ AV_INPUT_BUFFER_PADDING_SIZE); \
+ if (!name ## _ref) \
+ return AVERROR(ENOMEM); \
+ name = name ## _ref->data; \
+ } while (0)
+
+#define FUNC(name) FUNC_H266(name)
+#include "cbs_h266_syntax_template.c"
+#undef FUNC
+
+
+#undef READ
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+#undef allocate_struct
+
+
+#define WRITE
+#define READWRITE write
+#define RWContext PutBitContext
+
+#define ub(width, name) do { \
+ uint32_t value = current->name; \
+ CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
+ value)); \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+
+#define infer(name, value) do { \
+ if (current->name != (value)) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, \
+ "%s does not match inferred value: " \
+ "%"PRId64", but should be %"PRId64".\n", \
+ #name, (int64_t)current->name, (int64_t)(value)); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define more_rbsp_data(var) (var)
+
+#define bit_position(rw) (put_bits_count(rw))
+#define byte_alignment(rw) (put_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ if (!name) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
+ "for writing.\n", #name); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define FUNC(name) FUNC_H266(name)
+#include "cbs_h266_syntax_template.c"
+#undef FUNC
+
+#undef WRITE
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef u
+#undef i
+#undef flag
+#undef ue
+#undef se
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+
+
+
+static int cbs_h266_split_fragment(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *frag,
+ int header)
+{
+ enum AVCodecID codec_id = ctx->codec->codec_id;
+ CodedBitstreamH266Context *priv = ctx->priv_data;
+ CodedBitstreamH2645Context *h2645 = &priv->common;
+ GetByteContext gbc;
+ int err;
+
+ av_assert0(frag->data && frag->nb_units == 0);
+ if (frag->data_size == 0)
+ return 0;
+
+ if(header && frag->data[0]) {
+ // VVCC header.
+ int ptl_present_flag, num_arrays;
+ int b, i, j;
+
+ h2645->mp4 = 1;
+
+ bytestream2_init(&gbc, frag->data, frag->data_size);
+
+ b = bytestream2_get_byte(&gbc);
+ h2645->nal_length_size = ((b >> 1) & 3) + 1;
+ ptl_present_flag = b & 1;
+
+ if(ptl_present_flag) {
+ int num_sublayers, num_bytes_constraint_info, num_sub_profiles;
+ num_sublayers = (bytestream2_get_be16u(&gbc) >> 4) & 7;
+ bytestream2_skip(&gbc, 1);
+
+ // begin VvcPTLRecord(num_sublayers);
+ num_bytes_constraint_info = bytestream2_get_byte(&gbc) & 0x3f;
+ bytestream2_skip(&gbc, 2 + num_bytes_constraint_info);
+ if(num_sublayers > 1) {
+ int count_present_flags = 0;
+ b = bytestream2_get_byte(&gbc);
+ for(i = num_sublayers - 2; i >= 0; i--) {
+ if((b >> (7 - (num_sublayers - 2 - i))) & 0x01)
+ count_present_flags++;
+ }
+ bytestream2_skip(&gbc, count_present_flags);
+ }
+ num_sub_profiles = bytestream2_get_byte(&gbc);
+ bytestream2_skip(&gbc, num_sub_profiles * 4);
+ // end VvcPTLRecord(num_sublayers);
+
+ bytestream2_skip(&gbc, 3 * 2);
+ }
+
+ num_arrays = bytestream2_get_byte(&gbc);
+ for(j = 0; j < num_arrays; j++) {
+ size_t start, end, size;
+ int nal_unit_type = bytestream2_get_byte(&gbc) & 0x1f;
+ unsigned int num_nalus = 1;
+ if(nal_unit_type != VVC_DCI_NUT && nal_unit_type != VVC_OPI_NUT)
+ num_nalus = bytestream2_get_be16(&gbc);
+
+ start = bytestream2_tell(&gbc);
+ for(i = 0; i < num_nalus; i++) {
+ if (bytestream2_get_bytes_left(&gbc) < 2)
+ return AVERROR_INVALIDDATA;
+ size = bytestream2_get_be16(&gbc);
+ if (bytestream2_get_bytes_left(&gbc) < size)
+ return AVERROR_INVALIDDATA;
+ bytestream2_skip(&gbc, size);
+ }
+ end = bytestream2_tell(&gbc);
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data + start, end - start,
+ ctx->log_ctx, 2, AV_CODEC_ID_VVC,
+ H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
+ if (err < 0) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split "
+ "VVCC array %d (%d NAL units of type %d).\n",
+ i, num_nalus, nal_unit_type);
+ return err;
+ }
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+ }
+ } else {
+ int flags = (H2645_FLAG_IS_NALFF * !!h2645->mp4) | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF;
+ // Annex B, or later MP4 with already-known parameters.
+
+ err = ff_h2645_packet_split(&h2645->read_packet,
+ frag->data, frag->data_size,
+ ctx->log_ctx,
+ h2645->nal_length_size,
+ codec_id, flags);
+ if (err < 0)
+ return err;
+
+ err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+#define cbs_h266_replace_ps(ps_name, ps_var, id_element) \
+static int cbs_h266_replace_ ## ps_var(CodedBitstreamContext *ctx, \
+ CodedBitstreamUnit *unit) \
+{ \
+ CodedBitstreamH266Context *priv = ctx->priv_data; \
+ H266Raw ## ps_name *ps_var = unit->content; \
+ unsigned int id = ps_var->id_element; \
+ int err = ff_cbs_make_unit_refcounted(ctx, unit); \
+ if (err < 0) \
+ return err; \
+ av_assert0(unit->content_ref); \
+ av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
+ return 0; \
+}
+
+cbs_h266_replace_ps(VPS, vps, vps_video_parameter_set_id)
+cbs_h266_replace_ps(PPS, pps, pps_pic_parameter_set_id)
+
+static int cbs_h266_replace_sps(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit)
+{
+ CodedBitstreamH266Context *priv = ctx->priv_data;
+ H266RawSPS *sps = unit->content;
+ unsigned int id = sps->sps_seq_parameter_set_id;
+ int err = ff_cbs_make_unit_refcounted(ctx, unit);
+ if (err < 0)
+ return err;
+ av_assert0(unit->content_ref);
+ if (priv->sps[id] && memcmp(priv->sps[id], unit->content_ref, sizeof(*priv->sps[id]))) {
+ for (unsigned int i = 0; i < VVC_MAX_PPS_COUNT; i++) {
+ if (priv->pps[i] && priv->pps[i]->pps_seq_parameter_set_id == id)
+ av_refstruct_unref(&priv->pps[i]);
+ }
+ }
+ av_refstruct_replace(&priv->sps[id], unit->content_ref);
+ return 0;
+}
+
+static int cbs_h266_replace_ph(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit,
+ H266RawPictureHeader *ph)
+{
+ CodedBitstreamH266Context *h266 = ctx->priv_data;
+ int err;
+
+ err = ff_cbs_make_unit_refcounted(ctx, unit);
+ if (err < 0)
+ return err;
+ av_assert0(unit->content_ref);
+ av_refstruct_replace(&h266->ph_ref, unit->content_ref);
+ h266->ph = ph;
+ return 0;
+}
+
+static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit)
+{
+ GetBitContext gbc;
+ int err;
+ CodedBitstreamH266Context *h266 = ctx->priv_data;
+
+ err = init_get_bits8(&gbc, unit->data, unit->data_size);
+ if (err < 0)
+ return err;
+
+ err = ff_cbs_alloc_unit_content(ctx, unit);
+ if (err < 0)
+ return err;
+
+ switch (unit->type) {
+ case VVC_DCI_NUT:
+ {
+ err = cbs_h266_read_dci(ctx, &gbc, unit->content);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_OPI_NUT:
+ {
+ err = cbs_h266_read_opi(ctx, &gbc, unit->content);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_VPS_NUT:
+ {
+ H266RawVPS *vps = unit->content;
+
+ err = cbs_h266_read_vps(ctx, &gbc, vps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_vps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_SPS_NUT:
+ {
+ H266RawSPS *sps = unit->content;
+
+ err = cbs_h266_read_sps(ctx, &gbc, sps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_sps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_PPS_NUT:
+ {
+ H266RawPPS *pps = unit->content;
+
+ err = cbs_h266_read_pps(ctx, &gbc, pps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_pps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_PREFIX_APS_NUT:
+ case VVC_SUFFIX_APS_NUT:
+ {
+ err = cbs_h266_read_aps(ctx, &gbc, unit->content,
+ unit->type == VVC_PREFIX_APS_NUT);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_PH_NUT:
+ {
+ H266RawPH *ph = unit->content;
+ err = cbs_h266_read_ph(ctx, &gbc, ph);
+ if (err < 0)
+ return err;
+ err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_TRAIL_NUT:
+ case VVC_STSA_NUT:
+ case VVC_RADL_NUT:
+ case VVC_RASL_NUT:
+ case VVC_IDR_W_RADL:
+ case VVC_IDR_N_LP:
+ case VVC_CRA_NUT:
+ case VVC_GDR_NUT:
+ {
+ H266RawSlice *slice = unit->content;
+ int pos, len;
+
+ err = cbs_h266_read_slice_header(ctx, &gbc, &slice->header);
+ if (err < 0)
+ return err;
+
+ if (!ff_cbs_h2645_read_more_rbsp_data(&gbc))
+ return AVERROR_INVALIDDATA;
+
+ pos = get_bits_count(&gbc);
+ len = unit->data_size;
+
+ if (slice->header.sh_picture_header_in_slice_header_flag) {
+ err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
+ if (err < 0)
+ return err;
+ slice->ph_ref = NULL;
+ } else {
+ slice->ph_ref = av_refstruct_ref(h266->ph_ref);
+ }
+ slice->ph = h266->ph;
+ slice->pps = av_refstruct_ref(h266->pps[slice->ph->ph_pic_parameter_set_id]);
+ slice->sps = av_refstruct_ref(h266->sps[slice->pps->pps_seq_parameter_set_id]);
+
+ slice->header_size = pos / 8;
+ slice->data_size = len - pos / 8;
+ slice->data_ref = av_buffer_ref(unit->data_ref);
+ if (!slice->data_ref)
+ return AVERROR(ENOMEM);
+ slice->data = unit->data + pos / 8;
+ slice->data_bit_start = pos % 8;
+ }
+ break;
+
+ case VVC_AUD_NUT:
+ {
+ err = cbs_h266_read_aud(ctx, &gbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_PREFIX_SEI_NUT:
+ case VVC_SUFFIX_SEI_NUT:
+ {
+ err = cbs_h266_read_sei(ctx, &gbc, unit->content,
+ unit->type == VVC_PREFIX_SEI_NUT);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ default:
+ return AVERROR(ENOSYS);
+ }
+ return 0;
+}
+
+static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit,
+ PutBitContext *pbc)
+{
+ int err;
+
+ switch (unit->type) {
+ case VVC_DCI_NUT:
+ {
+ H266RawDCI *dci = unit->content;
+
+ err = cbs_h266_write_dci(ctx, pbc, dci);
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_OPI_NUT:
+ {
+ H266RawOPI *opi = unit->content;
+
+ err = cbs_h266_write_opi(ctx, pbc, opi);
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_VPS_NUT:
+ {
+ H266RawVPS *vps = unit->content;
+
+ err = cbs_h266_write_vps(ctx, pbc, vps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_vps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_SPS_NUT:
+ {
+ H266RawSPS *sps = unit->content;
+
+ err = cbs_h266_write_sps(ctx, pbc, sps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_sps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_PPS_NUT:
+ {
+ H266RawPPS *pps = unit->content;
+
+ err = cbs_h266_write_pps(ctx, pbc, pps);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_pps(ctx, unit);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_PREFIX_APS_NUT:
+ case VVC_SUFFIX_APS_NUT:
+ {
+ err = cbs_h266_write_aps(ctx, pbc, unit->content,
+ unit->type == VVC_PREFIX_APS_NUT);
+ if (err < 0)
+ return err;
+ }
+ break;
+ case VVC_PH_NUT:
+ {
+ H266RawPH *ph = unit->content;
+ err = cbs_h266_write_ph(ctx, pbc, ph);
+ if (err < 0)
+ return err;
+
+ err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_TRAIL_NUT:
+ case VVC_STSA_NUT:
+ case VVC_RADL_NUT:
+ case VVC_RASL_NUT:
+ case VVC_IDR_W_RADL:
+ case VVC_IDR_N_LP:
+ case VVC_CRA_NUT:
+ case VVC_GDR_NUT:
+ {
+ H266RawSlice *slice = unit->content;
+
+ err = cbs_h266_write_slice_header(ctx, pbc, &slice->header);
+ if (err < 0)
+ return err;
+
+ if (slice->header.sh_picture_header_in_slice_header_flag) {
+ err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
+ if (err < 0)
+ return err;
+ }
+
+ if (slice->data) {
+ err = ff_cbs_h2645_write_slice_data(ctx, pbc, slice->data,
+ slice->data_size,
+ slice->data_bit_start);
+ if (err < 0)
+ return err;
+ } else {
+ // No slice data - that was just the header.
+ }
+ }
+ break;
+
+ case VVC_AUD_NUT:
+ {
+ err = cbs_h266_write_aud(ctx, pbc, unit->content);
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ case VVC_PREFIX_SEI_NUT:
+ case VVC_SUFFIX_SEI_NUT:
+ {
+ err = cbs_h266_write_sei(ctx, pbc, unit->content,
+ unit->type == VVC_PREFIX_SEI_NUT);
+
+ if (err < 0)
+ return err;
+ }
+ break;
+
+ default:
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
+ "NAL unit type %"PRIu32".\n", unit->type);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ return 0;
+}
+
+static av_cold void cbs_h266_flush(CodedBitstreamContext *ctx)
+{
+ CodedBitstreamH266Context *h266 = ctx->priv_data;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(h266->vps); i++)
+ av_refstruct_unref(&h266->vps[i]);
+ for (int i = 0; i < FF_ARRAY_ELEMS(h266->sps); i++)
+ av_refstruct_unref(&h266->sps[i]);
+ for (int i = 0; i < FF_ARRAY_ELEMS(h266->pps); i++)
+ av_refstruct_unref(&h266->pps[i]);
+ av_refstruct_unref(&h266->ph_ref);
+}
+
+static av_cold void cbs_h266_close(CodedBitstreamContext *ctx)
+{
+ CodedBitstreamH266Context *h266 = ctx->priv_data;
+
+ cbs_h266_flush(ctx);
+ ff_h2645_packet_uninit(&h266->common.read_packet);
+}
+
+static void cbs_h266_free_slice(AVRefStructOpaque unused, void *content)
+{
+ H266RawSlice *slice = content;
+ av_buffer_unref(&slice->data_ref);
+ av_refstruct_unref(&slice->sps);
+ av_refstruct_unref(&slice->pps);
+ av_refstruct_unref(&slice->ph_ref);
+}
+
+
+static void cbs_h266_free_sei(AVRefStructOpaque unused, void *content)
+{
+ H266RawSEI *sei = content;
+ ff_cbs_sei_free_message_list(&sei->message_list);
+}
+
+static CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = {
+ CBS_UNIT_TYPE_INTERNAL_REF(VVC_DCI_NUT, H266RawDCI, extension_data.data),
+ CBS_UNIT_TYPE_INTERNAL_REF(VVC_OPI_NUT, H266RawOPI, extension_data.data),
+ CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data),
+ {
+ .nb_unit_types = 1,
+ .unit_type.list[0] = VVC_SPS_NUT,
+ .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS,
+ .content_size = sizeof(H266RawSPS),
+ .type.ref = {
+ .nb_offsets = 2,
+ .offsets = { offsetof(H266RawSPS, extension_data.data),
+ offsetof(H266RawSPS, vui.extension_data.data) }
+ },
+ },
+ CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data),
+ CBS_UNIT_TYPE_INTERNAL_REF(VVC_PREFIX_APS_NUT, H266RawAPS, extension_data.data),
+ CBS_UNIT_TYPE_INTERNAL_REF(VVC_SUFFIX_APS_NUT, H266RawAPS, extension_data.data),
+
+ CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH),
+ CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD),
+
+ CBS_UNIT_TYPES_COMPLEX((VVC_TRAIL_NUT, VVC_STSA_NUT, VVC_RADL_NUT),
+ H266RawSlice, cbs_h266_free_slice),
+ CBS_UNIT_TYPES_COMPLEX((VVC_RASL_NUT, VVC_IDR_W_RADL, VVC_IDR_N_LP),
+ H266RawSlice, cbs_h266_free_slice),
+ CBS_UNIT_TYPES_COMPLEX((VVC_CRA_NUT, VVC_GDR_NUT),
+ H266RawSlice, cbs_h266_free_slice),
+
+ CBS_UNIT_TYPES_COMPLEX((VVC_PREFIX_SEI_NUT, VVC_SUFFIX_SEI_NUT),
+ H266RawSEI, cbs_h266_free_sei),
+
+ CBS_UNIT_TYPE_END_OF_LIST
+};
+
+const CodedBitstreamType ff_cbs_type_h266 = {
+ .codec_id = AV_CODEC_ID_VVC,
+
+ .priv_data_size = sizeof(CodedBitstreamH266Context),
+
+ .unit_types = cbs_h266_unit_types,
+
+ .split_fragment = &cbs_h266_split_fragment,
+ .read_unit = &cbs_h266_read_nal_unit,
+ .write_unit = &cbs_h266_write_nal_unit,
+ .assemble_fragment = &ff_cbs_h2645_assemble_fragment,
+
+ .flush = &cbs_h266_flush,
+ .close = &cbs_h266_close,
+};
diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c
index 4f6ae76e27..d33240e7df 100644
--- a/libavcodec/cbs_h266_syntax_template.c
+++ b/libavcodec/cbs_h266_syntax_template.c
@@ -318,7 +318,7 @@ static int FUNC(payload_extension) (CodedBitstreamContext *ctx, RWContext *rw,
GetBitContext tmp;
int bits_left, payload_zero_bits;
- if (!cbs_h265_payload_extension_present(rw, payload_size, cur_pos))
+ if (!ff_cbs_h2645_payload_extension_present(rw, payload_size, cur_pos))
return 0;
bits_left = 8 * payload_size - cur_pos;
@@ -373,7 +373,7 @@ static int FUNC(extension_data) (CodedBitstreamContext *ctx, RWContext *rw,
GetBitContext start;
uint8_t bit;
start = *rw;
- for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++)
+ for (k = 0; ff_cbs_h2645_read_more_rbsp_data(rw); k++)
skip_bits(rw, 1);
current->bit_length = k;
if (k > 0) {
diff --git a/libavcodec/cbs_sei.c b/libavcodec/cbs_sei.c
index d57901f15d..f354a10029 100644
--- a/libavcodec/cbs_sei.c
+++ b/libavcodec/cbs_sei.c
@@ -25,6 +25,206 @@
#include "cbs_sei.h"
#include "libavutil/refstruct.h"
+#define HEADER(name) do { \
+ ff_cbs_trace_header(ctx, name); \
+ } while (0)
+
+#define CHECK(call) do { \
+ err = (call); \
+ if (err < 0) \
+ return err; \
+ } while (0)
+
+#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
+#define FUNC_NAME2_EXPORT(rw, codec, name) ff_cbs_ ## codec ## _ ## rw ## _ ## name
+#define FUNC_NAME1_EXPORT(rw, codec, name) FUNC_NAME2_EXPORT(rw, codec, name)
+#define FUNC_SEI(name) FUNC_NAME1(READWRITE, sei, name)
+#define FUNC_SEI_EXPORT(name) FUNC_NAME1_EXPORT(READWRITE, sei, name)
+
+#define SEI_FUNC(name, args) \
+static int FUNC_SEI(name) args; \
+static int FUNC_SEI(name ## _internal)(CodedBitstreamContext *ctx, \
+ RWContext *rw, void *cur, \
+ SEIMessageState *state) \
+{ \
+ return FUNC_SEI(name)(ctx, rw, cur, state); \
+} \
+static int FUNC_SEI(name) args
+
+#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
+
+#define u(width, name, range_min, range_max) \
+ xu(width, name, current->name, range_min, range_max, 0, )
+#define flag(name) ub(1, name)
+#define ue(name, range_min, range_max) \
+ xue(name, current->name, range_min, range_max, 0, )
+#define i(width, name, range_min, range_max) \
+ xi(width, name, current->name, range_min, range_max, 0, )
+#define ib(width, name) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
+#define se(name, range_min, range_max) \
+ xse(name, current->name, range_min, range_max, 0, )
+
+#define us(width, name, range_min, range_max, subs, ...) \
+ xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ubs(width, name, subs, ...) \
+ xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
+#define flags(name, subs, ...) \
+ xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
+#define ues(name, range_min, range_max, subs, ...) \
+ xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define is(width, name, range_min, range_max, subs, ...) \
+ xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
+#define ibs(width, name, subs, ...) \
+ xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
+#define ses(name, range_min, range_max, subs, ...) \
+ xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
+
+#define fixed(width, name, value) do { \
+ av_unused uint32_t fixed_value = value; \
+ xu(width, name, fixed_value, value, value, 0, ); \
+ } while (0)
+
+
+#define READ
+#define READWRITE read
+#define RWContext GetBitContext
+
+#define ub(width, name) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
+ &value)); \
+ current->name = value; \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value; \
+ CHECK(ff_cbs_read_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value; \
+ CHECK(ff_cbs_read_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ &value, range_min, range_max)); \
+ var = value; \
+ } while (0)
+
+
+#define infer(name, value) do { \
+ current->name = value; \
+ } while (0)
+
+#define more_rbsp_data(var) ((var) = ff_cbs_h2645_read_more_rbsp_data(rw))
+
+#define bit_position(rw) (get_bits_count(rw))
+#define byte_alignment(rw) (get_bits_count(rw) % 8)
+
+/* The CBS SEI code uses the refstruct API for the allocation
+ * of its child buffers. */
+#define allocate(name, size) do { \
+ name = av_refstruct_allocz(size + \
+ AV_INPUT_BUFFER_PADDING_SIZE); \
+ if (!name) \
+ return AVERROR(ENOMEM); \
+ } while (0)
+
+#define FUNC(name) FUNC_SEI_EXPORT(name)
+#include "cbs_sei_syntax_template.c"
+#undef FUNC
+
+#undef READ
+#undef READWRITE
+#undef RWContext
+#undef ub
+#undef xu
+#undef xi
+#undef xue
+#undef xse
+#undef infer
+#undef more_rbsp_data
+#undef bit_position
+#undef byte_alignment
+#undef allocate
+
+
+#define WRITE
+#define READWRITE write
+#define RWContext PutBitContext
+
+#define ub(width, name) do { \
+ uint32_t value = current->name; \
+ CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
+ value)); \
+ } while (0)
+#define xu(width, name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xue(name, var, range_min, range_max, subs, ...) do { \
+ uint32_t value = var; \
+ CHECK(ff_cbs_write_ue_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xi(width, name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+#define xse(name, var, range_min, range_max, subs, ...) do { \
+ int32_t value = var; \
+ CHECK(ff_cbs_write_se_golomb(ctx, rw, #name, \
+ SUBSCRIPTS(subs, __VA_ARGS__), \
+ value, range_min, range_max)); \
+ } while (0)
+
+#define infer(name, value) do { \
+ if (current->name != (value)) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, \
+ "%s does not match inferred value: " \
+ "%"PRId64", but should be %"PRId64".\n", \
+ #name, (int64_t)current->name, (int64_t)(value)); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define more_rbsp_data(var) (var)
+
+#define bit_position(rw) (put_bits_count(rw))
+#define byte_alignment(rw) (put_bits_count(rw) % 8)
+
+#define allocate(name, size) do { \
+ if (!name) { \
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
+ "for writing.\n", #name); \
+ return AVERROR_INVALIDDATA; \
+ } \
+ } while (0)
+
+#define FUNC(name) FUNC_SEI_EXPORT(name)
+#include "cbs_sei_syntax_template.c"
+#undef FUNC
+
static void cbs_free_user_data_registered(AVRefStructOpaque unused, void *obj)
{
SEIRawUserDataRegistered *udr = obj;
@@ -384,3 +584,123 @@ void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx,
}
}
}
+
+// Macro for the read/write pair.
+#define SEI_MESSAGE_RW(codec, name) \
+ .read = cbs_ ## codec ## _read_ ## name ## _internal, \
+ .write = cbs_ ## codec ## _write_ ## name ## _internal
+
+static const SEIMessageTypeDescriptor cbs_sei_common_types[] = {
+ {
+ SEI_TYPE_FILLER_PAYLOAD,
+ 1, 1,
+ sizeof(SEIRawFillerPayload),
+ SEI_MESSAGE_RW(sei, filler_payload),
+ },
+ {
+ SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
+ 1, 1,
+ sizeof(SEIRawUserDataRegistered),
+ SEI_MESSAGE_RW(sei, user_data_registered),
+ },
+ {
+ SEI_TYPE_USER_DATA_UNREGISTERED,
+ 1, 1,
+ sizeof(SEIRawUserDataUnregistered),
+ SEI_MESSAGE_RW(sei, user_data_unregistered),
+ },
+ {
+ SEI_TYPE_FRAME_PACKING_ARRANGEMENT,
+ 1, 0,
+ sizeof(SEIRawFramePackingArrangement),
+ SEI_MESSAGE_RW(sei, frame_packing_arrangement),
+ },
+ {
+ SEI_TYPE_DECODED_PICTURE_HASH,
+ 0, 1,
+ sizeof(SEIRawDecodedPictureHash),
+ SEI_MESSAGE_RW(sei, decoded_picture_hash),
+ },
+ {
+ SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME,
+ 1, 0,
+ sizeof(SEIRawMasteringDisplayColourVolume),
+ SEI_MESSAGE_RW(sei, mastering_display_colour_volume),
+ },
+ {
+ SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
+ 1, 0,
+ sizeof(SEIRawContentLightLevelInfo),
+ SEI_MESSAGE_RW(sei, content_light_level_info),
+ },
+ {
+ SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS,
+ 1, 0,
+ sizeof(SEIRawAlternativeTransferCharacteristics),
+ SEI_MESSAGE_RW(sei, alternative_transfer_characteristics),
+ },
+ {
+ SEI_TYPE_AMBIENT_VIEWING_ENVIRONMENT,
+ 1, 0,
+ sizeof(SEIRawAmbientViewingEnvironment),
+ SEI_MESSAGE_RW(sei, ambient_viewing_environment),
+ },
+ SEI_MESSAGE_TYPE_END,
+};
+
+static const SEIMessageTypeDescriptor cbs_sei_h274_types[] = {
+ {
+ SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
+ 1, 0,
+ sizeof(SEIRawFilmGrainCharacteristics),
+ SEI_MESSAGE_RW(sei, film_grain_characteristics),
+ },
+ {
+ SEI_TYPE_DISPLAY_ORIENTATION,
+ 1, 0,
+ sizeof(SEIRawDisplayOrientation),
+ SEI_MESSAGE_RW(sei, display_orientation)
+ },
+ {
+ SEI_TYPE_FRAME_FIELD_INFO,
+ 1, 0,
+ sizeof(SEIRawFrameFieldInformation),
+ SEI_MESSAGE_RW(sei, frame_field_information)
+ },
+ SEI_MESSAGE_TYPE_END,
+};
+
+const SEIMessageTypeDescriptor *ff_cbs_sei_find_type(CodedBitstreamContext *ctx,
+ int payload_type)
+{
+ const SEIMessageTypeDescriptor *codec_list = NULL;
+ int i;
+
+ switch (ctx->codec->codec_id) {
+#if CBS_H264
+ case AV_CODEC_ID_H264:
+ codec_list = ff_cbs_sei_h264_types;
+ break;
+#endif
+#if CBS_H265
+ case AV_CODEC_ID_H265:
+ codec_list = ff_cbs_sei_h265_types;
+ break;
+#endif
+ case AV_CODEC_ID_H266:
+ codec_list = cbs_sei_h274_types;
+ break;
+ }
+
+ for (i = 0; codec_list && codec_list[i].type >= 0; i++) {
+ if (codec_list[i].type == payload_type)
+ return &codec_list[i];
+ }
+
+ for (i = 0; cbs_sei_common_types[i].type >= 0; i++) {
+ if (cbs_sei_common_types[i].type == payload_type)
+ return &cbs_sei_common_types[i];
+ }
+
+ return NULL;
+}
diff --git a/libavcodec/cbs_sei.h b/libavcodec/cbs_sei.h
index decc4e19e1..e3e3097104 100644
--- a/libavcodec/cbs_sei.h
+++ b/libavcodec/cbs_sei.h
@@ -202,6 +202,9 @@ typedef struct SEIMessageTypeDescriptor {
#define SEI_MESSAGE_TYPE_END { .type = -1 }
+extern const SEIMessageTypeDescriptor ff_cbs_sei_h264_types[];
+extern const SEIMessageTypeDescriptor ff_cbs_sei_h265_types[];
+
/**
* Find the type descriptor for the given payload type.
*
@@ -263,4 +266,13 @@ void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx,
CodedBitstreamFragment *au,
uint32_t payload_type);
+int ff_cbs_sei_read_message_list(CodedBitstreamContext *ctx, struct GetBitContext *rw,
+ SEIRawMessageList *current, int prefix);
+int ff_cbs_sei_write_message_list(CodedBitstreamContext *ctx, struct PutBitContext *rw,
+ SEIRawMessageList *current, int prefix);
+int ff_cbs_sei_read_message(CodedBitstreamContext *ctx, struct GetBitContext *rw,
+ SEIRawMessage *current);
+int ff_cbs_sei_write_message(CodedBitstreamContext *ctx, struct PutBitContext *rw,
+ SEIRawMessage *current);
+
#endif /* AVCODEC_CBS_SEI_H */
diff --git a/libavcodec/cbs_sei_syntax_template.c b/libavcodec/cbs_sei_syntax_template.c
index f70eb24d80..4fc3061728 100644
--- a/libavcodec/cbs_sei_syntax_template.c
+++ b/libavcodec/cbs_sei_syntax_template.c
@@ -334,7 +334,7 @@ SEI_FUNC(frame_field_information, (CodedBitstreamContext *ctx, RWContext *rw,
return 0;
}
-static int FUNC(message)(CodedBitstreamContext *ctx, RWContext *rw,
+int FUNC(message)(CodedBitstreamContext *ctx, RWContext *rw,
SEIRawMessage *current)
{
const SEIMessageTypeDescriptor *desc;
@@ -422,7 +422,7 @@ static int FUNC(message)(CodedBitstreamContext *ctx, RWContext *rw,
return 0;
}
-static int FUNC(message_list)(CodedBitstreamContext *ctx, RWContext *rw,
+int FUNC(message_list)(CodedBitstreamContext *ctx, RWContext *rw,
SEIRawMessageList *current, int prefix)
{
SEIRawMessage *message;
@@ -471,7 +471,7 @@ static int FUNC(message_list)(CodedBitstreamContext *ctx, RWContext *rw,
skip_bits_long(rw, 8 * payload_size);
- if (!cbs_h2645_read_more_rbsp_data(rw))
+ if (!ff_cbs_h2645_read_more_rbsp_data(rw))
break;
}
#else
1
0