LCOV - code coverage report
Current view: top level - libavcodec - vp9_superframe_split_bsf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 55 65 84.6 %
Date: 2018-05-20 11:54:08 Functions: 2 2 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             : /**
      20             :  * @file
      21             :  * This bitstream filter splits VP9 superframes into packets containing
      22             :  * just one frame.
      23             :  */
      24             : 
      25             : #include <stddef.h>
      26             : 
      27             : #include "avcodec.h"
      28             : #include "bsf.h"
      29             : #include "bytestream.h"
      30             : #include "get_bits.h"
      31             : 
      32             : typedef struct VP9SFSplitContext {
      33             :     AVPacket buffer_pkt;
      34             : 
      35             :     int nb_frames;
      36             :     int next_frame;
      37             :     size_t next_frame_offset;
      38             :     int sizes[8];
      39             : } VP9SFSplitContext;
      40             : 
      41        4504 : static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out)
      42             : {
      43        4504 :     VP9SFSplitContext *s = ctx->priv_data;
      44             :     AVPacket *in;
      45             :     int i, j, ret, marker;
      46        4504 :     int is_superframe = !!s->buffer_pkt.data;
      47             : 
      48        4504 :     if (!s->buffer_pkt.data) {
      49        4442 :         ret = ff_bsf_get_packet_ref(ctx, &s->buffer_pkt);
      50        4442 :         if (ret < 0)
      51        2214 :             return ret;
      52        2228 :         in = &s->buffer_pkt;
      53             : 
      54        2228 :         marker = in->data[in->size - 1];
      55        2228 :         if ((marker & 0xe0) == 0xc0) {
      56          57 :             int length_size = 1 + ((marker >> 3) & 0x3);
      57          57 :             int   nb_frames = 1 + (marker & 0x7);
      58          57 :             int    idx_size = 2 + nb_frames * length_size;
      59             : 
      60          57 :             if (in->size >= idx_size && in->data[in->size - idx_size] == marker) {
      61             :                 GetByteContext bc;
      62          57 :                 int64_t total_size = 0;
      63             : 
      64          57 :                 bytestream2_init(&bc, in->data + in->size + 1 - idx_size,
      65             :                                  nb_frames * length_size);
      66             : 
      67         176 :                 for (i = 0; i < nb_frames; i++) {
      68         119 :                     int frame_size = 0;
      69         353 :                     for (j = 0; j < length_size; j++)
      70         234 :                         frame_size |= bytestream2_get_byte(&bc) << (j * 8);
      71             : 
      72         119 :                     total_size += frame_size;
      73         119 :                     if (frame_size < 0 || total_size > in->size - idx_size) {
      74           0 :                         av_log(ctx, AV_LOG_ERROR,
      75             :                                "Invalid frame size in a superframe: %d\n", frame_size);
      76           0 :                         ret = AVERROR(EINVAL);
      77           0 :                         goto fail;
      78             :                     }
      79         119 :                     s->sizes[i] = frame_size;
      80             :                 }
      81          57 :                 s->nb_frames         = nb_frames;
      82          57 :                 s->next_frame        = 0;
      83          57 :                 s->next_frame_offset = 0;
      84          57 :                 is_superframe        = 1;
      85             :             }
      86             :         }
      87             :     }
      88             : 
      89        2290 :     if (is_superframe) {
      90             :         GetBitContext gb;
      91         119 :         int profile, invisible = 0;
      92             : 
      93         119 :         ret = av_packet_ref(out, &s->buffer_pkt);
      94         119 :         if (ret < 0)
      95           0 :             goto fail;
      96             : 
      97         119 :         out->data += s->next_frame_offset;
      98         119 :         out->size  = s->sizes[s->next_frame];
      99             : 
     100         119 :         s->next_frame_offset += out->size;
     101         119 :         s->next_frame++;
     102             : 
     103         119 :         if (s->next_frame >= s->nb_frames)
     104          57 :             av_packet_unref(&s->buffer_pkt);
     105             : 
     106         119 :         ret = init_get_bits8(&gb, out->data, out->size);
     107         119 :         if (ret < 0)
     108           0 :             goto fail;
     109             : 
     110         119 :         get_bits(&gb, 2); // frame_marker
     111         119 :         profile  = get_bits1(&gb);
     112         119 :         profile |= get_bits1(&gb) << 1;
     113         119 :         if (profile == 3)
     114          26 :             get_bits1(&gb);
     115         119 :         if (!get_bits1(&gb)) {
     116         117 :             get_bits1(&gb);
     117         117 :             invisible = !get_bits1(&gb);
     118             :         }
     119             : 
     120         119 :         if (invisible)
     121          62 :             out->pts = AV_NOPTS_VALUE;
     122             : 
     123             :     } else {
     124        2171 :         av_packet_move_ref(out, &s->buffer_pkt);
     125             :     }
     126             : 
     127        2290 :     return 0;
     128           0 : fail:
     129           0 :     if (ret < 0)
     130           0 :         av_packet_unref(out);
     131           0 :     av_packet_unref(&s->buffer_pkt);
     132           0 :     return ret;
     133             : }
     134             : 
     135         465 : static void vp9_superframe_split_uninit(AVBSFContext *ctx)
     136             : {
     137         465 :     VP9SFSplitContext *s = ctx->priv_data;
     138         465 :     av_packet_unref(&s->buffer_pkt);
     139         465 : }
     140             : 
     141             : const AVBitStreamFilter ff_vp9_superframe_split_bsf = {
     142             :     .name = "vp9_superframe_split",
     143             :     .priv_data_size = sizeof(VP9SFSplitContext),
     144             :     .close          = vp9_superframe_split_uninit,
     145             :     .filter         = vp9_superframe_split_filter,
     146             :     .codec_ids      = (const enum AVCodecID []){ AV_CODEC_ID_VP9, AV_CODEC_ID_NONE },
     147             : };

Generated by: LCOV version 1.13