LCOV - code coverage report
Current view: top level - libavcodec - cbs_vp9.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 175 245 71.4 %
Date: 2018-05-20 11:54:08 Functions: 12 12 100.0 %

          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 "libavutil/avassert.h"
      20             : 
      21             : #include "cbs.h"
      22             : #include "cbs_internal.h"
      23             : #include "cbs_vp9.h"
      24             : #include "internal.h"
      25             : 
      26             : 
      27          50 : static int cbs_vp9_read_s(CodedBitstreamContext *ctx, GetBitContext *gbc,
      28             :                           int width, const char *name,
      29             :                           const int *subscripts, int32_t *write_to)
      30             : {
      31             :     uint32_t magnitude;
      32             :     int position, sign;
      33             :     int32_t value;
      34             : 
      35          50 :     if (ctx->trace_enable)
      36           0 :         position = get_bits_count(gbc);
      37             : 
      38          50 :     if (get_bits_left(gbc) < width + 1) {
      39           0 :         av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid signed value at "
      40             :                "%s: bitstream ended.\n", name);
      41           0 :         return AVERROR_INVALIDDATA;
      42             :     }
      43             : 
      44          50 :     magnitude = get_bits(gbc, width);
      45          50 :     sign      = get_bits1(gbc);
      46          50 :     value     = sign ? -(int32_t)magnitude : magnitude;
      47             : 
      48          50 :     if (ctx->trace_enable) {
      49             :         char bits[33];
      50             :         int i;
      51           0 :         for (i = 0; i < width; i++)
      52           0 :             bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0';
      53           0 :         bits[i] = sign ? '1' : '0';
      54           0 :         bits[i + 1] = 0;
      55             : 
      56           0 :         ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
      57             :                                     bits, value);
      58             :     }
      59             : 
      60          50 :     *write_to = value;
      61          50 :     return 0;
      62             : }
      63             : 
      64          50 : static int cbs_vp9_write_s(CodedBitstreamContext *ctx, PutBitContext *pbc,
      65             :                            int width, const char *name,
      66             :                            const int *subscripts, int32_t value)
      67             : {
      68             :     uint32_t magnitude;
      69             :     int sign;
      70             : 
      71          50 :     if (put_bits_left(pbc) < width + 1)
      72           0 :         return AVERROR(ENOSPC);
      73             : 
      74          50 :     sign      = value < 0;
      75          50 :     magnitude = sign ? -value : value;
      76             : 
      77          50 :     if (ctx->trace_enable) {
      78             :         char bits[33];
      79             :         int i;
      80           0 :         for (i = 0; i < width; i++)
      81           0 :             bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0';
      82           0 :         bits[i] = sign ? '1' : '0';
      83           0 :         bits[i + 1] = 0;
      84             : 
      85           0 :         ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
      86             :                                     name, subscripts, bits, value);
      87             :     }
      88             : 
      89          50 :     put_bits(pbc, width, magnitude);
      90          50 :     put_bits(pbc, 1, sign);
      91             : 
      92          50 :     return 0;
      93             : }
      94             : 
      95         362 : static int cbs_vp9_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc,
      96             :                                   uint32_t range_min, uint32_t range_max,
      97             :                                   const char *name, uint32_t *write_to)
      98             : {
      99             :     uint32_t value;
     100             :     int position, i;
     101             :     char bits[8];
     102             : 
     103         362 :     av_assert0(range_min <= range_max && range_max - range_min < sizeof(bits) - 1);
     104         362 :     if (ctx->trace_enable)
     105           0 :         position = get_bits_count(gbc);
     106             : 
     107         728 :     for (i = 0, value = range_min; value < range_max;) {
     108         187 :         if (get_bits_left(gbc) < 1) {
     109           0 :             av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid increment value at "
     110             :                    "%s: bitstream ended.\n", name);
     111           0 :             return AVERROR_INVALIDDATA;
     112             :         }
     113         187 :         if (get_bits1(gbc)) {
     114           4 :             bits[i++] = '1';
     115           4 :             ++value;
     116             :         } else {
     117         183 :             bits[i++] = '0';
     118         183 :             break;
     119             :         }
     120             :     }
     121             : 
     122         362 :     if (ctx->trace_enable) {
     123           0 :         bits[i] = 0;
     124           0 :         ff_cbs_trace_syntax_element(ctx, position, name, NULL, bits, value);
     125             :     }
     126             : 
     127         362 :     *write_to = value;
     128         362 :     return 0;
     129             : }
     130             : 
     131         362 : static int cbs_vp9_write_increment(CodedBitstreamContext *ctx, PutBitContext *pbc,
     132             :                                    uint32_t range_min, uint32_t range_max,
     133             :                                    const char *name, uint32_t value)
     134             : {
     135             :     int len;
     136             : 
     137         362 :     av_assert0(range_min <= range_max && range_max - range_min < 8);
     138         362 :     if (value < range_min || value > range_max) {
     139           0 :         av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
     140             :                "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
     141             :                name, value, range_min, range_max);
     142           0 :         return AVERROR_INVALIDDATA;
     143             :     }
     144             : 
     145         362 :     if (value == range_max)
     146         179 :         len = range_max - range_min;
     147             :     else
     148         183 :         len = value - range_min + 1;
     149         362 :     if (put_bits_left(pbc) < len)
     150           0 :         return AVERROR(ENOSPC);
     151             : 
     152         362 :     if (ctx->trace_enable) {
     153             :         char bits[8];
     154             :         int i;
     155           0 :         for (i = 0; i < len; i++) {
     156           0 :             if (range_min + i == value)
     157           0 :                 bits[i] = '0';
     158             :             else
     159           0 :                 bits[i] = '1';
     160             :         }
     161           0 :         bits[i] = 0;
     162           0 :         ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
     163             :                                     name, NULL, bits, value);
     164             :     }
     165             : 
     166         362 :     if (len > 0)
     167         183 :         put_bits(pbc, len, (1 << len) - 1 - (value != range_max));
     168             : 
     169         362 :     return 0;
     170             : }
     171             : 
     172          27 : static int cbs_vp9_read_le(CodedBitstreamContext *ctx, GetBitContext *gbc,
     173             :                            int width, const char *name,
     174             :                            const int *subscripts, uint32_t *write_to)
     175             : {
     176             :     uint32_t value;
     177             :     int position, b;
     178             : 
     179          27 :     av_assert0(width % 8 == 0);
     180             : 
     181          27 :     if (ctx->trace_enable)
     182           0 :         position = get_bits_count(gbc);
     183             : 
     184          27 :     if (get_bits_left(gbc) < width) {
     185           0 :         av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid le value at "
     186             :                "%s: bitstream ended.\n", name);
     187           0 :         return AVERROR_INVALIDDATA;
     188             :     }
     189             : 
     190          27 :     value = 0;
     191          81 :     for (b = 0; b < width; b += 8)
     192          54 :         value |= get_bits(gbc, 8) << b;
     193             : 
     194          27 :     if (ctx->trace_enable) {
     195             :         char bits[33];
     196             :         int i;
     197           0 :         for (b = 0; b < width; b += 8)
     198           0 :             for (i = 0; i < 8; i++)
     199           0 :                 bits[b + i] = value >> (b + i) & 1 ? '1' : '0';
     200           0 :         bits[b] = 0;
     201             : 
     202           0 :         ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
     203             :                                     bits, value);
     204             :     }
     205             : 
     206          27 :     *write_to = value;
     207          27 :     return 0;
     208             : }
     209             : 
     210          27 : static int cbs_vp9_write_le(CodedBitstreamContext *ctx, PutBitContext *pbc,
     211             :                             int width, const char *name,
     212             :                             const int *subscripts, uint32_t value)
     213             : {
     214             :     int b;
     215             : 
     216          27 :     av_assert0(width % 8 == 0);
     217             : 
     218          27 :     if (put_bits_left(pbc) < width)
     219           0 :         return AVERROR(ENOSPC);
     220             : 
     221          27 :     if (ctx->trace_enable) {
     222             :         char bits[33];
     223             :         int i;
     224           0 :         for (b = 0; b < width; b += 8)
     225           0 :             for (i = 0; i < 8; i++)
     226           0 :                 bits[b + i] = value >> (b + i) & 1 ? '1' : '0';
     227           0 :         bits[b] = 0;
     228             : 
     229           0 :         ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
     230             :                                     name, subscripts, bits, value);
     231             :     }
     232             : 
     233          81 :     for (b = 0; b < width; b += 8)
     234          54 :         put_bits(pbc, 8, value >> b & 0xff);
     235             : 
     236          27 :     return 0;
     237             : }
     238             : 
     239             : #define HEADER(name) do { \
     240             :         ff_cbs_trace_header(ctx, name); \
     241             :     } while (0)
     242             : 
     243             : #define CHECK(call) do { \
     244             :         err = (call); \
     245             :         if (err < 0) \
     246             :             return err; \
     247             :     } while (0)
     248             : 
     249             : #define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
     250             : #define FUNC_VP9(rw, name) FUNC_NAME(rw, vp9, name)
     251             : #define FUNC(name) FUNC_VP9(READWRITE, name)
     252             : 
     253             : #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
     254             : 
     255             : #define f(width, name) \
     256             :         xf(width, name, current->name, 0)
     257             : #define s(width, name) \
     258             :         xs(width, name, current->name, 0)
     259             : #define fs(width, name, subs, ...) \
     260             :         xf(width, name, current->name, subs, __VA_ARGS__)
     261             : #define ss(width, name, subs, ...) \
     262             :         xs(width, name, current->name, subs, __VA_ARGS__)
     263             : 
     264             : 
     265             : #define READ
     266             : #define READWRITE read
     267             : #define RWContext GetBitContext
     268             : 
     269             : #define xf(width, name, var, subs, ...) do { \
     270             :         uint32_t value = 0; \
     271             :         CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
     272             :                                    SUBSCRIPTS(subs, __VA_ARGS__), \
     273             :                                    &value, 0, (1 << width) - 1)); \
     274             :         var = value; \
     275             :     } while (0)
     276             : #define xs(width, name, var, subs, ...) do { \
     277             :         int32_t value = 0; \
     278             :         CHECK(cbs_vp9_read_s(ctx, rw, width, #name, \
     279             :                              SUBSCRIPTS(subs, __VA_ARGS__), &value)); \
     280             :         var = value; \
     281             :     } while (0)
     282             : 
     283             : 
     284             : #define increment(name, min, max) do { \
     285             :         uint32_t value = 0; \
     286             :         CHECK(cbs_vp9_read_increment(ctx, rw, min, max, #name, &value)); \
     287             :         current->name = value; \
     288             :     } while (0)
     289             : 
     290             : #define fle(width, name, subs, ...) do { \
     291             :         CHECK(cbs_vp9_read_le(ctx, rw, width, #name, \
     292             :                               SUBSCRIPTS(subs, __VA_ARGS__), &current->name)); \
     293             :     } while (0)
     294             : 
     295             : #define delta_q(name) do { \
     296             :         uint8_t delta_coded; \
     297             :         int8_t delta_q; \
     298             :         xf(1, name.delta_coded, delta_coded, 0); \
     299             :         if (delta_coded) \
     300             :             xs(4, name.delta_q, delta_q, 0); \
     301             :         else \
     302             :             delta_q = 0; \
     303             :         current->name = delta_q; \
     304             :     } while (0)
     305             : 
     306             : #define prob(name, subs, ...) do { \
     307             :         uint8_t prob_coded; \
     308             :         int8_t prob; \
     309             :         xf(1, name.prob_coded, prob_coded, subs, __VA_ARGS__); \
     310             :         if (prob_coded) \
     311             :             xf(8, name.prob, prob, subs, __VA_ARGS__); \
     312             :         else \
     313             :             prob = 255; \
     314             :         current->name = prob; \
     315             :     } while (0)
     316             : 
     317             : #define infer(name, value) do { \
     318             :         current->name = value; \
     319             :     } while (0)
     320             : 
     321             : #define byte_alignment(rw) (get_bits_count(rw) % 8)
     322             : 
     323             : #include "cbs_vp9_syntax_template.c"
     324             : 
     325             : #undef READ
     326             : #undef READWRITE
     327             : #undef RWContext
     328             : #undef xf
     329             : #undef xs
     330             : #undef increment
     331             : #undef fle
     332             : #undef delta_q
     333             : #undef prob
     334             : #undef infer
     335             : #undef byte_alignment
     336             : 
     337             : 
     338             : #define WRITE
     339             : #define READWRITE write
     340             : #define RWContext PutBitContext
     341             : 
     342             : #define xf(width, name, var, subs, ...) do { \
     343             :         CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
     344             :                                     SUBSCRIPTS(subs, __VA_ARGS__), \
     345             :                                     var, 0, (1 << width) - 1)); \
     346             :     } while (0)
     347             : #define xs(width, name, var, subs, ...) do { \
     348             :         CHECK(cbs_vp9_write_s(ctx, rw, width, #name, \
     349             :                               SUBSCRIPTS(subs, __VA_ARGS__), var)); \
     350             :     } while (0)
     351             : 
     352             : #define increment(name, min, max) do { \
     353             :         CHECK(cbs_vp9_write_increment(ctx, rw, min, max, #name, current->name)); \
     354             :     } while (0)
     355             : 
     356             : #define fle(width, name, subs, ...) do { \
     357             :         CHECK(cbs_vp9_write_le(ctx, rw, width, #name, \
     358             :                                SUBSCRIPTS(subs, __VA_ARGS__), current->name)); \
     359             :     } while (0)
     360             : 
     361             : #define delta_q(name) do { \
     362             :         xf(1, name.delta_coded, !!current->name, 0); \
     363             :         if (current->name) \
     364             :             xs(4, name.delta_q, current->name, 0); \
     365             :     } while (0)
     366             : 
     367             : #define prob(name, subs, ...) do { \
     368             :         xf(1, name.prob_coded, current->name != 255, subs, __VA_ARGS__); \
     369             :         if (current->name != 255) \
     370             :             xf(8, name.prob, current->name, subs, __VA_ARGS__); \
     371             :     } while (0)
     372             : 
     373             : #define infer(name, value) do { \
     374             :         if (current->name != (value)) { \
     375             :             av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \
     376             :                    "%s does not match inferred value: " \
     377             :                    "%"PRId64", but should be %"PRId64".\n", \
     378             :                    #name, (int64_t)current->name, (int64_t)(value)); \
     379             :         } \
     380             :     } while (0)
     381             : 
     382             : #define byte_alignment(rw) (put_bits_count(rw) % 8)
     383             : 
     384             : #include "cbs_vp9_syntax_template.c"
     385             : 
     386             : #undef READ
     387             : #undef READWRITE
     388             : #undef RWContext
     389             : #undef xf
     390             : #undef xs
     391             : #undef increment
     392             : #undef fle
     393             : #undef delta_q
     394             : #undef prob
     395             : #undef infer
     396             : #undef byte_alignment
     397             : 
     398             : 
     399         183 : static int cbs_vp9_split_fragment(CodedBitstreamContext *ctx,
     400             :                                   CodedBitstreamFragment *frag,
     401             :                                   int header)
     402             : {
     403             :     uint8_t superframe_header;
     404             :     int err;
     405             : 
     406             :     // Last byte in the packet.
     407         183 :     superframe_header = frag->data[frag->data_size - 1];
     408             : 
     409         183 :     if ((superframe_header & 0xe0) == 0xc0) {
     410             :         VP9RawSuperframeIndex sfi;
     411             :         GetBitContext gbc;
     412             :         size_t index_size, pos;
     413             :         int i;
     414             : 
     415          26 :         index_size = 2 + (((superframe_header & 0x18) >> 3) + 1) *
     416          13 :                           ((superframe_header & 0x07) + 1);
     417             : 
     418          13 :         err = init_get_bits(&gbc, frag->data + frag->data_size - index_size,
     419             :                             8 * index_size);
     420          13 :         if (err < 0)
     421           0 :             return err;
     422             : 
     423          13 :         err = cbs_vp9_read_superframe_index(ctx, &gbc, &sfi);
     424          13 :         if (err < 0)
     425           0 :             return err;
     426             : 
     427          13 :         pos = 0;
     428          40 :         for (i = 0; i <= sfi.frames_in_superframe_minus_1; i++) {
     429          27 :             if (pos + sfi.frame_sizes[i] + index_size > frag->data_size) {
     430           0 :                 av_log(ctx->log_ctx, AV_LOG_ERROR, "Frame %d too large "
     431             :                        "in superframe: %"PRIu32" bytes.\n",
     432             :                        i, sfi.frame_sizes[i]);
     433           0 :                 return AVERROR_INVALIDDATA;
     434             :             }
     435             : 
     436          81 :             err = ff_cbs_insert_unit_data(ctx, frag, -1, 0,
     437          27 :                                           frag->data + pos,
     438          27 :                                           sfi.frame_sizes[i],
     439             :                                           frag->data_ref);
     440          27 :             if (err < 0)
     441           0 :                 return err;
     442             : 
     443          27 :             pos += sfi.frame_sizes[i];
     444             :         }
     445          13 :         if (pos + index_size != frag->data_size) {
     446           0 :             av_log(ctx->log_ctx, AV_LOG_WARNING, "Extra padding at "
     447             :                    "end of superframe: %zu bytes.\n",
     448           0 :                    frag->data_size - (pos + index_size));
     449             :         }
     450             : 
     451          13 :         return 0;
     452             : 
     453             :     } else {
     454         170 :         err = ff_cbs_insert_unit_data(ctx, frag, -1, 0,
     455             :                                       frag->data, frag->data_size,
     456             :                                       frag->data_ref);
     457         170 :         if (err < 0)
     458           0 :             return err;
     459             :     }
     460             : 
     461         170 :     return 0;
     462             : }
     463             : 
     464         197 : static void cbs_vp9_free_frame(void *unit, uint8_t *content)
     465             : {
     466         197 :     VP9RawFrame *frame = (VP9RawFrame*)content;
     467         197 :     av_buffer_unref(&frame->data_ref);
     468         197 :     av_freep(&frame);
     469         197 : }
     470             : 
     471         197 : static int cbs_vp9_read_unit(CodedBitstreamContext *ctx,
     472             :                              CodedBitstreamUnit *unit)
     473             : {
     474             :     VP9RawFrame *frame;
     475             :     GetBitContext gbc;
     476             :     int err, pos;
     477             : 
     478         197 :     err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
     479         197 :     if (err < 0)
     480           0 :         return err;
     481             : 
     482         197 :     err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*frame),
     483             :                                     &cbs_vp9_free_frame);
     484         197 :     if (err < 0)
     485           0 :         return err;
     486         197 :     frame = unit->content;
     487             : 
     488         197 :     err = cbs_vp9_read_frame(ctx, &gbc, frame);
     489         197 :     if (err < 0)
     490           0 :         return err;
     491             : 
     492         197 :     pos = get_bits_count(&gbc);
     493         197 :     av_assert0(pos % 8 == 0);
     494         197 :     pos /= 8;
     495         197 :     av_assert0(pos <= unit->data_size);
     496             : 
     497         197 :     if (pos == unit->data_size) {
     498             :         // No data (e.g. a show-existing-frame frame).
     499             :     } else {
     500         181 :         frame->data_ref = av_buffer_ref(unit->data_ref);
     501         181 :         if (!frame->data_ref)
     502           0 :             return AVERROR(ENOMEM);
     503             : 
     504         181 :         frame->data      = unit->data      + pos;
     505         181 :         frame->data_size = unit->data_size - pos;
     506             :     }
     507             : 
     508         197 :     return 0;
     509             : }
     510             : 
     511         197 : static int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
     512             :                               CodedBitstreamUnit *unit)
     513             : {
     514         197 :     CodedBitstreamVP9Context *priv = ctx->priv_data;
     515         197 :     VP9RawFrame *frame = unit->content;
     516             :     PutBitContext pbc;
     517             :     int err;
     518             : 
     519         197 :     if (!priv->write_buffer) {
     520             :         // Initial write buffer size is 1MB.
     521          14 :         priv->write_buffer_size = 1024 * 1024;
     522             : 
     523          14 :     reallocate_and_try_again:
     524          14 :         err = av_reallocp(&priv->write_buffer, priv->write_buffer_size);
     525          14 :         if (err < 0) {
     526           0 :             av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
     527             :                    "sufficiently large write buffer (last attempt "
     528             :                    "%zu bytes).\n", priv->write_buffer_size);
     529           0 :             return err;
     530             :         }
     531             :     }
     532             : 
     533         197 :     init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size);
     534             : 
     535         197 :     err = cbs_vp9_write_frame(ctx, &pbc, frame);
     536         197 :     if (err == AVERROR(ENOSPC)) {
     537           0 :         priv->write_buffer_size *= 2;
     538           0 :         goto reallocate_and_try_again;
     539             :     }
     540         197 :     if (err < 0)
     541           0 :         return err;
     542             : 
     543             :     // Frame must be byte-aligned.
     544         197 :     av_assert0(put_bits_count(&pbc) % 8 == 0);
     545             : 
     546         197 :     unit->data_size        = put_bits_count(&pbc) / 8;
     547         197 :     unit->data_bit_padding = 0;
     548         197 :     flush_put_bits(&pbc);
     549             : 
     550         197 :     if (frame->data) {
     551         362 :         if (unit->data_size + frame->data_size >
     552         181 :             priv->write_buffer_size) {
     553           0 :             priv->write_buffer_size *= 2;
     554           0 :             goto reallocate_and_try_again;
     555             :         }
     556             : 
     557         362 :         memcpy(priv->write_buffer + unit->data_size,
     558         181 :                frame->data, frame->data_size);
     559         181 :         unit->data_size += frame->data_size;
     560             :     }
     561             : 
     562         197 :     err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size);
     563         197 :     if (err < 0)
     564           0 :         return err;
     565             : 
     566         197 :     memcpy(unit->data, priv->write_buffer, unit->data_size);
     567             : 
     568         197 :     return 0;
     569             : }
     570             : 
     571         183 : static int cbs_vp9_assemble_fragment(CodedBitstreamContext *ctx,
     572             :                                      CodedBitstreamFragment *frag)
     573             : {
     574             :     int err;
     575             : 
     576         183 :     if (frag->nb_units == 1) {
     577             :         // Output is just the content of the single frame.
     578             : 
     579         170 :         CodedBitstreamUnit *frame = &frag->units[0];
     580             : 
     581         170 :         frag->data_ref = av_buffer_ref(frame->data_ref);
     582         170 :         if (!frag->data_ref)
     583           0 :             return AVERROR(ENOMEM);
     584             : 
     585         170 :         frag->data      = frame->data;
     586         170 :         frag->data_size = frame->data_size;
     587             : 
     588             :     } else {
     589             :         // Build superframe out of frames.
     590             : 
     591             :         VP9RawSuperframeIndex sfi;
     592             :         PutBitContext pbc;
     593             :         AVBufferRef *ref;
     594             :         uint8_t *data;
     595             :         size_t size, max, pos;
     596             :         int i, size_len;
     597             : 
     598          13 :         if (frag->nb_units > 8) {
     599           0 :             av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many frames to "
     600             :                    "make superframe: %d.\n", frag->nb_units);
     601           0 :             return AVERROR(EINVAL);
     602             :         }
     603             : 
     604          13 :         max = 0;
     605          40 :         for (i = 0; i < frag->nb_units; i++)
     606          27 :             if (max < frag->units[i].data_size)
     607          14 :                 max = frag->units[i].data_size;
     608             : 
     609          13 :         if (max < 2)
     610           0 :             size_len = 1;
     611             :         else
     612          13 :             size_len = av_log2(max) / 8 + 1;
     613          13 :         av_assert0(size_len <= 4);
     614             : 
     615          13 :         sfi.superframe_marker            = VP9_SUPERFRAME_MARKER;
     616          13 :         sfi.bytes_per_framesize_minus_1  = size_len - 1;
     617          13 :         sfi.frames_in_superframe_minus_1 = frag->nb_units - 1;
     618             : 
     619          13 :         size = 2;
     620          40 :         for (i = 0; i < frag->nb_units; i++) {
     621          27 :             size += size_len + frag->units[i].data_size;
     622          27 :             sfi.frame_sizes[i] = frag->units[i].data_size;
     623             :         }
     624             : 
     625          13 :         ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
     626          13 :         if (!ref)
     627           0 :             return AVERROR(ENOMEM);
     628          13 :         data = ref->data;
     629          13 :         memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     630             : 
     631          13 :         pos = 0;
     632          40 :         for (i = 0; i < frag->nb_units; i++) {
     633          27 :             av_assert0(size - pos > frag->units[i].data_size);
     634          27 :             memcpy(data + pos, frag->units[i].data,
     635          27 :                    frag->units[i].data_size);
     636          27 :             pos += frag->units[i].data_size;
     637             :         }
     638          13 :         av_assert0(size - pos == 2 + frag->nb_units * size_len);
     639             : 
     640          13 :         init_put_bits(&pbc, data + pos, size - pos);
     641             : 
     642          13 :         err = cbs_vp9_write_superframe_index(ctx, &pbc, &sfi);
     643          13 :         if (err < 0) {
     644           0 :             av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write "
     645             :                    "superframe index.\n");
     646           0 :             av_buffer_unref(&ref);
     647           0 :             return err;
     648             :         }
     649             : 
     650          13 :         av_assert0(put_bits_left(&pbc) == 0);
     651          13 :         flush_put_bits(&pbc);
     652             : 
     653          13 :         frag->data_ref  = ref;
     654          13 :         frag->data      = data;
     655          13 :         frag->data_size = size;
     656             :     }
     657             : 
     658         183 :     return 0;
     659             : }
     660             : 
     661          14 : static void cbs_vp9_close(CodedBitstreamContext *ctx)
     662             : {
     663          14 :     CodedBitstreamVP9Context *priv = ctx->priv_data;
     664             : 
     665          14 :     av_freep(&priv->write_buffer);
     666          14 : }
     667             : 
     668             : const CodedBitstreamType ff_cbs_type_vp9 = {
     669             :     .codec_id          = AV_CODEC_ID_VP9,
     670             : 
     671             :     .priv_data_size    = sizeof(CodedBitstreamVP9Context),
     672             : 
     673             :     .split_fragment    = &cbs_vp9_split_fragment,
     674             :     .read_unit         = &cbs_vp9_read_unit,
     675             :     .write_unit        = &cbs_vp9_write_unit,
     676             :     .assemble_fragment = &cbs_vp9_assemble_fragment,
     677             : 
     678             :     .close             = &cbs_vp9_close,
     679             : };

Generated by: LCOV version 1.13