Libav 0.7.1
|
00001 /* 00002 * Yamaha SMAF format 00003 * Copyright (c) 2005 Vidar Madsen 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #include "avformat.h" 00022 #include "avio_internal.h" 00023 #include "pcm.h" 00024 #include "riff.h" 00025 00026 typedef struct { 00027 int64_t atrpos, atsqpos, awapos; 00028 int64_t data_size; 00029 } MMFContext; 00030 00031 static const int mmf_rates[] = { 4000, 8000, 11025, 22050, 44100 }; 00032 00033 static int mmf_rate(int code) 00034 { 00035 if((code < 0) || (code > 4)) 00036 return -1; 00037 return mmf_rates[code]; 00038 } 00039 00040 #if CONFIG_MMF_MUXER 00041 static int mmf_rate_code(int rate) 00042 { 00043 int i; 00044 for(i = 0; i < 5; i++) 00045 if(mmf_rates[i] == rate) 00046 return i; 00047 return -1; 00048 } 00049 00050 /* Copy of end_tag() from avienc.c, but for big-endian chunk size */ 00051 static void end_tag_be(AVIOContext *pb, int64_t start) 00052 { 00053 int64_t pos; 00054 00055 pos = avio_tell(pb); 00056 avio_seek(pb, start - 4, SEEK_SET); 00057 avio_wb32(pb, (uint32_t)(pos - start)); 00058 avio_seek(pb, pos, SEEK_SET); 00059 } 00060 00061 static int mmf_write_header(AVFormatContext *s) 00062 { 00063 MMFContext *mmf = s->priv_data; 00064 AVIOContext *pb = s->pb; 00065 int64_t pos; 00066 int rate; 00067 00068 rate = mmf_rate_code(s->streams[0]->codec->sample_rate); 00069 if(rate < 0) { 00070 av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d\n", s->streams[0]->codec->sample_rate); 00071 return -1; 00072 } 00073 00074 ffio_wfourcc(pb, "MMMD"); 00075 avio_wb32(pb, 0); 00076 pos = ff_start_tag(pb, "CNTI"); 00077 avio_w8(pb, 0); /* class */ 00078 avio_w8(pb, 0); /* type */ 00079 avio_w8(pb, 0); /* code type */ 00080 avio_w8(pb, 0); /* status */ 00081 avio_w8(pb, 0); /* counts */ 00082 avio_write(pb, "VN:libavcodec,", sizeof("VN:libavcodec,") -1); /* metadata ("ST:songtitle,VN:version,...") */ 00083 end_tag_be(pb, pos); 00084 00085 avio_write(pb, "ATR\x00", 4); 00086 avio_wb32(pb, 0); 00087 mmf->atrpos = avio_tell(pb); 00088 avio_w8(pb, 0); /* format type */ 00089 avio_w8(pb, 0); /* sequence type */ 00090 avio_w8(pb, (0 << 7) | (1 << 4) | rate); /* (channel << 7) | (format << 4) | rate */ 00091 avio_w8(pb, 0); /* wave base bit */ 00092 avio_w8(pb, 2); /* time base d */ 00093 avio_w8(pb, 2); /* time base g */ 00094 00095 ffio_wfourcc(pb, "Atsq"); 00096 avio_wb32(pb, 16); 00097 mmf->atsqpos = avio_tell(pb); 00098 /* Will be filled on close */ 00099 avio_write(pb, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16); 00100 00101 mmf->awapos = ff_start_tag(pb, "Awa\x01"); 00102 00103 av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); 00104 00105 avio_flush(pb); 00106 00107 return 0; 00108 } 00109 00110 static int mmf_write_packet(AVFormatContext *s, AVPacket *pkt) 00111 { 00112 AVIOContext *pb = s->pb; 00113 avio_write(pb, pkt->data, pkt->size); 00114 return 0; 00115 } 00116 00117 /* Write a variable-length symbol */ 00118 static void put_varlength(AVIOContext *pb, int val) 00119 { 00120 if(val < 128) 00121 avio_w8(pb, val); 00122 else { 00123 val -= 128; 00124 avio_w8(pb, 0x80 | val >> 7); 00125 avio_w8(pb, 0x7f & val); 00126 } 00127 } 00128 00129 static int mmf_write_trailer(AVFormatContext *s) 00130 { 00131 AVIOContext *pb = s->pb; 00132 MMFContext *mmf = s->priv_data; 00133 int64_t pos, size; 00134 int gatetime; 00135 00136 if (s->pb->seekable) { 00137 /* Fill in length fields */ 00138 end_tag_be(pb, mmf->awapos); 00139 end_tag_be(pb, mmf->atrpos); 00140 end_tag_be(pb, 8); 00141 00142 pos = avio_tell(pb); 00143 size = pos - mmf->awapos; 00144 00145 /* Fill Atsq chunk */ 00146 avio_seek(pb, mmf->atsqpos, SEEK_SET); 00147 00148 /* "play wav" */ 00149 avio_w8(pb, 0); /* start time */ 00150 avio_w8(pb, 1); /* (channel << 6) | wavenum */ 00151 gatetime = size * 500 / s->streams[0]->codec->sample_rate; 00152 put_varlength(pb, gatetime); /* duration */ 00153 00154 /* "nop" */ 00155 put_varlength(pb, gatetime); /* start time */ 00156 avio_write(pb, "\xff\x00", 2); /* nop */ 00157 00158 /* "end of sequence" */ 00159 avio_write(pb, "\x00\x00\x00\x00", 4); 00160 00161 avio_seek(pb, pos, SEEK_SET); 00162 00163 avio_flush(pb); 00164 } 00165 return 0; 00166 } 00167 #endif /* CONFIG_MMF_MUXER */ 00168 00169 static int mmf_probe(AVProbeData *p) 00170 { 00171 /* check file header */ 00172 if (p->buf[0] == 'M' && p->buf[1] == 'M' && 00173 p->buf[2] == 'M' && p->buf[3] == 'D' && 00174 p->buf[8] == 'C' && p->buf[9] == 'N' && 00175 p->buf[10] == 'T' && p->buf[11] == 'I') 00176 return AVPROBE_SCORE_MAX; 00177 else 00178 return 0; 00179 } 00180 00181 /* mmf input */ 00182 static int mmf_read_header(AVFormatContext *s, 00183 AVFormatParameters *ap) 00184 { 00185 MMFContext *mmf = s->priv_data; 00186 unsigned int tag; 00187 AVIOContext *pb = s->pb; 00188 AVStream *st; 00189 int64_t size; 00190 int rate, params; 00191 00192 tag = avio_rl32(pb); 00193 if (tag != MKTAG('M', 'M', 'M', 'D')) 00194 return -1; 00195 avio_skip(pb, 4); /* file_size */ 00196 00197 /* Skip some unused chunks that may or may not be present */ 00198 for(;; avio_skip(pb, size)) { 00199 tag = avio_rl32(pb); 00200 size = avio_rb32(pb); 00201 if(tag == MKTAG('C','N','T','I')) continue; 00202 if(tag == MKTAG('O','P','D','A')) continue; 00203 break; 00204 } 00205 00206 /* Tag = "ATRx", where "x" = track number */ 00207 if ((tag & 0xffffff) == MKTAG('M', 'T', 'R', 0)) { 00208 av_log(s, AV_LOG_ERROR, "MIDI like format found, unsupported\n"); 00209 return -1; 00210 } 00211 if ((tag & 0xffffff) != MKTAG('A', 'T', 'R', 0)) { 00212 av_log(s, AV_LOG_ERROR, "Unsupported SMAF chunk %08x\n", tag); 00213 return -1; 00214 } 00215 00216 avio_r8(pb); /* format type */ 00217 avio_r8(pb); /* sequence type */ 00218 params = avio_r8(pb); /* (channel << 7) | (format << 4) | rate */ 00219 rate = mmf_rate(params & 0x0f); 00220 if(rate < 0) { 00221 av_log(s, AV_LOG_ERROR, "Invalid sample rate\n"); 00222 return -1; 00223 } 00224 avio_r8(pb); /* wave base bit */ 00225 avio_r8(pb); /* time base d */ 00226 avio_r8(pb); /* time base g */ 00227 00228 /* Skip some unused chunks that may or may not be present */ 00229 for(;; avio_skip(pb, size)) { 00230 tag = avio_rl32(pb); 00231 size = avio_rb32(pb); 00232 if(tag == MKTAG('A','t','s','q')) continue; 00233 if(tag == MKTAG('A','s','p','I')) continue; 00234 break; 00235 } 00236 00237 /* Make sure it's followed by an Awa chunk, aka wave data */ 00238 if ((tag & 0xffffff) != MKTAG('A', 'w', 'a', 0)) { 00239 av_log(s, AV_LOG_ERROR, "Unexpected SMAF chunk %08x\n", tag); 00240 return -1; 00241 } 00242 mmf->data_size = size; 00243 00244 st = av_new_stream(s, 0); 00245 if (!st) 00246 return AVERROR(ENOMEM); 00247 00248 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00249 st->codec->codec_id = CODEC_ID_ADPCM_YAMAHA; 00250 st->codec->sample_rate = rate; 00251 st->codec->channels = 1; 00252 st->codec->bits_per_coded_sample = 4; 00253 st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample; 00254 00255 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00256 00257 return 0; 00258 } 00259 00260 #define MAX_SIZE 4096 00261 00262 static int mmf_read_packet(AVFormatContext *s, 00263 AVPacket *pkt) 00264 { 00265 MMFContext *mmf = s->priv_data; 00266 int ret, size; 00267 00268 if (s->pb->eof_reached) 00269 return AVERROR(EIO); 00270 00271 size = MAX_SIZE; 00272 if(size > mmf->data_size) 00273 size = mmf->data_size; 00274 00275 if(!size) 00276 return AVERROR(EIO); 00277 00278 if (av_new_packet(pkt, size)) 00279 return AVERROR(EIO); 00280 pkt->stream_index = 0; 00281 00282 ret = avio_read(s->pb, pkt->data, pkt->size); 00283 if (ret < 0) 00284 av_free_packet(pkt); 00285 00286 mmf->data_size -= ret; 00287 00288 pkt->size = ret; 00289 return ret; 00290 } 00291 00292 #if CONFIG_MMF_DEMUXER 00293 AVInputFormat ff_mmf_demuxer = { 00294 "mmf", 00295 NULL_IF_CONFIG_SMALL("Yamaha SMAF"), 00296 sizeof(MMFContext), 00297 mmf_probe, 00298 mmf_read_header, 00299 mmf_read_packet, 00300 NULL, 00301 pcm_read_seek, 00302 }; 00303 #endif 00304 #if CONFIG_MMF_MUXER 00305 AVOutputFormat ff_mmf_muxer = { 00306 "mmf", 00307 NULL_IF_CONFIG_SMALL("Yamaha SMAF"), 00308 "application/vnd.smaf", 00309 "mmf", 00310 sizeof(MMFContext), 00311 CODEC_ID_ADPCM_YAMAHA, 00312 CODEC_ID_NONE, 00313 mmf_write_header, 00314 mmf_write_packet, 00315 mmf_write_trailer, 00316 }; 00317 #endif