yading@11: /* yading@11: * Xiph CELT parser for Ogg yading@11: * Copyright (c) 2011 Nicolas George yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include yading@11: yading@11: #include "libavutil/intreadwrite.h" yading@11: #include "avformat.h" yading@11: #include "internal.h" yading@11: #include "oggdec.h" yading@11: yading@11: struct oggcelt_private { yading@11: int extra_headers_left; yading@11: }; yading@11: yading@11: static int celt_header(AVFormatContext *s, int idx) yading@11: { yading@11: struct ogg *ogg = s->priv_data; yading@11: struct ogg_stream *os = ogg->streams + idx; yading@11: AVStream *st = s->streams[idx]; yading@11: struct oggcelt_private *priv = os->private; yading@11: uint8_t *p = os->buf + os->pstart; yading@11: yading@11: if (os->psize == 60 && yading@11: !memcmp(p, ff_celt_codec.magic, ff_celt_codec.magicsize)) { yading@11: /* Main header */ yading@11: yading@11: uint32_t version, sample_rate, nb_channels, frame_size; yading@11: uint32_t overlap, extra_headers; yading@11: uint8_t *extradata; yading@11: yading@11: extradata = av_malloc(2 * sizeof(uint32_t) + yading@11: FF_INPUT_BUFFER_PADDING_SIZE); yading@11: priv = av_malloc(sizeof(struct oggcelt_private)); yading@11: if (!extradata || !priv) { yading@11: av_free(extradata); yading@11: av_free(priv); yading@11: return AVERROR(ENOMEM); yading@11: } yading@11: version = AV_RL32(p + 28); yading@11: /* unused header size field skipped */ yading@11: sample_rate = AV_RL32(p + 36); yading@11: nb_channels = AV_RL32(p + 40); yading@11: frame_size = AV_RL32(p + 44); yading@11: overlap = AV_RL32(p + 48); yading@11: /* unused bytes per packet field skipped */ yading@11: extra_headers = AV_RL32(p + 56); yading@11: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; yading@11: st->codec->codec_id = AV_CODEC_ID_CELT; yading@11: st->codec->sample_rate = sample_rate; yading@11: st->codec->channels = nb_channels; yading@11: st->codec->frame_size = frame_size; yading@11: av_free(st->codec->extradata); yading@11: st->codec->extradata = extradata; yading@11: st->codec->extradata_size = 2 * sizeof(uint32_t); yading@11: if (sample_rate) yading@11: avpriv_set_pts_info(st, 64, 1, sample_rate); yading@11: priv->extra_headers_left = 1 + extra_headers; yading@11: av_free(os->private); yading@11: os->private = priv; yading@11: AV_WL32(extradata + 0, overlap); yading@11: AV_WL32(extradata + 4, version); yading@11: return 1; yading@11: } else if (priv && priv->extra_headers_left) { yading@11: /* Extra headers (vorbiscomment) */ yading@11: yading@11: ff_vorbis_comment(s, &st->metadata, p, os->psize); yading@11: priv->extra_headers_left--; yading@11: return 1; yading@11: } else { yading@11: return 0; yading@11: } yading@11: } yading@11: yading@11: const struct ogg_codec ff_celt_codec = { yading@11: .magic = "CELT ", yading@11: .magicsize = 8, yading@11: .header = celt_header, yading@11: .nb_header = 2, yading@11: };