| 1 | /* |
| 2 | * Creative Voice File demuxer. |
| 3 | * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> |
| 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 "libavutil/intreadwrite.h" |
| 23 | #include "voc.h" |
| 24 | #include "internal.h" |
| 25 | |
| 26 | |
| 27 | static int voc_probe(AVProbeData *p) |
| 28 | { |
| 29 | int version, check; |
| 30 | |
| 31 | if (memcmp(p->buf, ff_voc_magic, sizeof(ff_voc_magic) - 1)) |
| 32 | return 0; |
| 33 | version = AV_RL16(p->buf + 22); |
| 34 | check = AV_RL16(p->buf + 24); |
| 35 | if (~version + 0x1234 != check) |
| 36 | return 10; |
| 37 | |
| 38 | return AVPROBE_SCORE_MAX; |
| 39 | } |
| 40 | |
| 41 | static int voc_read_header(AVFormatContext *s) |
| 42 | { |
| 43 | VocDecContext *voc = s->priv_data; |
| 44 | AVIOContext *pb = s->pb; |
| 45 | int header_size; |
| 46 | AVStream *st; |
| 47 | |
| 48 | avio_skip(pb, 20); |
| 49 | header_size = avio_rl16(pb) - 22; |
| 50 | if (header_size != 4) { |
| 51 | av_log(s, AV_LOG_ERROR, "unknown header size: %d\n", header_size); |
| 52 | return AVERROR(ENOSYS); |
| 53 | } |
| 54 | avio_skip(pb, header_size); |
| 55 | st = avformat_new_stream(s, NULL); |
| 56 | if (!st) |
| 57 | return AVERROR(ENOMEM); |
| 58 | st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
| 59 | |
| 60 | voc->remaining_size = 0; |
| 61 | return 0; |
| 62 | } |
| 63 | |
| 64 | int |
| 65 | ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) |
| 66 | { |
| 67 | VocDecContext *voc = s->priv_data; |
| 68 | AVCodecContext *dec = st->codec; |
| 69 | AVIOContext *pb = s->pb; |
| 70 | VocType type; |
| 71 | int size, tmp_codec=-1; |
| 72 | int sample_rate = 0; |
| 73 | int channels = 1; |
| 74 | |
| 75 | while (!voc->remaining_size) { |
| 76 | type = avio_r8(pb); |
| 77 | if (type == VOC_TYPE_EOF) |
| 78 | return AVERROR_EOF; |
| 79 | voc->remaining_size = avio_rl24(pb); |
| 80 | if (!voc->remaining_size) { |
| 81 | if (!s->pb->seekable) |
| 82 | return AVERROR(EIO); |
| 83 | voc->remaining_size = avio_size(pb) - avio_tell(pb); |
| 84 | } |
| 85 | max_size -= 4; |
| 86 | |
| 87 | switch (type) { |
| 88 | case VOC_TYPE_VOICE_DATA: |
| 89 | if (!dec->sample_rate) { |
| 90 | dec->sample_rate = 1000000 / (256 - avio_r8(pb)); |
| 91 | if (sample_rate) |
| 92 | dec->sample_rate = sample_rate; |
| 93 | avpriv_set_pts_info(st, 64, 1, dec->sample_rate); |
| 94 | dec->channels = channels; |
| 95 | dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id); |
| 96 | } else |
| 97 | avio_skip(pb, 1); |
| 98 | tmp_codec = avio_r8(pb); |
| 99 | voc->remaining_size -= 2; |
| 100 | max_size -= 2; |
| 101 | channels = 1; |
| 102 | break; |
| 103 | |
| 104 | case VOC_TYPE_VOICE_DATA_CONT: |
| 105 | break; |
| 106 | |
| 107 | case VOC_TYPE_EXTENDED: |
| 108 | sample_rate = avio_rl16(pb); |
| 109 | avio_r8(pb); |
| 110 | channels = avio_r8(pb) + 1; |
| 111 | sample_rate = 256000000 / (channels * (65536 - sample_rate)); |
| 112 | voc->remaining_size = 0; |
| 113 | max_size -= 4; |
| 114 | break; |
| 115 | |
| 116 | case VOC_TYPE_NEW_VOICE_DATA: |
| 117 | if (!dec->sample_rate) { |
| 118 | dec->sample_rate = avio_rl32(pb); |
| 119 | avpriv_set_pts_info(st, 64, 1, dec->sample_rate); |
| 120 | dec->bits_per_coded_sample = avio_r8(pb); |
| 121 | dec->channels = avio_r8(pb); |
| 122 | } else |
| 123 | avio_skip(pb, 6); |
| 124 | tmp_codec = avio_rl16(pb); |
| 125 | avio_skip(pb, 4); |
| 126 | voc->remaining_size -= 12; |
| 127 | max_size -= 12; |
| 128 | break; |
| 129 | |
| 130 | default: |
| 131 | avio_skip(pb, voc->remaining_size); |
| 132 | max_size -= voc->remaining_size; |
| 133 | voc->remaining_size = 0; |
| 134 | break; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | if (tmp_codec >= 0) { |
| 139 | tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec); |
| 140 | if (dec->codec_id == AV_CODEC_ID_NONE) |
| 141 | dec->codec_id = tmp_codec; |
| 142 | else if (dec->codec_id != tmp_codec) |
| 143 | av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n"); |
| 144 | if (dec->codec_id == AV_CODEC_ID_NONE) { |
| 145 | if (s->audio_codec_id == AV_CODEC_ID_NONE) { |
| 146 | av_log(s, AV_LOG_ERROR, "unknown codec tag\n"); |
| 147 | return AVERROR(EINVAL); |
| 148 | } |
| 149 | av_log(s, AV_LOG_WARNING, "unknown codec tag\n"); |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | dec->bit_rate = dec->sample_rate * dec->channels * dec->bits_per_coded_sample; |
| 154 | |
| 155 | if (max_size <= 0) |
| 156 | max_size = 2048; |
| 157 | size = FFMIN(voc->remaining_size, max_size); |
| 158 | voc->remaining_size -= size; |
| 159 | return av_get_packet(pb, pkt, size); |
| 160 | } |
| 161 | |
| 162 | static int voc_read_packet(AVFormatContext *s, AVPacket *pkt) |
| 163 | { |
| 164 | return ff_voc_get_packet(s, pkt, s->streams[0], 0); |
| 165 | } |
| 166 | |
| 167 | AVInputFormat ff_voc_demuxer = { |
| 168 | .name = "voc", |
| 169 | .long_name = NULL_IF_CONFIG_SMALL("Creative Voice"), |
| 170 | .priv_data_size = sizeof(VocDecContext), |
| 171 | .read_probe = voc_probe, |
| 172 | .read_header = voc_read_header, |
| 173 | .read_packet = voc_read_packet, |
| 174 | .codec_tag = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 }, |
| 175 | }; |