FFmpeg
Loading...
Searching...
No Matches
cbs_apv.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/mem.h"
20#include "cbs.h"
21#include "cbs_internal.h"
22#include "cbs_apv.h"
23
24
26{
27 switch (fh->frame_info.chroma_format_idc) {
29 return 1;
32 return 3;
34 return 4;
35 default:
36 av_unreachable("Invalid chroma_format_idc");
37 }
38}
39
41 const APVRawFrameHeader *fh)
42{
43 CodedBitstreamAPVContext *priv = ctx->priv_data;
44 int frame_width_in_mbs = (fh->frame_info.frame_width + 15) / 16;
45 int frame_height_in_mbs = (fh->frame_info.frame_height + 15) / 16;
46 int tile_cols = (frame_width_in_mbs + fh->tile_info.tile_width_in_mbs - 1) / fh->tile_info.tile_width_in_mbs;
47 int tile_rows = (frame_height_in_mbs + fh->tile_info.tile_height_in_mbs - 1) / fh->tile_info.tile_height_in_mbs;
48
50
52}
53
54
55#define HEADER(name) do { \
56 CBS_FUNC(trace_header)(ctx, name); \
57 } while (0)
58
59#define CHECK(call) do { \
60 err = (call); \
61 if (err < 0) \
62 return err; \
63 } while (0)
64
65#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
66
67
68#define u(width, name, range_min, range_max) \
69 xu(width, name, current->name, range_min, range_max, 0, )
70#define us(width, name, range_min, range_max, subs, ...) \
71 xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
72#define ubs(width, name, subs, ...) \
73 xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
74
75#define fixed(width, name, value) do { \
76 av_unused uint32_t fixed_value = value; \
77 xu(width, name, fixed_value, value, value, 0, ); \
78 } while (0)
79
80
81#if CBS_READ
82#define READ
83#define READWRITE read
84#define RWContext GetBitContext
85#define FUNC(name) cbs_apv_read_ ## name
86
87#define ub(width, name) do { \
88 uint32_t value; \
89 CHECK(CBS_FUNC(read_simple_unsigned)(ctx, rw, width, #name, \
90 &value)); \
91 current->name = value; \
92 } while (0)
93#define xu(width, name, var, range_min, range_max, subs, ...) do { \
94 uint32_t value; \
95 CHECK(CBS_FUNC(read_unsigned)(ctx, rw, width, #name, \
96 SUBSCRIPTS(subs, __VA_ARGS__), \
97 &value, range_min, range_max)); \
98 var = value; \
99 } while (0)
100
101#define infer(name, value) do { \
102 current->name = value; \
103 } while (0)
104
105#define byte_alignment(rw) (get_bits_count(rw) % 8)
106
108
109#undef READ
110#undef READWRITE
111#undef RWContext
112#undef FUNC
113#undef ub
114#undef xu
115#undef infer
116#undef byte_alignment
117#endif // CBS_READ
118
119#if CBS_WRITE
120#define WRITE
121#define READWRITE write
122#define RWContext PutBitContext
123#define FUNC(name) cbs_apv_write_ ## name
124
125#define ub(width, name) do { \
126 uint32_t value = current->name; \
127 CHECK(CBS_FUNC(write_simple_unsigned)(ctx, rw, width, #name, \
128 value)); \
129 } while (0)
130#define xu(width, name, var, range_min, range_max, subs, ...) do { \
131 uint32_t value = var; \
132 CHECK(CBS_FUNC(write_unsigned)(ctx, rw, width, #name, \
133 SUBSCRIPTS(subs, __VA_ARGS__), \
134 value, range_min, range_max)); \
135 } while (0)
136
137#define infer(name, value) do { \
138 if (current->name != (value)) { \
139 av_log(ctx->log_ctx, AV_LOG_ERROR, \
140 "%s does not match inferred value: " \
141 "%"PRId64", but should be %"PRId64".\n", \
142 #name, (int64_t)current->name, (int64_t)(value)); \
143 return AVERROR_INVALIDDATA; \
144 } \
145 } while (0)
146
147#define byte_alignment(rw) (put_bits_count(rw) % 8)
148
150
151#undef WRITE
152#undef READWRITE
153#undef RWContext
154#undef FUNC
155#undef ub
156#undef xu
157#undef infer
158#undef byte_alignment
159#endif // CBS_WRITE
160
161
164 int header)
165{
166#if CBS_READ
167 uint8_t *data = frag->data;
168 size_t size = frag->data_size;
169 uint32_t signature;
170 int err, trace;
171
172 if (header || !frag->data_size) {
173 // Ignore empty or extradata fragments.
174 return 0;
175 }
176
177 if (frag->data_size < 4) {
178 // Too small to be a valid fragment.
179 return AVERROR_INVALIDDATA;
180 }
181
182 // Don't include parsing here in trace output.
183 trace = ctx->trace_enable;
184 ctx->trace_enable = 0;
185
187 if (signature != APV_SIGNATURE) {
188 av_log(ctx->log_ctx, AV_LOG_ERROR,
189 "Invalid APV access unit: bad signature %08x.\n",
190 signature);
192 goto fail;
193 }
194 data += 4;
195 size -= 4;
196
197 while (size > 0) {
198 GetBitContext gbc;
199 uint32_t pbu_size;
201
202 if (size < 8) {
203 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid PBU: "
204 "fragment too short (%zu bytes).\n",
205 size);
207 goto fail;
208 }
209
210 pbu_size = AV_RB32(data);
211 if (pbu_size < 8) {
212 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid PBU: "
213 "pbu_size too small (%"PRIu32" bytes).\n",
214 pbu_size);
216 goto fail;
217 }
218
219 data += 4;
220 size -= 4;
221
222 if (pbu_size > size) {
223 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid PBU: "
224 "pbu_size too large (%"PRIu32" bytes).\n",
225 pbu_size);
227 goto fail;
228 }
229
230 init_get_bits(&gbc, data, 8 * pbu_size);
231
232 err = cbs_apv_read_pbu_header(ctx, &gbc, &pbu_header);
233 if (err < 0)
234 goto fail;
235
236 // Could select/skip frames based on type/group_id here.
237
238 err = CBS_FUNC(append_unit_data)(frag, pbu_header.pbu_type,
239 data, pbu_size, frag->data_ref);
240 if (err < 0)
241 goto fail;
242
243 data += pbu_size;
244 size -= pbu_size;
245 }
246
247 err = 0;
248fail:
249 ctx->trace_enable = trace;
250 return err;
251#else
252 return AVERROR(ENOSYS);
253#endif
254}
255
257 CodedBitstreamUnit *unit)
258{
259#if CBS_READ
260 GetBitContext gbc;
261 int err;
262
263 err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
264 if (err < 0)
265 return err;
266
267 err = CBS_FUNC(alloc_unit_content)(ctx, unit);
268 if (err < 0)
269 return err;
270
271 switch (unit->type) {
277 {
278 APVRawFrame *frame = unit->content;
279
280 err = cbs_apv_read_frame(ctx, &gbc, frame);
281 if (err < 0)
282 return err;
283
284 // Each tile inside the frame has pointers into the unit
285 // data buffer; make a single reference here for all of
286 // them together.
287 frame->tile_data_ref = av_buffer_ref(unit->data_ref);
288 if (!frame->tile_data_ref)
289 return AVERROR(ENOMEM);
290 }
291 break;
293 {
294 err = cbs_apv_read_au_info(ctx, &gbc, unit->content);
295 if (err < 0)
296 return err;
297 }
298 break;
299 case APV_PBU_METADATA:
300 {
301 err = cbs_apv_read_metadata(ctx, &gbc, unit->content);
302 if (err < 0)
303 return err;
304 }
305 break;
306 case APV_PBU_FILLER:
307 {
308 err = cbs_apv_read_filler(ctx, &gbc, unit->content);
309 if (err < 0)
310 return err;
311 }
312 break;
313 default:
314 return AVERROR(ENOSYS);
315 }
316
317 return 0;
318#else
319 return AVERROR(ENOSYS);
320#endif
321}
322
324 CodedBitstreamUnit *unit,
325 PutBitContext *pbc)
326{
327#if CBS_WRITE
328 int err;
329
330 switch (unit->type) {
336 {
337 APVRawFrame *frame = unit->content;
338
339 err = cbs_apv_write_frame(ctx, pbc, frame);
340 if (err < 0)
341 return err;
342 }
343 break;
345 {
346 err = cbs_apv_write_au_info(ctx, pbc, unit->content);
347 if (err < 0)
348 return err;
349 }
350 break;
351 case APV_PBU_METADATA:
352 {
353 err = cbs_apv_write_metadata(ctx, pbc, unit->content);
354 if (err < 0)
355 return err;
356 }
357 break;
358 case APV_PBU_FILLER:
359 {
360 err = cbs_apv_write_filler(ctx, pbc, unit->content);
361 if (err < 0)
362 return err;
363 }
364 break;
365 default:
366 return AVERROR(ENOSYS);
367 }
368
369 return 0;
370#else
371 return AVERROR(ENOSYS);
372#endif
373}
374
377{
378#if CBS_WRITE
379 size_t size = 4, pos;
380
381 for (int i = 0; i < frag->nb_units; i++)
382 size += frag->units[i].data_size + 4;
383
385 if (!frag->data_ref)
386 return AVERROR(ENOMEM);
387 frag->data = frag->data_ref->data;
388 memset(frag->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
389
390 AV_WB32(frag->data, APV_SIGNATURE);
391 pos = 4;
392 for (int i = 0; i < frag->nb_units; i++) {
393 AV_WB32(frag->data + pos, frag->units[i].data_size);
394 pos += 4;
395
396 memcpy(frag->data + pos, frag->units[i].data,
397 frag->units[i].data_size);
398 pos += frag->units[i].data_size;
399 }
400 av_assert0(pos == size);
401 frag->data_size = size;
402
403 return 0;
404#else
405 return AVERROR(ENOSYS);
406#endif
407}
408
409
410static void cbs_apv_free_metadata(AVRefStructOpaque unused, void *content)
411{
412 APVRawMetadata *md = content;
413 av_assert0(md->pbu_header.pbu_type == APV_PBU_METADATA);
414
415 for (int i = 0; i < md->metadata_count; i++) {
416 APVRawMetadataPayload *pl = &md->payloads[i];
417
418 switch (pl->payload_type) {
420 case APV_METADATA_CLL:
422 break;
425 break;
428 break;
429 default:
431 }
432 }
433}
434
436 {
437 .nb_unit_types = CBS_UNIT_TYPE_RANGE,
438 .unit_type.range = {
439 .start = APV_PBU_PRIMARY_FRAME,
440 .end = APV_PBU_ALPHA_FRAME,
441 },
442 .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS,
443 .content_size = sizeof(APVRawFrame),
444 .type.ref = {
445 .nb_offsets = 1,
446 .offsets = { offsetof(APVRawFrame, tile_data_ref) -
447 sizeof(void*) },
448 },
449 },
450
453
456
458};
459
460const CodedBitstreamType CBS_FUNC(type_apv) = {
461 .codec_id = AV_CODEC_ID_APV,
462
463 .priv_data_size = sizeof(CodedBitstreamAPVContext),
464
465 .unit_types = cbs_apv_unit_types,
466
467 .split_fragment = &cbs_apv_split_fragment,
468 .read_unit = &cbs_apv_read_unit,
469 .write_unit = &cbs_apv_write_unit,
470 .assemble_fragment = &cbs_apv_assemble_fragment,
471};
static AVFormatContext * ctx
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition avassert.h:109
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
static int FUNC pbu_header(CodedBitstreamContext *ctx, RWContext *rw, APVRawPBUHeader *current)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define CBS_UNIT_TYPE_POD(type_, structure)
@ CBS_UNIT_TYPE_RANGE
#define CBS_UNIT_TYPE_END_OF_LIST
@ CBS_CONTENT_TYPE_INTERNAL_REFS
#define CBS_UNIT_TYPE_COMPLEX(type, structure, free_func)
static AVFrame * frame
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition get_bits.h:517
#define fail
Definition test.h:479
@ AV_CODEC_ID_APV
Definition codec_id.h:323
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
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
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition buffer.c:77
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int tile_rows
cl_device_type type
#define AV_WB32(p, v)
#define AV_RB32(p)
static const char signature[]
Definition ipmovie.c:592
@ APV_PBU_ALPHA_FRAME
Definition apv.h:31
@ APV_PBU_PRIMARY_FRAME
Definition apv.h:27
@ APV_PBU_PREVIEW_FRAME
Definition apv.h:29
@ APV_PBU_NON_PRIMARY_FRAME
Definition apv.h:28
@ APV_PBU_FILLER
Definition apv.h:34
@ APV_PBU_ACCESS_UNIT_INFORMATION
Definition apv.h:32
@ APV_PBU_DEPTH_FRAME
Definition apv.h:30
@ APV_PBU_METADATA
Definition apv.h:33
@ APV_CHROMA_FORMAT_422
Definition apv.h:48
@ APV_CHROMA_FORMAT_400
Definition apv.h:47
@ APV_CHROMA_FORMAT_4444
Definition apv.h:50
@ APV_CHROMA_FORMAT_444
Definition apv.h:49
#define APV_SIGNATURE
Definition apv.h:23
@ APV_MAX_TILE_COLS
Definition apv.h:75
@ APV_MAX_TILE_ROWS
Definition apv.h:76
@ APV_METADATA_ITU_T_T35
Definition apv.h:82
@ APV_METADATA_USER_DEFINED
Definition apv.h:86
@ APV_METADATA_CLL
Definition apv.h:84
@ APV_METADATA_MDCV
Definition apv.h:83
@ APV_METADATA_FILLER
Definition apv.h:85
int CBS_FUNC alloc_unit_content(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit)
Allocate a new internal content buffer matching the type of the unit.
Definition cbs.c:911
int CBS_FUNC append_unit_data(CodedBitstreamFragment *frag, CodedBitstreamUnitType type, uint8_t *data, size_t data_size, AVBufferRef *data_buf)
Add a new unit to a fragment with the given data bitstream.
Definition cbs.c:838
#define CBS_FUNC(name)
Definition cbs.h:38
static void cbs_apv_derive_tile_info(CodedBitstreamContext *ctx, const APVRawFrameHeader *fh)
Definition cbs_apv.c:40
static int cbs_apv_assemble_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag)
Definition cbs_apv.c:375
static int cbs_apv_get_num_comp(const APVRawFrameHeader *fh)
Definition cbs_apv.c:25
static int cbs_apv_write_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit, PutBitContext *pbc)
Definition cbs_apv.c:323
static int cbs_apv_read_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit)
Definition cbs_apv.c:256
static CodedBitstreamUnitTypeDescriptor cbs_apv_unit_types[]
Definition cbs_apv.c:435
static void cbs_apv_free_metadata(AVRefStructOpaque unused, void *content)
Definition cbs_apv.c:410
static int cbs_apv_split_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int header)
Definition cbs_apv.c:162
Memory handling functions.
const char data[16]
Definition mxf.c:149
static const uint8_t header[24]
Definition sdr2.c:68
unsigned int pos
Definition spdifenc.c:431
APVRawTileInfo tile_info
Definition cbs_apv.h:80
APVRawFrameInfo frame_info
Definition cbs_apv.h:68
uint32_t frame_width
Definition cbs_apv.h:48
uint32_t frame_height
Definition cbs_apv.h:49
uint8_t chroma_format_idc
Definition cbs_apv.h:50
AVBufferRef * data_ref
Definition cbs_apv.h:129
APVRawMetadataUndefined undefined
Definition cbs_apv.h:174
uint32_t payload_type
Definition cbs_apv.h:166
APVRawMetadataITUTT35 itu_t_t35
Definition cbs_apv.h:169
APVRawMetadataUserDefined user_defined
Definition cbs_apv.h:173
AVBufferRef * data_ref
Definition cbs_apv.h:161
AVBufferRef * data_ref
Definition cbs_apv.h:155
uint32_t tile_width_in_mbs
Definition cbs_apv.h:61
uint32_t tile_height_in_mbs
Definition cbs_apv.h:62
uint8_t * data
The data buffer.
Definition buffer.h:90
Context structure for coded bitstream operations.
Definition cbs.h:226
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
size_t data_size
The number of bytes in the bitstream.
Definition cbs.h:142
uint8_t * data
Pointer to the bitstream form of this fragment.
Definition cbs.h:135
AVBufferRef * data_ref
A reference to the buffer containing data.
Definition cbs.h:152
Coded bitstream unit structure.
Definition cbs.h:77
void * content
Pointer to the decomposed form of this unit.
Definition cbs.h:114
uint8_t * data
Pointer to the directly-parsable bitstream form of this unit.
Definition cbs.h:88
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition cbs.h:81
size_t data_size
The number of bytes in the bitstream (including any padding bits in the final byte).
Definition cbs.h:93
AVBufferRef * data_ref
A reference to the buffer containing data.
Definition cbs.h:105
#define av_log(a,...)
int tile_cols
Definition av1_levels.c:73
int size
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
#define md