FFmpeg
Loading...
Searching...
No Matches
dovi_rpu.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "libavutil/common.h"
20#include "libavutil/mem.h"
21#include "libavutil/opt.h"
22
23#include "libavcodec/bsf.h"
25#include "libavcodec/cbs.h"
26#include "libavcodec/cbs_bsf.h"
27#include "libavcodec/cbs_av1.h"
28#include "libavcodec/cbs_h265.h"
29#include "libavcodec/dovi_rpu.h"
32#include "libavcodec/itut35.h"
33
35
44
45static int update_rpu(AVBSFContext *bsf, const AVPacket *pkt, int flags,
46 const uint8_t *rpu, size_t rpu_size,
47 uint8_t **out_rpu, int *out_size)
48{
51 int ret;
52
53 ret = ff_dovi_rpu_parse(&s->dec, rpu, rpu_size, 0);
54 if (ret < 0) {
55 ff_dovi_ctx_flush(&s->dec);
56 return ret;
57 }
58
59 ret = ff_dovi_get_metadata(&s->dec, &metadata);
60 if (ret == 0 /* no metadata */) {
61 *out_rpu = NULL;
62 *out_size = 0;
63 return 0;
64 } else if (ret < 0) {
65 ff_dovi_ctx_flush(&s->dec);
66 return ret;
67 }
68
69 if (pkt && !(pkt->flags & AV_PKT_FLAG_KEY))
71 ret = ff_dovi_rpu_generate(&s->enc, metadata, flags, out_rpu, out_size);
73 if (ret < 0)
74 ff_dovi_ctx_flush(&s->enc);
75
76 return ret;
77}
78
81{
83 CodedBitstreamUnit *nal = au->nb_units ? &au->units[au->nb_units - 1] : NULL;
84 uint8_t *rpu = NULL;
85 int rpu_size, ret;
86
87 // HEVC_NAL_UNSPEC62 is Dolby Vision RPU and HEVC_NAL_UNSPEC63 is Dolby Vision EL
88 if (!nal || (nal->type != HEVC_NAL_UNSPEC62 && nal->type != HEVC_NAL_UNSPEC63))
89 return 0;
90
91 if (s->strip) {
92 ff_cbs_delete_unit(au, au->nb_units - 1);
93 return 0;
94 }
95
96 if (nal->type == HEVC_NAL_UNSPEC63)
97 return 0;
98
99 ret = update_rpu(bsf, pkt, 0, nal->data + 2, nal->data_size - 2, &rpu, &rpu_size);
100 if (ret < 0)
101 return ret;
102 if (!rpu || rpu_size <= 0)
103 return 0;
104
105 /* NAL unit header + NAL prefix */
106 if (rpu_size + 3 <= nal->data_size && av_buffer_is_writable(nal->data_ref)) {
107 memcpy(nal->data + 3, rpu, rpu_size);
108 av_free(rpu);
109 nal->data_size = rpu_size + 3;
110 } else {
111 AVBufferRef *ref = av_buffer_alloc(rpu_size + 3);
112 if (!ref) {
113 av_free(rpu);
114 return AVERROR(ENOMEM);
115 }
116
117 memcpy(ref->data, nal->data, 3);
118 memcpy(ref->data + 3, rpu, rpu_size);
119 av_buffer_unref(&nal->data_ref);
120 av_free(rpu);
121 nal->data = ref->data;
122 nal->data_size = rpu_size + 3;
123 nal->data_ref = ref;
124 nal->data_bit_padding = 0;
125 }
126
127 return 0;
128}
129
132{
133 DoviRpuContext *s = bsf->priv_data;
134 int provider_code, provider_oriented_code, rpu_size, ret;
136 uint8_t *rpu;
137
138 for (int i = 0; i < frag->nb_units; i++) {
139 AV1RawOBU *obu = frag->units[i].content;
140 AV1RawMetadataITUTT35 *t35 = &obu->obu.metadata.metadata.itut_t35;
141 if (frag->units[i].type != AV1_OBU_METADATA ||
142 obu->obu.metadata.metadata_type != AV1_METADATA_TYPE_ITUT_T35 ||
144 t35->payload_size < 6)
145 continue;
146
147 provider_code = AV_RB16(t35->payload);
148 provider_oriented_code = AV_RB32(t35->payload + 2);
149 if (provider_code != ITU_T_T35_PROVIDER_CODE_DOLBY ||
150 provider_oriented_code != 0x800)
151 continue;
152
153 if (s->strip) {
154 ff_cbs_delete_unit(frag, i);
155 return 0;
156 }
157
158 ret = update_rpu(bsf, pkt, FF_DOVI_WRAP_T35,
159 t35->payload + 6, t35->payload_size - 6,
160 &rpu, &rpu_size);
161 if (ret < 0)
162 return ret;
163 if (!rpu || rpu_size <= 1) {
164 av_free(rpu);
165 continue;
166 }
167
168 ref = av_buffer_create(rpu, rpu_size, av_buffer_default_free, NULL, 0);
169 if (!ref) {
170 av_free(rpu);
171 return AVERROR(ENOMEM);
172 }
173
175 t35->payload_ref = ref;
176 t35->payload = rpu + 1; /* skip country code */
177 t35->payload_size = rpu_size - 1;
178 break; /* should be only one RPU per packet */
179 }
180
181 return 0;
182}
183
185 .codec_id = AV_CODEC_ID_HEVC,
186 .fragment_name = "access unit",
187 .unit_name = "NAL unit",
188 .update_fragment = &dovi_rpu_update_fragment_hevc,
189};
190
192 .codec_id = AV_CODEC_ID_AV1,
193 .fragment_name = "temporal unit",
194 .unit_name = "OBU",
195 .update_fragment = &dovi_rpu_update_fragment_av1,
196};
197
199{
200 int ret;
201 DoviRpuContext *s = bsf->priv_data;
202 s->dec.logctx = s->enc.logctx = bsf;
203 s->enc.enable = 1;
204
205 if (s->compression == AV_DOVI_COMPRESSION_RESERVED) {
206 av_log(bsf, AV_LOG_ERROR, "Invalid compression level: %d\n", s->compression);
207 return AVERROR(EINVAL);
208 }
209
210 if (s->strip) {
214 } else {
215 const AVPacketSideData *sd;
219
220 if (sd) {
223 s->dec.cfg = *cfg;
224
225 /* Update configuration record before setting to enc ctx */
226 cfg->dv_md_compression = s->compression;
227 if (s->compression && s->dec.cfg.dv_profile < 8) {
228 av_log(bsf, AV_LOG_ERROR, "Invalid compression level %d for "
229 "Dolby Vision profile %d.\n", s->compression, s->dec.cfg.dv_profile);
230 return AVERROR(EINVAL);
231 }
232
233 s->enc.cfg = *cfg;
234 } else {
235 av_log(bsf, AV_LOG_WARNING, "No Dolby Vision configuration record "
236 "found? Generating one, but results may be invalid.\n");
237 ret = ff_dovi_configure_from_codedpar(&s->enc, bsf->par_out, NULL, s->compression,
239 if (ret < 0)
240 return ret;
241 /* Be conservative in accepting all compressed RPUs */
242 s->dec.cfg = s->enc.cfg;
243 s->dec.cfg.dv_md_compression = AV_DOVI_COMPRESSION_EXTENDED;
244 }
245 }
246
247 switch (bsf->par_in->codec_id) {
248 case AV_CODEC_ID_HEVC:
250 case AV_CODEC_ID_AV1:
252 default:
253 return AVERROR_BUG;
254 }
255}
256
258{
259 DoviRpuContext *s = bsf->priv_data;
260 ff_dovi_ctx_unref(&s->dec);
261 ff_dovi_ctx_unref(&s->enc);
263}
264
265#define OFFSET(x) offsetof(DoviRpuContext, x)
266#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
267static const AVOption dovi_rpu_options[] = {
268 { "strip", "Strip Dolby Vision metadata", OFFSET(strip), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
269 { "compression", "DV metadata compression mode", OFFSET(compression), AV_OPT_TYPE_INT, { .i64 = AV_DOVI_COMPRESSION_LIMITED }, 0, AV_DOVI_COMPRESSION_EXTENDED, FLAGS, .unit = "compression" },
270 { "none", "Don't compress metadata", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, .flags = FLAGS, .unit = "compression" },
271 { "limited", "Limited metadata compression", 0, AV_OPT_TYPE_CONST, {.i64 = AV_DOVI_COMPRESSION_LIMITED}, .flags = FLAGS, .unit = "compression" },
272 { "extended", "Extended metadata compression",0, AV_OPT_TYPE_CONST, {.i64 = AV_DOVI_COMPRESSION_EXTENDED}, .flags = FLAGS, .unit = "compression" },
273 { NULL }
274};
275
276static const AVClass dovi_rpu_class = {
277 .class_name = "dovi_rpu_bsf",
278 .item_name = av_default_item_name,
279 .option = dovi_rpu_options,
280 .version = LIBAVUTIL_VERSION_INT,
281};
282
286
288 .p.name = "dovi_rpu",
289 .p.codec_ids = dovi_rpu_codec_ids,
290 .p.priv_class = &dovi_rpu_class,
291 .priv_data_size = sizeof(DoviRpuContext),
295};
static int out_size
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
const FFBitStreamFilter ff_dovi_rpu_bsf
Definition dovi_rpu.c:287
static int dovi_rpu_update_fragment_hevc(AVBSFContext *bsf, AVPacket *pkt, CodedBitstreamFragment *au)
Definition dovi_rpu.c:79
static const CBSBSFType dovi_rpu_hevc_type
Definition dovi_rpu.c:184
static int dovi_rpu_update_fragment_av1(AVBSFContext *bsf, AVPacket *pkt, CodedBitstreamFragment *frag)
Definition dovi_rpu.c:130
static void dovi_rpu_close(AVBSFContext *bsf)
Definition dovi_rpu.c:257
static int dovi_rpu_init(AVBSFContext *bsf)
Definition dovi_rpu.c:198
static int update_rpu(AVBSFContext *bsf, const AVPacket *pkt, int flags, const uint8_t *rpu, size_t rpu_size, uint8_t **out_rpu, int *out_size)
Definition dovi_rpu.c:45
static const AVOption dovi_rpu_options[]
Definition dovi_rpu.c:267
static enum AVCodecID dovi_rpu_codec_ids[]
Definition dovi_rpu.c:283
#define OFFSET(x)
Definition dovi_rpu.c:265
static const AVClass dovi_rpu_class
Definition dovi_rpu.c:276
static const CBSBSFType dovi_rpu_av1_type
Definition dovi_rpu.c:191
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
int ff_cbs_bsf_generic_filter(AVBSFContext *bsf, AVPacket *pkt)
Filter operation for CBS BSF.
Definition cbs_bsf.c:97
av_cold void ff_cbs_bsf_generic_close(AVBSFContext *bsf)
Close a generic CBS BSF instance.
Definition cbs_bsf.c:191
av_cold int ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type)
Initialise generic CBS BSF setup.
Definition cbs_bsf.c:146
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC nal(CodedBitstreamContext *ctx, RWContext *rw, LCEVCRawNAL *current, int nal_unit_type)
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
common internal and external API header
#define NULL
Definition coverity.c:32
#define FF_COMPLIANCE_NORMAL
Definition defs.h:60
static AVPacket * pkt
@ AV_DOVI_COMPRESSION_EXTENDED
Definition dovi_meta.h:71
@ AV_DOVI_COMPRESSION_LIMITED
Definition dovi_meta.h:69
@ AV_DOVI_COMPRESSION_RESERVED
Definition dovi_meta.h:70
av_cold void ff_dovi_ctx_flush(DOVIContext *s)
Partially reset the internal state.
Definition dovi_rpu.c:43
void ff_dovi_ctx_unref(DOVIContext *s)
Completely reset a DOVIContext, preserving only logctx.
Definition dovi_rpu.c:30
int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size, int err_recognition)
Parse the contents of a Dolby Vision RPU and update the parsed values in the DOVIContext struct.
int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata, int flags, uint8_t **out_rpu, int *out_size)
Synthesize a Dolby Vision RPU reflecting the current state.
@ FF_DOVI_WRAP_T35
wrap inside T.35+EMDF
Definition dovi_rpu.h:160
@ FF_DOVI_COMPRESS_RPU
enable compression for this RPU
Definition dovi_rpu.h:161
int ff_dovi_configure_from_codedpar(DOVIContext *s, AVCodecParameters *codecpar, const AVDOVIMetadata *metadata, enum AVDOVICompression compression, int strict_std_compliance)
Configure the encoder for Dolby Vision encoding.
int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
Get the decoded AVDOVIMetadata.
Definition dovi_rpudec.c:33
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static CheckasmConfig cfg
Definition checkasm.c:74
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition codec_id.h:47
@ AV_CODEC_ID_NONE
Definition codec_id.h:48
@ AV_CODEC_ID_AV1
Definition codec_id.h:275
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
void av_packet_side_data_remove(AVPacketSideData *sd, int *pnb_sd, enum AVPacketSideDataType type)
Remove side data of the given type from a side data array.
Definition packet.c:642
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition packet.c:570
@ AV_PKT_DATA_DOVI_CONF
DOVI configuration ref: dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2....
Definition packet.h:280
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
int av_buffer_is_writable(const AVBufferRef *buf)
Definition buffer.c:147
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
void av_buffer_default_free(void *opaque, uint8_t *data)
Default free callback, which calls av_free() on the buffer data.
Definition buffer.c:72
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition buffer.c:77
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define AV_RB32(p)
#define AV_RB16(p)
#define ITU_T_T35_PROVIDER_CODE_DOLBY
Definition itut35.h:45
#define ITU_T_T35_COUNTRY_CODE_US
Definition itut35.h:32
@ AV1_METADATA_TYPE_ITUT_T35
Definition av1.h:47
@ AV1_OBU_METADATA
Definition av1.h:34
@ HEVC_NAL_UNSPEC62
Definition hevc.h:91
@ HEVC_NAL_UNSPEC63
Definition hevc.h:92
Memory handling functions.
AVOptions.
uint8_t itu_t_t35_country_code
Definition cbs_av1.h:364
AVBufferRef * payload_ref
Definition cbs_av1.h:368
union AV1RawOBU::@016362317061177152367125047142162076164261250366 obu
The bitstream filter state.
Definition bsf.h:68
void * priv_data
Opaque filter-specific private data.
Definition bsf.h:83
AVCodecParameters * par_in
Parameters of the input stream.
Definition bsf.h:90
AVCodecParameters * par_out
Parameters of the output stream.
Definition bsf.h:96
A reference to a data buffer.
Definition buffer.h:82
Describe the class of an AVClass context structure.
Definition log.h:76
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition codec_par.h:88
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
AVPacketSideData * coded_side_data
Additional data associated with the entire stream.
Definition codec_par.h:83
Combined struct representing a combination of header, mapping and color metadata, for attaching to fr...
Definition dovi_meta.h:345
AVOption.
Definition opt.h:428
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition packet.h:424
uint8_t * data
Definition packet.h:425
This structure stores compressed data.
Definition packet.h:580
Coded bitstream fragment structure, combining one or more units.
Definition cbs.h:129
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
Definition cbs.h:175
int nb_units
Number of units in this fragment.
Definition cbs.h:160
Coded bitstream unit structure.
Definition cbs.h:77
void * content
Pointer to the decomposed form of this unit.
Definition cbs.h:114
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition cbs.h:81
DOVIContext dec
Definition dovi_rpu.c:38
DOVIContext enc
Definition dovi_rpu.c:39
CBSBSFContext common
Definition dovi_rpu.c:37
#define av_free(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
static int ref[MAX_W *MAX_W]