Libav
|
00001 /* 00002 * VQF demuxer 00003 * Copyright (c) 2009 Vitor Sessak 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "avformat.h" 00023 #include "libavutil/intreadwrite.h" 00024 00025 typedef struct VqfContext { 00026 int frame_bit_len; 00027 uint8_t last_frame_bits; 00028 int remaining_bits; 00029 } VqfContext; 00030 00031 static int vqf_probe(AVProbeData *probe_packet) 00032 { 00033 if (AV_RL32(probe_packet->buf) != MKTAG('T','W','I','N')) 00034 return 0; 00035 00036 if (!memcmp(probe_packet->buf + 4, "97012000", 8)) 00037 return AVPROBE_SCORE_MAX; 00038 00039 if (!memcmp(probe_packet->buf + 4, "00052200", 8)) 00040 return AVPROBE_SCORE_MAX; 00041 00042 return AVPROBE_SCORE_MAX/2; 00043 } 00044 00045 static void add_metadata(AVFormatContext *s, const char *tag, 00046 unsigned int tag_len, unsigned int remaining) 00047 { 00048 int len = FFMIN(tag_len, remaining); 00049 char *buf; 00050 00051 if (len == UINT_MAX) 00052 return; 00053 00054 buf = av_malloc(len+1); 00055 if (!buf) 00056 return; 00057 get_buffer(s->pb, buf, len); 00058 buf[len] = 0; 00059 av_metadata_set2(&s->metadata, tag, buf, AV_METADATA_DONT_STRDUP_VAL); 00060 } 00061 00062 static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) 00063 { 00064 VqfContext *c = s->priv_data; 00065 AVStream *st = av_new_stream(s, 0); 00066 int chunk_tag; 00067 int rate_flag = -1; 00068 int header_size; 00069 int read_bitrate = 0; 00070 int size; 00071 00072 if (!st) 00073 return AVERROR(ENOMEM); 00074 00075 url_fskip(s->pb, 12); 00076 00077 header_size = get_be32(s->pb); 00078 00079 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00080 st->codec->codec_id = CODEC_ID_TWINVQ; 00081 st->start_time = 0; 00082 00083 do { 00084 int len; 00085 chunk_tag = get_le32(s->pb); 00086 00087 if (chunk_tag == MKTAG('D','A','T','A')) 00088 break; 00089 00090 len = get_be32(s->pb); 00091 00092 if ((unsigned) len > INT_MAX/2) { 00093 av_log(s, AV_LOG_ERROR, "Malformed header\n"); 00094 return -1; 00095 } 00096 00097 header_size -= 8; 00098 00099 switch(chunk_tag){ 00100 case MKTAG('C','O','M','M'): 00101 st->codec->channels = get_be32(s->pb) + 1; 00102 read_bitrate = get_be32(s->pb); 00103 rate_flag = get_be32(s->pb); 00104 url_fskip(s->pb, len-12); 00105 00106 st->codec->bit_rate = read_bitrate*1000; 00107 st->codec->bits_per_coded_sample = 16; 00108 break; 00109 case MKTAG('N','A','M','E'): 00110 add_metadata(s, "title" , len, header_size); 00111 break; 00112 case MKTAG('(','c',')',' '): 00113 add_metadata(s, "copyright", len, header_size); 00114 break; 00115 case MKTAG('A','U','T','H'): 00116 add_metadata(s, "author" , len, header_size); 00117 break; 00118 case MKTAG('A','L','B','M'): 00119 add_metadata(s, "album" , len, header_size); 00120 break; 00121 case MKTAG('T','R','C','K'): 00122 add_metadata(s, "track" , len, header_size); 00123 break; 00124 case MKTAG('C','O','M','T'): 00125 add_metadata(s, "comment" , len, header_size); 00126 break; 00127 case MKTAG('F','I','L','E'): 00128 add_metadata(s, "filename" , len, header_size); 00129 break; 00130 case MKTAG('D','S','I','Z'): 00131 add_metadata(s, "size" , len, header_size); 00132 break; 00133 case MKTAG('D','A','T','E'): 00134 add_metadata(s, "date" , len, header_size); 00135 break; 00136 case MKTAG('G','E','N','R'): 00137 add_metadata(s, "genre" , len, header_size); 00138 break; 00139 default: 00140 av_log(s, AV_LOG_ERROR, "Unknown chunk: %c%c%c%c\n", 00141 ((char*)&chunk_tag)[0], ((char*)&chunk_tag)[1], 00142 ((char*)&chunk_tag)[2], ((char*)&chunk_tag)[3]); 00143 url_fskip(s->pb, FFMIN(len, header_size)); 00144 break; 00145 } 00146 00147 header_size -= len; 00148 00149 } while (header_size >= 0); 00150 00151 switch (rate_flag) { 00152 case -1: 00153 av_log(s, AV_LOG_ERROR, "COMM tag not found!\n"); 00154 return -1; 00155 case 44: 00156 st->codec->sample_rate = 44100; 00157 break; 00158 case 22: 00159 st->codec->sample_rate = 22050; 00160 break; 00161 case 11: 00162 st->codec->sample_rate = 11025; 00163 break; 00164 default: 00165 st->codec->sample_rate = rate_flag*1000; 00166 break; 00167 } 00168 00169 switch (((st->codec->sample_rate/1000) << 8) + 00170 read_bitrate/st->codec->channels) { 00171 case (11<<8) + 8 : 00172 case (8 <<8) + 8 : 00173 case (11<<8) + 10: 00174 case (22<<8) + 32: 00175 size = 512; 00176 break; 00177 case (16<<8) + 16: 00178 case (22<<8) + 20: 00179 case (22<<8) + 24: 00180 size = 1024; 00181 break; 00182 case (44<<8) + 40: 00183 case (44<<8) + 48: 00184 size = 2048; 00185 break; 00186 default: 00187 av_log(s, AV_LOG_ERROR, "Mode not suported: %d Hz, %d kb/s.\n", 00188 st->codec->sample_rate, st->codec->bit_rate); 00189 return -1; 00190 } 00191 c->frame_bit_len = st->codec->bit_rate*size/st->codec->sample_rate; 00192 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00193 00194 return 0; 00195 } 00196 00197 static int vqf_read_packet(AVFormatContext *s, AVPacket *pkt) 00198 { 00199 VqfContext *c = s->priv_data; 00200 int ret; 00201 int size = (c->frame_bit_len - c->remaining_bits + 7)>>3; 00202 00203 pkt->pos = url_ftell(s->pb); 00204 pkt->stream_index = 0; 00205 00206 if (av_new_packet(pkt, size+2) < 0) 00207 return AVERROR(EIO); 00208 00209 pkt->data[0] = 8 - c->remaining_bits; // Number of bits to skip 00210 pkt->data[1] = c->last_frame_bits; 00211 ret = get_buffer(s->pb, pkt->data+2, size); 00212 00213 if (ret<=0) { 00214 av_free_packet(pkt); 00215 return AVERROR(EIO); 00216 } 00217 00218 c->last_frame_bits = pkt->data[size+1]; 00219 c->remaining_bits = (size << 3) - c->frame_bit_len + c->remaining_bits; 00220 00221 return size+2; 00222 } 00223 00224 static int vqf_read_seek(AVFormatContext *s, 00225 int stream_index, int64_t timestamp, int flags) 00226 { 00227 VqfContext *c = s->priv_data; 00228 AVStream *st; 00229 int ret; 00230 int64_t pos; 00231 00232 st = s->streams[stream_index]; 00233 pos = av_rescale_rnd(timestamp * st->codec->bit_rate, 00234 st->time_base.num, 00235 st->time_base.den * (int64_t)c->frame_bit_len, 00236 (flags & AVSEEK_FLAG_BACKWARD) ? 00237 AV_ROUND_DOWN : AV_ROUND_UP); 00238 pos *= c->frame_bit_len; 00239 00240 st->cur_dts = av_rescale(pos, st->time_base.den, 00241 st->codec->bit_rate * (int64_t)st->time_base.num); 00242 00243 if ((ret = url_fseek(s->pb, ((pos-7) >> 3) + s->data_offset, SEEK_SET)) < 0) 00244 return ret; 00245 00246 c->remaining_bits = -7 - ((pos-7)&7); 00247 return 0; 00248 } 00249 00250 AVInputFormat vqf_demuxer = { 00251 "vqf", 00252 NULL_IF_CONFIG_SMALL("Nippon Telegraph and Telephone Corporation (NTT) TwinVQ"), 00253 sizeof(VqfContext), 00254 vqf_probe, 00255 vqf_read_header, 00256 vqf_read_packet, 00257 NULL, 00258 vqf_read_seek, 00259 .extensions = "vqf", 00260 };