LCOV - code coverage report
Current view: top level - libavcodec - cbs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 182 304 59.9 %
Date: 2018-05-20 11:54:08 Functions: 18 22 81.8 %

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

Generated by: LCOV version 1.13