Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * VP9 compatible video decoder
  3.  *
  4.  * Copyright (C) 2013 Ronald S. Bultje <rsbultje gmail com>
  5.  * Copyright (C) 2013 Clément Bœsch <u pkh me>
  6.  *
  7.  * This file is part of FFmpeg.
  8.  *
  9.  * FFmpeg is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU Lesser General Public
  11.  * License as published by the Free Software Foundation; either
  12.  * version 2.1 of the License, or (at your option) any later version.
  13.  *
  14.  * FFmpeg is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  * Lesser General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU Lesser General Public
  20.  * License along with FFmpeg; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22.  */
  23.  
  24. #include "libavutil/intreadwrite.h"
  25. #include "libavcodec/get_bits.h"
  26. #include "parser.h"
  27.  
  28. typedef struct VP9ParseContext {
  29.     int n_frames; // 1-8
  30.     int size[8];
  31.     int64_t pts;
  32. } VP9ParseContext;
  33.  
  34. static int parse_frame(AVCodecParserContext *ctx, const uint8_t *buf, int size)
  35. {
  36.     VP9ParseContext *s = ctx->priv_data;
  37.     GetBitContext gb;
  38.     int res, profile, keyframe, invisible;
  39.  
  40.     if ((res = init_get_bits8(&gb, buf, size)) < 0)
  41.         return res;
  42.     get_bits(&gb, 2); // frame marker
  43.     profile  = get_bits1(&gb);
  44.     profile |= get_bits1(&gb) << 1;
  45.     if (profile == 3) profile += get_bits1(&gb);
  46.  
  47.     if (get_bits1(&gb)) {
  48.         keyframe = 0;
  49.         invisible = 0;
  50.     } else {
  51.         keyframe  = !get_bits1(&gb);
  52.         invisible = !get_bits1(&gb);
  53.     }
  54.  
  55.     if (!keyframe) {
  56.         ctx->pict_type = AV_PICTURE_TYPE_P;
  57.         ctx->key_frame = 0;
  58.     } else {
  59.         ctx->pict_type = AV_PICTURE_TYPE_I;
  60.         ctx->key_frame = 1;
  61.     }
  62.  
  63.     if (!invisible) {
  64.         if (ctx->pts == AV_NOPTS_VALUE)
  65.             ctx->pts = s->pts;
  66.         s->pts = AV_NOPTS_VALUE;
  67.     } else {
  68.         s->pts = ctx->pts;
  69.         ctx->pts = AV_NOPTS_VALUE;
  70.     }
  71.  
  72.     return 0;
  73. }
  74.  
  75. static int parse(AVCodecParserContext *ctx,
  76.                  AVCodecContext *avctx,
  77.                  const uint8_t **out_data, int *out_size,
  78.                  const uint8_t *data, int size)
  79. {
  80.     VP9ParseContext *s = ctx->priv_data;
  81.     int full_size = size;
  82.     int marker;
  83.  
  84.     if (size <= 0) {
  85.         *out_size = 0;
  86.         *out_data = data;
  87.  
  88.         return 0;
  89.     }
  90.  
  91.     if (s->n_frames > 0) {
  92.         *out_data = data;
  93.         *out_size = s->size[--s->n_frames];
  94.         parse_frame(ctx, *out_data, *out_size);
  95.  
  96.         return s->n_frames > 0 ? *out_size : size /* i.e. include idx tail */;
  97.     }
  98.  
  99.     marker = data[size - 1];
  100.     if ((marker & 0xe0) == 0xc0) {
  101.         int nbytes = 1 + ((marker >> 3) & 0x3);
  102.         int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes;
  103.  
  104.         if (size >= idx_sz && data[size - idx_sz] == marker) {
  105.             const uint8_t *idx = data + size + 1 - idx_sz;
  106.             int first = 1;
  107.  
  108.             switch (nbytes) {
  109. #define case_n(a, rd) \
  110.             case a: \
  111.                 while (n_frames--) { \
  112.                     unsigned sz = rd; \
  113.                     idx += a; \
  114.                     if (sz > size) { \
  115.                         s->n_frames = 0; \
  116.                         *out_size = size; \
  117.                         *out_data = data; \
  118.                         av_log(avctx, AV_LOG_ERROR, \
  119.                                "Superframe packet size too big: %u > %d\n", \
  120.                                sz, size); \
  121.                         return full_size; \
  122.                     } \
  123.                     if (first) { \
  124.                         first = 0; \
  125.                         *out_data = data; \
  126.                         *out_size = sz; \
  127.                         s->n_frames = n_frames; \
  128.                     } else { \
  129.                         s->size[n_frames] = sz; \
  130.                     } \
  131.                     data += sz; \
  132.                     size -= sz; \
  133.                 } \
  134.                 parse_frame(ctx, *out_data, *out_size); \
  135.                 return *out_size
  136.  
  137.                 case_n(1, *idx);
  138.                 case_n(2, AV_RL16(idx));
  139.                 case_n(3, AV_RL24(idx));
  140.                 case_n(4, AV_RL32(idx));
  141.             }
  142.         }
  143.     }
  144.  
  145.     *out_data = data;
  146.     *out_size = size;
  147.     parse_frame(ctx, data, size);
  148.  
  149.     return size;
  150. }
  151.  
  152. AVCodecParser ff_vp9_parser = {
  153.     .codec_ids      = { AV_CODEC_ID_VP9 },
  154.     .priv_data_size = sizeof(VP9ParseContext),
  155.     .parser_parse   = parse,
  156. };
  157.