diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-09-05 17:57:22 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-09-05 17:57:22 +0100 |
| commit | 8992cb1d0d07edc33d274f6d7924ecdf6f83d994 (patch) | |
| tree | 3a2c86846b7eec8137c1507e623fc7018f13d453 /ffmpeg/libavformat/vocdec.c | |
| parent | 741fb4b9e135cfb161a749db88713229038577bb (diff) | |
making act segmenter
Diffstat (limited to 'ffmpeg/libavformat/vocdec.c')
| -rw-r--r-- | ffmpeg/libavformat/vocdec.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/ffmpeg/libavformat/vocdec.c b/ffmpeg/libavformat/vocdec.c new file mode 100644 index 0000000..62215fc --- /dev/null +++ b/ffmpeg/libavformat/vocdec.c @@ -0,0 +1,175 @@ +/* + * Creative Voice File demuxer. + * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "voc.h" +#include "internal.h" + + +static int voc_probe(AVProbeData *p) +{ + int version, check; + + if (memcmp(p->buf, ff_voc_magic, sizeof(ff_voc_magic) - 1)) + return 0; + version = AV_RL16(p->buf + 22); + check = AV_RL16(p->buf + 24); + if (~version + 0x1234 != check) + return 10; + + return AVPROBE_SCORE_MAX; +} + +static int voc_read_header(AVFormatContext *s) +{ + VocDecContext *voc = s->priv_data; + AVIOContext *pb = s->pb; + int header_size; + AVStream *st; + + avio_skip(pb, 20); + header_size = avio_rl16(pb) - 22; + if (header_size != 4) { + av_log(s, AV_LOG_ERROR, "unknown header size: %d\n", header_size); + return AVERROR(ENOSYS); + } + avio_skip(pb, header_size); + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + + voc->remaining_size = 0; + return 0; +} + +int +ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) +{ + VocDecContext *voc = s->priv_data; + AVCodecContext *dec = st->codec; + AVIOContext *pb = s->pb; + VocType type; + int size, tmp_codec=-1; + int sample_rate = 0; + int channels = 1; + + while (!voc->remaining_size) { + type = avio_r8(pb); + if (type == VOC_TYPE_EOF) + return AVERROR(EIO); + voc->remaining_size = avio_rl24(pb); + if (!voc->remaining_size) { + if (!s->pb->seekable) + return AVERROR(EIO); + voc->remaining_size = avio_size(pb) - avio_tell(pb); + } + max_size -= 4; + + switch (type) { + case VOC_TYPE_VOICE_DATA: + if (!dec->sample_rate) { + dec->sample_rate = 1000000 / (256 - avio_r8(pb)); + if (sample_rate) + dec->sample_rate = sample_rate; + avpriv_set_pts_info(st, 64, 1, dec->sample_rate); + } else + avio_skip(pb, 1); + dec->channels = channels; + tmp_codec = avio_r8(pb); + dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id); + voc->remaining_size -= 2; + max_size -= 2; + channels = 1; + break; + + case VOC_TYPE_VOICE_DATA_CONT: + break; + + case VOC_TYPE_EXTENDED: + sample_rate = avio_rl16(pb); + avio_r8(pb); + channels = avio_r8(pb) + 1; + sample_rate = 256000000 / (channels * (65536 - sample_rate)); + voc->remaining_size = 0; + max_size -= 4; + break; + + case VOC_TYPE_NEW_VOICE_DATA: + if (!dec->sample_rate) { + dec->sample_rate = avio_rl32(pb); + avpriv_set_pts_info(st, 64, 1, dec->sample_rate); + } else + avio_skip(pb, 4); + dec->bits_per_coded_sample = avio_r8(pb); + dec->channels = avio_r8(pb); + tmp_codec = avio_rl16(pb); + avio_skip(pb, 4); + voc->remaining_size -= 12; + max_size -= 12; + break; + + default: + avio_skip(pb, voc->remaining_size); + max_size -= voc->remaining_size; + voc->remaining_size = 0; + break; + } + } + + if (tmp_codec >= 0) { + tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec); + if (dec->codec_id == AV_CODEC_ID_NONE) + dec->codec_id = tmp_codec; + else if (dec->codec_id != tmp_codec) + av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n"); + if (dec->codec_id == AV_CODEC_ID_NONE) { + if (s->audio_codec_id == AV_CODEC_ID_NONE) { + av_log(s, AV_LOG_ERROR, "unknown codec tag\n"); + return AVERROR(EINVAL); + } + av_log(s, AV_LOG_WARNING, "unknown codec tag\n"); + } + } + + dec->bit_rate = dec->sample_rate * dec->channels * dec->bits_per_coded_sample; + + if (max_size <= 0) + max_size = 2048; + size = FFMIN(voc->remaining_size, max_size); + voc->remaining_size -= size; + return av_get_packet(pb, pkt, size); +} + +static int voc_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + return ff_voc_get_packet(s, pkt, s->streams[0], 0); +} + +AVInputFormat ff_voc_demuxer = { + .name = "voc", + .long_name = NULL_IF_CONFIG_SMALL("Creative Voice"), + .priv_data_size = sizeof(VocDecContext), + .read_probe = voc_probe, + .read_header = voc_read_header, + .read_packet = voc_read_packet, + .codec_tag = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 }, +}; |
