annotate ffmpeg/libavformat/oggparsespeex.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 Copyright (C) 2008 Reimar Döffinger
yading@11 3
yading@11 4 Permission is hereby granted, free of charge, to any person
yading@11 5 obtaining a copy of this software and associated documentation
yading@11 6 files (the "Software"), to deal in the Software without
yading@11 7 restriction, including without limitation the rights to use, copy,
yading@11 8 modify, merge, publish, distribute, sublicense, and/or sell copies
yading@11 9 of the Software, and to permit persons to whom the Software is
yading@11 10 furnished to do so, subject to the following conditions:
yading@11 11
yading@11 12 The above copyright notice and this permission notice shall be
yading@11 13 included in all copies or substantial portions of the Software.
yading@11 14
yading@11 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
yading@11 16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
yading@11 17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
yading@11 18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
yading@11 19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
yading@11 20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
yading@11 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
yading@11 22 DEALINGS IN THE SOFTWARE.
yading@11 23 **/
yading@11 24
yading@11 25 #include <stdlib.h>
yading@11 26 #include "libavutil/bswap.h"
yading@11 27 #include "libavutil/avstring.h"
yading@11 28 #include "libavutil/channel_layout.h"
yading@11 29 #include "libavcodec/get_bits.h"
yading@11 30 #include "libavcodec/bytestream.h"
yading@11 31 #include "avformat.h"
yading@11 32 #include "internal.h"
yading@11 33 #include "oggdec.h"
yading@11 34
yading@11 35 struct speex_params {
yading@11 36 int packet_size;
yading@11 37 int final_packet_duration;
yading@11 38 int seq;
yading@11 39 };
yading@11 40
yading@11 41 static int speex_header(AVFormatContext *s, int idx) {
yading@11 42 struct ogg *ogg = s->priv_data;
yading@11 43 struct ogg_stream *os = ogg->streams + idx;
yading@11 44 struct speex_params *spxp = os->private;
yading@11 45 AVStream *st = s->streams[idx];
yading@11 46 uint8_t *p = os->buf + os->pstart;
yading@11 47
yading@11 48 if (!spxp) {
yading@11 49 spxp = av_mallocz(sizeof(*spxp));
yading@11 50 os->private = spxp;
yading@11 51 }
yading@11 52
yading@11 53 if (spxp->seq > 1)
yading@11 54 return 0;
yading@11 55
yading@11 56 if (spxp->seq == 0) {
yading@11 57 int frames_per_packet;
yading@11 58 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 59 st->codec->codec_id = AV_CODEC_ID_SPEEX;
yading@11 60
yading@11 61 if (os->psize < 68) {
yading@11 62 av_log(s, AV_LOG_ERROR, "speex packet too small\n");
yading@11 63 return AVERROR_INVALIDDATA;
yading@11 64 }
yading@11 65
yading@11 66 st->codec->sample_rate = AV_RL32(p + 36);
yading@11 67 st->codec->channels = AV_RL32(p + 48);
yading@11 68 if (st->codec->channels < 1 || st->codec->channels > 2) {
yading@11 69 av_log(s, AV_LOG_ERROR, "invalid channel count. Speex must be mono or stereo.\n");
yading@11 70 return AVERROR_INVALIDDATA;
yading@11 71 }
yading@11 72 st->codec->channel_layout = st->codec->channels == 1 ? AV_CH_LAYOUT_MONO :
yading@11 73 AV_CH_LAYOUT_STEREO;
yading@11 74
yading@11 75 spxp->packet_size = AV_RL32(p + 56);
yading@11 76 frames_per_packet = AV_RL32(p + 64);
yading@11 77 if (frames_per_packet)
yading@11 78 spxp->packet_size *= frames_per_packet;
yading@11 79
yading@11 80 st->codec->extradata_size = os->psize;
yading@11 81 st->codec->extradata = av_malloc(st->codec->extradata_size
yading@11 82 + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 83 memcpy(st->codec->extradata, p, st->codec->extradata_size);
yading@11 84
yading@11 85 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
yading@11 86 } else
yading@11 87 ff_vorbis_comment(s, &st->metadata, p, os->psize);
yading@11 88
yading@11 89 spxp->seq++;
yading@11 90 return 1;
yading@11 91 }
yading@11 92
yading@11 93 static int ogg_page_packets(struct ogg_stream *os)
yading@11 94 {
yading@11 95 int i;
yading@11 96 int packets = 0;
yading@11 97 for (i = 0; i < os->nsegs; i++)
yading@11 98 if (os->segments[i] < 255)
yading@11 99 packets++;
yading@11 100 return packets;
yading@11 101 }
yading@11 102
yading@11 103 static int speex_packet(AVFormatContext *s, int idx)
yading@11 104 {
yading@11 105 struct ogg *ogg = s->priv_data;
yading@11 106 struct ogg_stream *os = ogg->streams + idx;
yading@11 107 struct speex_params *spxp = os->private;
yading@11 108 int packet_size = spxp->packet_size;
yading@11 109
yading@11 110 if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE &&
yading@11 111 os->granule > 0) {
yading@11 112 /* first packet of final page. we have to calculate the final packet
yading@11 113 duration here because it is the only place we know the next-to-last
yading@11 114 granule position. */
yading@11 115 spxp->final_packet_duration = os->granule - os->lastpts -
yading@11 116 packet_size * (ogg_page_packets(os) - 1);
yading@11 117 }
yading@11 118
yading@11 119 if (!os->lastpts && os->granule > 0)
yading@11 120 /* first packet */
yading@11 121 os->lastpts = os->lastdts = os->granule - packet_size *
yading@11 122 ogg_page_packets(os);
yading@11 123 if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs &&
yading@11 124 spxp->final_packet_duration)
yading@11 125 /* final packet */
yading@11 126 os->pduration = spxp->final_packet_duration;
yading@11 127 else
yading@11 128 os->pduration = packet_size;
yading@11 129
yading@11 130 return 0;
yading@11 131 }
yading@11 132
yading@11 133 const struct ogg_codec ff_speex_codec = {
yading@11 134 .magic = "Speex ",
yading@11 135 .magicsize = 8,
yading@11 136 .header = speex_header,
yading@11 137 .packet = speex_packet,
yading@11 138 .nb_header = 2,
yading@11 139 };