annotate ffmpeg/libavformat/oggparseopus.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Opus parser for Ogg
yading@11 3 * Copyright (c) 2012 Nicolas George
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 #include <string.h>
yading@11 23
yading@11 24 #include "libavutil/intreadwrite.h"
yading@11 25 #include "avformat.h"
yading@11 26 #include "internal.h"
yading@11 27 #include "oggdec.h"
yading@11 28
yading@11 29 struct oggopus_private {
yading@11 30 int need_comments;
yading@11 31 unsigned pre_skip;
yading@11 32 int64_t cur_dts;
yading@11 33 };
yading@11 34
yading@11 35 #define OPUS_HEAD_SIZE 19
yading@11 36
yading@11 37 static int opus_header(AVFormatContext *avf, int idx)
yading@11 38 {
yading@11 39 struct ogg *ogg = avf->priv_data;
yading@11 40 struct ogg_stream *os = &ogg->streams[idx];
yading@11 41 AVStream *st = avf->streams[idx];
yading@11 42 struct oggopus_private *priv = os->private;
yading@11 43 uint8_t *packet = os->buf + os->pstart;
yading@11 44 uint8_t *extradata;
yading@11 45
yading@11 46 if (!priv) {
yading@11 47 priv = os->private = av_mallocz(sizeof(*priv));
yading@11 48 if (!priv)
yading@11 49 return AVERROR(ENOMEM);
yading@11 50 }
yading@11 51 if (os->flags & OGG_FLAG_BOS) {
yading@11 52 if (os->psize < OPUS_HEAD_SIZE || (AV_RL8(packet + 8) & 0xF0) != 0)
yading@11 53 return AVERROR_INVALIDDATA;
yading@11 54 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 55 st->codec->codec_id = AV_CODEC_ID_OPUS;
yading@11 56 st->codec->channels = AV_RL8 (packet + 9);
yading@11 57 priv->pre_skip = AV_RL16(packet + 10);
yading@11 58 /*orig_sample_rate = AV_RL32(packet + 12);*/
yading@11 59 /*gain = AV_RL16(packet + 16);*/
yading@11 60 /*channel_map = AV_RL8 (packet + 18);*/
yading@11 61
yading@11 62 extradata = av_malloc(os->psize + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 63 if (!extradata)
yading@11 64 return AVERROR(ENOMEM);
yading@11 65 memcpy(extradata, packet, os->psize);
yading@11 66 st->codec->extradata = extradata;
yading@11 67 st->codec->extradata_size = os->psize;
yading@11 68
yading@11 69 st->codec->sample_rate = 48000;
yading@11 70 avpriv_set_pts_info(st, 64, 1, 48000);
yading@11 71 priv->need_comments = 1;
yading@11 72 return 1;
yading@11 73 }
yading@11 74
yading@11 75 if (priv->need_comments) {
yading@11 76 if (os->psize < 8 || memcmp(packet, "OpusTags", 8))
yading@11 77 return AVERROR_INVALIDDATA;
yading@11 78 ff_vorbis_comment(avf, &st->metadata, packet + 8, os->psize - 8);
yading@11 79 priv->need_comments--;
yading@11 80 return 1;
yading@11 81 }
yading@11 82 return 0;
yading@11 83 }
yading@11 84
yading@11 85 static int opus_packet(AVFormatContext *avf, int idx)
yading@11 86 {
yading@11 87 struct ogg *ogg = avf->priv_data;
yading@11 88 struct ogg_stream *os = &ogg->streams[idx];
yading@11 89 AVStream *st = avf->streams[idx];
yading@11 90 struct oggopus_private *priv = os->private;
yading@11 91 uint8_t *packet = os->buf + os->pstart;
yading@11 92 unsigned toc, toc_config, toc_count, frame_size, nb_frames = 1;
yading@11 93
yading@11 94 if (!os->psize)
yading@11 95 return AVERROR_INVALIDDATA;
yading@11 96 toc = *packet;
yading@11 97 toc_config = toc >> 3;
yading@11 98 toc_count = toc & 3;
yading@11 99 frame_size = toc_config < 12 ? FFMAX(480, 960 * (toc_config & 3)) :
yading@11 100 toc_config < 16 ? 480 << (toc_config & 1) :
yading@11 101 120 << (toc_config & 3);
yading@11 102 if (toc_count == 3) {
yading@11 103 if (os->psize < 2)
yading@11 104 return AVERROR_INVALIDDATA;
yading@11 105 nb_frames = packet[1] & 0x3F;
yading@11 106 } else if (toc_count) {
yading@11 107 nb_frames = 2;
yading@11 108 }
yading@11 109 os->pduration = frame_size * nb_frames;
yading@11 110 if (os->lastpts != AV_NOPTS_VALUE) {
yading@11 111 if (st->start_time == AV_NOPTS_VALUE)
yading@11 112 st->start_time = os->lastpts;
yading@11 113 priv->cur_dts = os->lastdts = os->lastpts -= priv->pre_skip;
yading@11 114 }
yading@11 115 priv->cur_dts += os->pduration;
yading@11 116 if ((os->flags & OGG_FLAG_EOS)) {
yading@11 117 int64_t skip = priv->cur_dts - os->granule + priv->pre_skip;
yading@11 118 skip = FFMIN(skip, os->pduration);
yading@11 119 if (skip > 0) {
yading@11 120 os->pduration = skip < os->pduration ? os->pduration - skip : 1;
yading@11 121 av_log(avf, AV_LOG_WARNING,
yading@11 122 "Last packet must be truncated to %d (unimplemented).\n",
yading@11 123 os->pduration);
yading@11 124 }
yading@11 125 }
yading@11 126 return 0;
yading@11 127 }
yading@11 128
yading@11 129 const struct ogg_codec ff_opus_codec = {
yading@11 130 .name = "Opus",
yading@11 131 .magic = "OpusHead",
yading@11 132 .magicsize = 8,
yading@11 133 .header = opus_header,
yading@11 134 .packet = opus_packet,
yading@11 135 };