lavc: Add coded bitstream read/write support for H.264
[libav.git] / libavcodec / cbs.c
CommitLineData
18f1706f
MT
1/*
2 * This file is part of Libav.
3 *
4 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <string.h>
20
21#include "config.h"
22
23#include "libavutil/avassert.h"
24#include "libavutil/common.h"
25
26#include "cbs.h"
27#include "cbs_internal.h"
28
29
30static const CodedBitstreamType *cbs_type_table[] = {
acf06f45
MT
31#if CONFIG_CBS_H264
32 &ff_cbs_type_h264,
33#endif
18f1706f
MT
34};
35
36int ff_cbs_init(CodedBitstreamContext *ctx,
37 enum AVCodecID codec_id, void *log_ctx)
38{
39 const CodedBitstreamType *type;
40 int i;
41
42 type = NULL;
43 for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
44 if (cbs_type_table[i]->codec_id == codec_id) {
45 type = cbs_type_table[i];
46 break;
47 }
48 }
49 if (!type)
50 return AVERROR(EINVAL);
51
52 ctx->log_ctx = log_ctx;
53 ctx->codec = type;
54
55 ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
56 if (!ctx->priv_data)
57 return AVERROR(ENOMEM);
58
59 ctx->decompose_unit_types = NULL;
60
61 ctx->trace_enable = 0;
62 ctx->trace_level = AV_LOG_TRACE;
63
64 return 0;
65}
66
67void ff_cbs_close(CodedBitstreamContext *ctx)
68{
69 if (ctx->codec && ctx->codec->close)
70 ctx->codec->close(ctx);
71
72 av_freep(&ctx->priv_data);
73}
74
75static void cbs_unit_uninit(CodedBitstreamContext *ctx,
76 CodedBitstreamUnit *unit)
77{
78 if (ctx->codec->free_unit && unit->content && !unit->content_external)
79 ctx->codec->free_unit(unit);
80
81 av_freep(&unit->data);
82 unit->data_size = 0;
83 unit->data_bit_padding = 0;
84}
85
86void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
87 CodedBitstreamFragment *frag)
88{
89 int i;
90
91 for (i = 0; i < frag->nb_units; i++)
92 cbs_unit_uninit(ctx, &frag->units[i]);
93 av_freep(&frag->units);
94 frag->nb_units = 0;
95
96 av_freep(&frag->data);
97 frag->data_size = 0;
98 frag->data_bit_padding = 0;
99}
100
101static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
102 CodedBitstreamFragment *frag)
103{
104 int err, i, j;
105
106 for (i = 0; i < frag->nb_units; i++) {
107 if (ctx->decompose_unit_types) {
108 for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
109 if (ctx->decompose_unit_types[j] == frag->units[i].type)
110 break;
111 }
112 if (j >= ctx->nb_decompose_unit_types)
113 continue;
114 }
115
116 err = ctx->codec->read_unit(ctx, &frag->units[i]);
117 if (err == AVERROR(ENOSYS)) {
118 av_log(ctx->log_ctx, AV_LOG_WARNING,
119 "Decomposition unimplemented for unit %d "
120 "(type %d).\n", i, frag->units[i].type);
121 } else if (err < 0) {
122 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
123 "(type %d).\n", i, frag->units[i].type);
124 return err;
125 }
126 }
127
128 return 0;
129}
130
131int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
132 CodedBitstreamFragment *frag,
133 const AVCodecParameters *par)
134{
135 int err;
136
137 memset(frag, 0, sizeof(*frag));
138
139 frag->data = par->extradata;
140 frag->data_size = par->extradata_size;
141
142 err = ctx->codec->split_fragment(ctx, frag, 1);
143 if (err < 0)
144 return err;
145
146 frag->data = NULL;
147 frag->data_size = 0;
148
149 return cbs_read_fragment_content(ctx, frag);
150}
151
152int ff_cbs_read_packet(CodedBitstreamContext *ctx,
153 CodedBitstreamFragment *frag,
154 const AVPacket *pkt)
155{
156 int err;
157
158 memset(frag, 0, sizeof(*frag));
159
160 frag->data = pkt->data;
161 frag->data_size = pkt->size;
162
163 err = ctx->codec->split_fragment(ctx, frag, 0);
164 if (err < 0)
165 return err;
166
167 frag->data = NULL;
168 frag->data_size = 0;
169
170 return cbs_read_fragment_content(ctx, frag);
171}
172
173int ff_cbs_read(CodedBitstreamContext *ctx,
174 CodedBitstreamFragment *frag,
175 const uint8_t *data, size_t size)
176{
177 int err;
178
179 memset(frag, 0, sizeof(*frag));
180
181 // (We won't write to this during split.)
182 frag->data = (uint8_t*)data;
183 frag->data_size = size;
184
185 err = ctx->codec->split_fragment(ctx, frag, 0);
186 if (err < 0)
187 return err;
188
189 frag->data = NULL;
190 frag->data_size = 0;
191
192 return cbs_read_fragment_content(ctx, frag);
193}
194
195
196int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
197 CodedBitstreamFragment *frag)
198{
199 int err, i;
200
201 for (i = 0; i < frag->nb_units; i++) {
202 if (!frag->units[i].content)
203 continue;
204
205 err = ctx->codec->write_unit(ctx, &frag->units[i]);
206 if (err < 0) {
207 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
208 "(type %d).\n", i, frag->units[i].type);
209 return err;
210 }
211 }
212
213 err = ctx->codec->assemble_fragment(ctx, frag);
214 if (err < 0) {
215 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
216 return err;
217 }
218
219 return 0;
220}
221
222int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
223 AVCodecParameters *par,
224 CodedBitstreamFragment *frag)
225{
226 int err;
227
228 err = ff_cbs_write_fragment_data(ctx, frag);
229 if (err < 0)
230 return err;
231
232 av_freep(&par->extradata);
233
234 par->extradata = av_malloc(frag->data_size +
235 AV_INPUT_BUFFER_PADDING_SIZE);
236 if (!par->extradata)
237 return AVERROR(ENOMEM);
238
239 memcpy(par->extradata, frag->data, frag->data_size);
240 memset(par->extradata + frag->data_size, 0,
241 AV_INPUT_BUFFER_PADDING_SIZE);
242 par->extradata_size = frag->data_size;
243
244 return 0;
245}
246
247int ff_cbs_write_packet(CodedBitstreamContext *ctx,
248 AVPacket *pkt,
249 CodedBitstreamFragment *frag)
250{
251 int err;
252
253 err = ff_cbs_write_fragment_data(ctx, frag);
254 if (err < 0)
255 return err;
256
257 av_new_packet(pkt, frag->data_size);
258 if (err < 0)
259 return err;
260
261 memcpy(pkt->data, frag->data, frag->data_size);
262 pkt->size = frag->data_size;
263
264 return 0;
265}
266
267
268void ff_cbs_trace_header(CodedBitstreamContext *ctx,
269 const char *name)
270{
271 if (!ctx->trace_enable)
272 return;
273
274 av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
275}
276
277void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
278 const char *name, const char *bits,
279 int64_t value)
280{
281 size_t name_len, bits_len;
282 int pad;
283
284 if (!ctx->trace_enable)
285 return;
286
287 av_assert0(value >= INT_MIN && value <= UINT32_MAX);
288
289 name_len = strlen(name);
290 bits_len = strlen(bits);
291
292 if (name_len + bits_len > 60)
293 pad = bits_len + 2;
294 else
295 pad = 61 - name_len;
296
297 av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
298 position, name, pad, bits, value);
299}
300
301int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc,
302 int width, const char *name, uint32_t *write_to,
303 uint32_t range_min, uint32_t range_max)
304{
305 uint32_t value;
306 int position;
307
308 av_assert0(width <= 32);
309
310 if (ctx->trace_enable)
311 position = bitstream_tell(bc);
312
313 value = bitstream_read(bc, width);
314
315 if (ctx->trace_enable) {
316 char bits[33];
317 int i;
318 for (i = 0; i < width; i++)
319 bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
320 bits[i] = 0;
321
322 ff_cbs_trace_syntax_element(ctx, position, name, bits, value);
323 }
324
325 if (value < range_min || value > range_max) {
326 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
327 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
328 name, value, range_min, range_max);
329 return AVERROR_INVALIDDATA;
330 }
331
332 *write_to = value;
333 return 0;
334}
335
336int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
337 int width, const char *name, uint32_t value,
338 uint32_t range_min, uint32_t range_max)
339{
340 av_assert0(width <= 32);
341
342 if (value < range_min || value > range_max) {
343 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
344 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
345 name, value, range_min, range_max);
346 return AVERROR_INVALIDDATA;
347 }
348
349 if (put_bits_left(pbc) < width)
350 return AVERROR(ENOSPC);
351
352 if (ctx->trace_enable) {
353 char bits[33];
354 int i;
355 for (i = 0; i < width; i++)
356 bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
357 bits[i] = 0;
358
359 ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value);
360 }
361
362 if (width < 32)
363 put_bits(pbc, width, value);
364 else
365 put_bits32(pbc, value);
366
367 return 0;
368}
369
370
371static int cbs_insert_unit(CodedBitstreamContext *ctx,
372 CodedBitstreamFragment *frag,
373 int position)
374{
375 CodedBitstreamUnit *units;
376
377 units = av_malloc_array(frag->nb_units + 1, sizeof(*units));
378 if (!units)
379 return AVERROR(ENOMEM);
380
381 if (position > 0)
382 memcpy(units, frag->units, position * sizeof(*units));
383 if (position < frag->nb_units)
384 memcpy(units + position + 1, frag->units + position,
385 (frag->nb_units - position) * sizeof(*units));
386
387 memset(units + position, 0, sizeof(*units));
388
389 av_freep(&frag->units);
390 frag->units = units;
391 ++frag->nb_units;
392
393 return 0;
394}
395
396int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
397 CodedBitstreamFragment *frag,
398 int position, uint32_t type,
399 void *content)
400{
401 int err;
402
403 if (position == -1)
404 position = frag->nb_units;
405 av_assert0(position >= 0 && position <= frag->nb_units);
406
407 err = cbs_insert_unit(ctx, frag, position);
408 if (err < 0)
409 return err;
410
411 frag->units[position].type = type;
412 frag->units[position].content = content;
413 frag->units[position].content_external = 1;
414
415 return 0;
416}
417
418int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
419 CodedBitstreamFragment *frag,
420 int position, uint32_t type,
421 uint8_t *data, size_t data_size)
422{
423 int err;
424
425 if (position == -1)
426 position = frag->nb_units;
427 av_assert0(position >= 0 && position <= frag->nb_units);
428
429 err = cbs_insert_unit(ctx, frag, position);
430 if (err < 0)
431 return err;
432
433 frag->units[position].type = type;
434 frag->units[position].data = data;
435 frag->units[position].data_size = data_size;
436
437 return 0;
438}
439
440int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
441 CodedBitstreamFragment *frag,
442 int position)
443{
444 if (position < 0 || position >= frag->nb_units)
445 return AVERROR(EINVAL);
446
447 cbs_unit_uninit(ctx, &frag->units[position]);
448
449 --frag->nb_units;
450
451 if (frag->nb_units == 0) {
452 av_freep(&frag->units);
453
454 } else {
455 memmove(frag->units + position,
456 frag->units + position + 1,
457 (frag->nb_units - position) * sizeof(*frag->units));
458
459 // Don't bother reallocating the unit array.
460 }
461
462 return 0;
463}