Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Opus parser for Ogg
  3.  * Copyright (c) 2012 Nicolas George
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include <string.h>
  23.  
  24. #include "libavutil/intreadwrite.h"
  25. #include "avformat.h"
  26. #include "internal.h"
  27. #include "oggdec.h"
  28.  
  29. struct oggopus_private {
  30.     int need_comments;
  31.     unsigned pre_skip;
  32.     int64_t cur_dts;
  33. };
  34.  
  35. #define OPUS_SEEK_PREROLL_MS 80
  36. #define OPUS_HEAD_SIZE 19
  37.  
  38. static int opus_header(AVFormatContext *avf, int idx)
  39. {
  40.     struct ogg *ogg              = avf->priv_data;
  41.     struct ogg_stream *os        = &ogg->streams[idx];
  42.     AVStream *st                 = avf->streams[idx];
  43.     struct oggopus_private *priv = os->private;
  44.     uint8_t *packet              = os->buf + os->pstart;
  45.  
  46.     if (!priv) {
  47.         priv = os->private = av_mallocz(sizeof(*priv));
  48.         if (!priv)
  49.             return AVERROR(ENOMEM);
  50.     }
  51.  
  52.     if (os->flags & OGG_FLAG_BOS) {
  53.         if (os->psize < OPUS_HEAD_SIZE || (AV_RL8(packet + 8) & 0xF0) != 0)
  54.             return AVERROR_INVALIDDATA;
  55.         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
  56.         st->codec->codec_id   = AV_CODEC_ID_OPUS;
  57.         st->codec->channels   = AV_RL8 (packet + 9);
  58.         priv->pre_skip        = AV_RL16(packet + 10);
  59.         st->codec->delay      = priv->pre_skip;
  60.         /*orig_sample_rate    = AV_RL32(packet + 12);*/
  61.         /*gain                = AV_RL16(packet + 16);*/
  62.         /*channel_map         = AV_RL8 (packet + 18);*/
  63.  
  64.         if (ff_alloc_extradata(st->codec, os->psize))
  65.             return AVERROR(ENOMEM);
  66.  
  67.         memcpy(st->codec->extradata, packet, os->psize);
  68.  
  69.         st->codec->sample_rate = 48000;
  70.         av_codec_set_seek_preroll(st->codec,
  71.                                   av_rescale(OPUS_SEEK_PREROLL_MS,
  72.                                              st->codec->sample_rate, 1000));
  73.         avpriv_set_pts_info(st, 64, 1, 48000);
  74.         priv->need_comments = 1;
  75.         return 1;
  76.     }
  77.  
  78.     if (priv->need_comments) {
  79.         if (os->psize < 8 || memcmp(packet, "OpusTags", 8))
  80.             return AVERROR_INVALIDDATA;
  81.         ff_vorbis_stream_comment(avf, st, packet + 8, os->psize - 8);
  82.         priv->need_comments--;
  83.         return 1;
  84.     }
  85.  
  86.     return 0;
  87. }
  88.  
  89. static int opus_duration(uint8_t *src, int size)
  90. {
  91.     unsigned nb_frames  = 1;
  92.     unsigned toc        = src[0];
  93.     unsigned toc_config = toc >> 3;
  94.     unsigned toc_count  = toc & 3;
  95.     unsigned frame_size = toc_config < 12 ? FFMAX(480, 960 * (toc_config & 3)) :
  96.                           toc_config < 16 ? 480 << (toc_config & 1) :
  97.                                             120 << (toc_config & 3);
  98.     if (toc_count == 3) {
  99.         if (size<2)
  100.             return AVERROR_INVALIDDATA;
  101.         nb_frames = src[1] & 0x3F;
  102.     } else if (toc_count) {
  103.         nb_frames = 2;
  104.     }
  105.  
  106.     return frame_size * nb_frames;
  107. }
  108.  
  109. static int opus_packet(AVFormatContext *avf, int idx)
  110. {
  111.     struct ogg *ogg              = avf->priv_data;
  112.     struct ogg_stream *os        = &ogg->streams[idx];
  113.     AVStream *st                 = avf->streams[idx];
  114.     struct oggopus_private *priv = os->private;
  115.     uint8_t *packet              = os->buf + os->pstart;
  116.     int ret;
  117.  
  118.     if (!os->psize)
  119.         return AVERROR_INVALIDDATA;
  120.  
  121.     if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
  122.         int seg, d;
  123.         int duration;
  124.         uint8_t *last_pkt  = os->buf + os->pstart;
  125.         uint8_t *next_pkt  = last_pkt;
  126.  
  127.         duration = 0;
  128.         seg = os->segp;
  129.         d = opus_duration(last_pkt, os->psize);
  130.         if (d < 0) {
  131.             os->pflags |= AV_PKT_FLAG_CORRUPT;
  132.             return 0;
  133.         }
  134.         duration += d;
  135.         last_pkt = next_pkt =  next_pkt + os->psize;
  136.         for (; seg < os->nsegs; seg++) {
  137.             next_pkt += os->segments[seg];
  138.             if (os->segments[seg] < 255 && next_pkt != last_pkt) {
  139.                 int d = opus_duration(last_pkt, next_pkt - last_pkt);
  140.                 if (d > 0)
  141.                     duration += d;
  142.                 last_pkt = next_pkt;
  143.             }
  144.         }
  145.         os->lastpts                 =
  146.         os->lastdts                 = os->granule - duration;
  147.     }
  148.  
  149.     if ((ret = opus_duration(packet, os->psize)) < 0)
  150.         return ret;
  151.  
  152.     os->pduration = ret;
  153.     if (os->lastpts != AV_NOPTS_VALUE) {
  154.         if (st->start_time == AV_NOPTS_VALUE)
  155.             st->start_time = os->lastpts;
  156.         priv->cur_dts = os->lastdts = os->lastpts -= priv->pre_skip;
  157.     }
  158.  
  159.     priv->cur_dts += os->pduration;
  160.     if ((os->flags & OGG_FLAG_EOS)) {
  161.         int64_t skip = priv->cur_dts - os->granule + priv->pre_skip;
  162.         skip = FFMIN(skip, os->pduration);
  163.         if (skip > 0) {
  164.             os->pduration = skip < os->pduration ? os->pduration - skip : 1;
  165.             os->end_trimming = skip;
  166.             av_log(avf, AV_LOG_DEBUG,
  167.                    "Last packet was truncated to %d due to end trimming.\n",
  168.                    os->pduration);
  169.         }
  170.     }
  171.  
  172.     return 0;
  173. }
  174.  
  175. const struct ogg_codec ff_opus_codec = {
  176.     .name             = "Opus",
  177.     .magic            = "OpusHead",
  178.     .magicsize        = 8,
  179.     .header           = opus_header,
  180.     .packet           = opus_packet,
  181.     .nb_header        = 1,
  182. };
  183.