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