]> git.sesse.net Git - ffmpeg/blob - libavcodec/cbs.c
cbs: Fragment/unit data is always reference counted
[ffmpeg] / libavcodec / cbs.c
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 <string.h>
20
21 #include "config.h"
22
23 #include "libavutil/avassert.h"
24 #include "libavutil/buffer.h"
25 #include "libavutil/common.h"
26
27 #include "cbs.h"
28 #include "cbs_internal.h"
29
30
31 static const CodedBitstreamType *cbs_type_table[] = {
32 #if CONFIG_CBS_H264
33     &ff_cbs_type_h264,
34 #endif
35 #if CONFIG_CBS_H265
36     &ff_cbs_type_h265,
37 #endif
38 #if CONFIG_CBS_MPEG2
39     &ff_cbs_type_mpeg2,
40 #endif
41 };
42
43 const enum AVCodecID ff_cbs_all_codec_ids[] = {
44 #if CONFIG_CBS_H264
45     AV_CODEC_ID_H264,
46 #endif
47 #if CONFIG_CBS_H265
48     AV_CODEC_ID_H265,
49 #endif
50 #if CONFIG_CBS_MPEG2
51     AV_CODEC_ID_MPEG2VIDEO,
52 #endif
53     AV_CODEC_ID_NONE
54 };
55
56 int ff_cbs_init(CodedBitstreamContext **ctx_ptr,
57                 enum AVCodecID codec_id, void *log_ctx)
58 {
59     CodedBitstreamContext *ctx;
60     const CodedBitstreamType *type;
61     int i;
62
63     type = NULL;
64     for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
65         if (cbs_type_table[i]->codec_id == codec_id) {
66             type = cbs_type_table[i];
67             break;
68         }
69     }
70     if (!type)
71         return AVERROR(EINVAL);
72
73     ctx = av_mallocz(sizeof(*ctx));
74     if (!ctx)
75         return AVERROR(ENOMEM);
76
77     ctx->log_ctx = log_ctx;
78     ctx->codec   = type;
79
80     ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
81     if (!ctx->priv_data) {
82         av_freep(&ctx);
83         return AVERROR(ENOMEM);
84     }
85
86     ctx->decompose_unit_types = NULL;
87
88     ctx->trace_enable = 0;
89     ctx->trace_level  = AV_LOG_TRACE;
90
91     *ctx_ptr = ctx;
92     return 0;
93 }
94
95 void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
96 {
97     CodedBitstreamContext *ctx = *ctx_ptr;
98
99     if (!ctx)
100         return;
101
102     if (ctx->codec && ctx->codec->close)
103         ctx->codec->close(ctx);
104
105     av_freep(&ctx->priv_data);
106     av_freep(ctx_ptr);
107 }
108
109 static void cbs_unit_uninit(CodedBitstreamContext *ctx,
110                             CodedBitstreamUnit *unit)
111 {
112     av_buffer_unref(&unit->content_ref);
113     unit->content = NULL;
114
115     av_buffer_unref(&unit->data_ref);
116     unit->data             = NULL;
117     unit->data_size        = 0;
118     unit->data_bit_padding = 0;
119 }
120
121 void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
122                             CodedBitstreamFragment *frag)
123 {
124     int i;
125
126     for (i = 0; i < frag->nb_units; i++)
127         cbs_unit_uninit(ctx, &frag->units[i]);
128     av_freep(&frag->units);
129     frag->nb_units = 0;
130
131     av_buffer_unref(&frag->data_ref);
132     frag->data             = NULL;
133     frag->data_size        = 0;
134     frag->data_bit_padding = 0;
135 }
136
137 static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
138                                      CodedBitstreamFragment *frag)
139 {
140     int err, i, j;
141
142     for (i = 0; i < frag->nb_units; i++) {
143         CodedBitstreamUnit *unit = &frag->units[i];
144
145         if (ctx->decompose_unit_types) {
146             for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
147                 if (ctx->decompose_unit_types[j] == unit->type)
148                     break;
149             }
150             if (j >= ctx->nb_decompose_unit_types)
151                 continue;
152         }
153
154         av_buffer_unref(&unit->content_ref);
155         unit->content = NULL;
156
157         av_assert0(unit->data && unit->data_ref);
158
159         err = ctx->codec->read_unit(ctx, unit);
160         if (err == AVERROR(ENOSYS)) {
161             av_log(ctx->log_ctx, AV_LOG_VERBOSE,
162                    "Decomposition unimplemented for unit %d "
163                    "(type %"PRIu32").\n", i, unit->type);
164         } else if (err < 0) {
165             av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
166                    "(type %"PRIu32").\n", i, unit->type);
167             return err;
168         }
169     }
170
171     return 0;
172 }
173
174 static int cbs_fill_fragment_data(CodedBitstreamContext *ctx,
175                                   CodedBitstreamFragment *frag,
176                                   const uint8_t *data, size_t size)
177 {
178     av_assert0(!frag->data && !frag->data_ref);
179
180     frag->data_ref =
181         av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
182     if (!frag->data_ref)
183         return AVERROR(ENOMEM);
184
185     frag->data      = frag->data_ref->data;
186     frag->data_size = size;
187
188     memcpy(frag->data, data, size);
189     memset(frag->data + size, 0,
190            AV_INPUT_BUFFER_PADDING_SIZE);
191
192     return 0;
193 }
194
195 int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
196                           CodedBitstreamFragment *frag,
197                           const AVCodecParameters *par)
198 {
199     int err;
200
201     memset(frag, 0, sizeof(*frag));
202
203     err = cbs_fill_fragment_data(ctx, frag, par->extradata,
204                                  par->extradata_size);
205     if (err < 0)
206         return err;
207
208     err = ctx->codec->split_fragment(ctx, frag, 1);
209     if (err < 0)
210         return err;
211
212     return cbs_read_fragment_content(ctx, frag);
213 }
214
215 int ff_cbs_read_packet(CodedBitstreamContext *ctx,
216                        CodedBitstreamFragment *frag,
217                        const AVPacket *pkt)
218 {
219     int err;
220
221     memset(frag, 0, sizeof(*frag));
222
223     if (pkt->buf) {
224         frag->data_ref = av_buffer_ref(pkt->buf);
225         if (!frag->data_ref)
226             return AVERROR(ENOMEM);
227
228         frag->data      = pkt->data;
229         frag->data_size = pkt->size;
230
231     } else {
232         err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size);
233         if (err < 0)
234             return err;
235     }
236
237     err = ctx->codec->split_fragment(ctx, frag, 0);
238     if (err < 0)
239         return err;
240
241     return cbs_read_fragment_content(ctx, frag);
242 }
243
244 int ff_cbs_read(CodedBitstreamContext *ctx,
245                 CodedBitstreamFragment *frag,
246                 const uint8_t *data, size_t size)
247 {
248     int err;
249
250     memset(frag, 0, sizeof(*frag));
251
252     err = cbs_fill_fragment_data(ctx, frag, data, size);
253     if (err < 0)
254         return err;
255
256     err = ctx->codec->split_fragment(ctx, frag, 0);
257     if (err < 0)
258         return err;
259
260     return cbs_read_fragment_content(ctx, frag);
261 }
262
263
264 int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
265                                CodedBitstreamFragment *frag)
266 {
267     int err, i;
268
269     for (i = 0; i < frag->nb_units; i++) {
270         CodedBitstreamUnit *unit = &frag->units[i];
271
272         if (!unit->content)
273             continue;
274
275         av_buffer_unref(&unit->data_ref);
276         unit->data = NULL;
277
278         err = ctx->codec->write_unit(ctx, unit);
279         if (err < 0) {
280             av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
281                    "(type %"PRIu32").\n", i, unit->type);
282             return err;
283         }
284         av_assert0(unit->data && unit->data_ref);
285     }
286
287     av_buffer_unref(&frag->data_ref);
288     frag->data = NULL;
289
290     err = ctx->codec->assemble_fragment(ctx, frag);
291     if (err < 0) {
292         av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
293         return err;
294     }
295     av_assert0(frag->data && frag->data_ref);
296
297     return 0;
298 }
299
300 int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
301                            AVCodecParameters *par,
302                            CodedBitstreamFragment *frag)
303 {
304     int err;
305
306     err = ff_cbs_write_fragment_data(ctx, frag);
307     if (err < 0)
308         return err;
309
310     av_freep(&par->extradata);
311
312     par->extradata = av_malloc(frag->data_size +
313                                AV_INPUT_BUFFER_PADDING_SIZE);
314     if (!par->extradata)
315         return AVERROR(ENOMEM);
316
317     memcpy(par->extradata, frag->data, frag->data_size);
318     memset(par->extradata + frag->data_size, 0,
319            AV_INPUT_BUFFER_PADDING_SIZE);
320     par->extradata_size = frag->data_size;
321
322     return 0;
323 }
324
325 int ff_cbs_write_packet(CodedBitstreamContext *ctx,
326                         AVPacket *pkt,
327                         CodedBitstreamFragment *frag)
328 {
329     AVBufferRef *buf;
330     int err;
331
332     err = ff_cbs_write_fragment_data(ctx, frag);
333     if (err < 0)
334         return err;
335
336     buf = av_buffer_ref(frag->data_ref);
337     if (!buf)
338         return AVERROR(ENOMEM);
339
340     av_init_packet(pkt);
341     pkt->buf  = buf;
342     pkt->data = frag->data;
343     pkt->size = frag->data_size;
344
345     return 0;
346 }
347
348
349 void ff_cbs_trace_header(CodedBitstreamContext *ctx,
350                          const char *name)
351 {
352     if (!ctx->trace_enable)
353         return;
354
355     av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
356 }
357
358 void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
359                                  const char *name, const char *bits,
360                                  int64_t value)
361 {
362     size_t name_len, bits_len;
363     int pad;
364
365     if (!ctx->trace_enable)
366         return;
367
368     av_assert0(value >= INT_MIN && value <= UINT32_MAX);
369
370     name_len = strlen(name);
371     bits_len = strlen(bits);
372
373     if (name_len + bits_len > 60)
374         pad = bits_len + 2;
375     else
376         pad = 61 - name_len;
377
378     av_log(ctx->log_ctx, ctx->trace_level, "%-10d  %s%*s = %"PRId64"\n",
379            position, name, pad, bits, value);
380 }
381
382 int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
383                          int width, const char *name, uint32_t *write_to,
384                          uint32_t range_min, uint32_t range_max)
385 {
386     uint32_t value;
387     int position;
388
389     av_assert0(width > 0 && width <= 32);
390
391     if (get_bits_left(gbc) < width) {
392         av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
393                "%s: bitstream ended.\n", name);
394         return AVERROR_INVALIDDATA;
395     }
396
397     if (ctx->trace_enable)
398         position = get_bits_count(gbc);
399
400     value = get_bits_long(gbc, width);
401
402     if (ctx->trace_enable) {
403         char bits[33];
404         int i;
405         for (i = 0; i < width; i++)
406             bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
407         bits[i] = 0;
408
409         ff_cbs_trace_syntax_element(ctx, position, name, bits, value);
410     }
411
412     if (value < range_min || value > range_max) {
413         av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
414                "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
415                name, value, range_min, range_max);
416         return AVERROR_INVALIDDATA;
417     }
418
419     *write_to = value;
420     return 0;
421 }
422
423 int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
424                           int width, const char *name, uint32_t value,
425                           uint32_t range_min, uint32_t range_max)
426 {
427     av_assert0(width > 0 && width <= 32);
428
429     if (value < range_min || value > range_max) {
430         av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
431                "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
432                name, value, range_min, range_max);
433         return AVERROR_INVALIDDATA;
434     }
435
436     if (put_bits_left(pbc) < width)
437         return AVERROR(ENOSPC);
438
439     if (ctx->trace_enable) {
440         char bits[33];
441         int i;
442         for (i = 0; i < width; i++)
443             bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
444         bits[i] = 0;
445
446         ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value);
447     }
448
449     if (width < 32)
450         put_bits(pbc, width, value);
451     else
452         put_bits32(pbc, value);
453
454     return 0;
455 }
456
457
458 int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
459                               CodedBitstreamUnit *unit,
460                               size_t size,
461                               void (*free)(void *opaque, uint8_t *data))
462 {
463     av_assert0(!unit->content && !unit->content_ref);
464
465     unit->content = av_mallocz(size);
466     if (!unit->content)
467         return AVERROR(ENOMEM);
468
469     unit->content_ref = av_buffer_create(unit->content, size,
470                                          free, ctx, 0);
471     if (!unit->content_ref) {
472         av_freep(&unit->content);
473         return AVERROR(ENOMEM);
474     }
475
476     return 0;
477 }
478
479 int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx,
480                            CodedBitstreamUnit *unit,
481                            size_t size)
482 {
483     av_assert0(!unit->data && !unit->data_ref);
484
485     unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
486     if (!unit->data_ref)
487         return AVERROR(ENOMEM);
488
489     unit->data      = unit->data_ref->data;
490     unit->data_size = size;
491
492     memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
493
494     return 0;
495 }
496
497 static int cbs_insert_unit(CodedBitstreamContext *ctx,
498                            CodedBitstreamFragment *frag,
499                            int position)
500 {
501     CodedBitstreamUnit *units;
502
503     units = av_malloc_array(frag->nb_units + 1, sizeof(*units));
504     if (!units)
505         return AVERROR(ENOMEM);
506
507     if (position > 0)
508         memcpy(units, frag->units, position * sizeof(*units));
509     if (position < frag->nb_units)
510         memcpy(units + position + 1, frag->units + position,
511                (frag->nb_units - position) * sizeof(*units));
512
513     memset(units + position, 0, sizeof(*units));
514
515     av_freep(&frag->units);
516     frag->units = units;
517     ++frag->nb_units;
518
519     return 0;
520 }
521
522 int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
523                                CodedBitstreamFragment *frag,
524                                int position,
525                                CodedBitstreamUnitType type,
526                                void *content,
527                                AVBufferRef *content_buf)
528 {
529     CodedBitstreamUnit *unit;
530     AVBufferRef *content_ref;
531     int err;
532
533     if (position == -1)
534         position = frag->nb_units;
535     av_assert0(position >= 0 && position <= frag->nb_units);
536
537     if (content_buf) {
538         content_ref = av_buffer_ref(content_buf);
539         if (!content_ref)
540             return AVERROR(ENOMEM);
541     } else {
542         content_ref = NULL;
543     }
544
545     err = cbs_insert_unit(ctx, frag, position);
546     if (err < 0) {
547         av_buffer_unref(&content_ref);
548         return err;
549     }
550
551     unit = &frag->units[position];
552     unit->type        = type;
553     unit->content     = content;
554     unit->content_ref = content_ref;
555
556     return 0;
557 }
558
559 int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
560                             CodedBitstreamFragment *frag,
561                             int position,
562                             CodedBitstreamUnitType type,
563                             uint8_t *data, size_t data_size,
564                             AVBufferRef *data_buf)
565 {
566     CodedBitstreamUnit *unit;
567     AVBufferRef *data_ref;
568     int err;
569
570     if (position == -1)
571         position = frag->nb_units;
572     av_assert0(position >= 0 && position <= frag->nb_units);
573
574     if (data_buf)
575         data_ref = av_buffer_ref(data_buf);
576     else
577         data_ref = av_buffer_create(data, data_size, NULL, NULL, 0);
578     if (!data_ref)
579         return AVERROR(ENOMEM);
580
581     err = cbs_insert_unit(ctx, frag, position);
582     if (err < 0) {
583         av_buffer_unref(&data_ref);
584         return err;
585     }
586
587     unit = &frag->units[position];
588     unit->type      = type;
589     unit->data      = data;
590     unit->data_size = data_size;
591     unit->data_ref  = data_ref;
592
593     return 0;
594 }
595
596 int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
597                        CodedBitstreamFragment *frag,
598                        int position)
599 {
600     if (position < 0 || position >= frag->nb_units)
601         return AVERROR(EINVAL);
602
603     cbs_unit_uninit(ctx, &frag->units[position]);
604
605     --frag->nb_units;
606
607     if (frag->nb_units == 0) {
608         av_freep(&frag->units);
609
610     } else {
611         memmove(frag->units + position,
612                 frag->units + position + 1,
613                 (frag->nb_units - position) * sizeof(*frag->units));
614
615         // Don't bother reallocating the unit array.
616     }
617
618     return 0;
619 }