00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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);
00078 avio_w8(pb, 0);
00079 avio_w8(pb, 0);
00080 avio_w8(pb, 0);
00081 avio_w8(pb, 0);
00082 avio_write(pb, "VN:libavcodec,", sizeof("VN:libavcodec,") -1);
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);
00089 avio_w8(pb, 0);
00090 avio_w8(pb, (0 << 7) | (1 << 4) | rate);
00091 avio_w8(pb, 0);
00092 avio_w8(pb, 2);
00093 avio_w8(pb, 2);
00094
00095 ffio_wfourcc(pb, "Atsq");
00096 avio_wb32(pb, 16);
00097 mmf->atsqpos = avio_tell(pb);
00098
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
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
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
00146 avio_seek(pb, mmf->atsqpos, SEEK_SET);
00147
00148
00149 avio_w8(pb, 0);
00150 avio_w8(pb, 1);
00151 gatetime = size * 500 / s->streams[0]->codec->sample_rate;
00152 put_varlength(pb, gatetime);
00153
00154
00155 put_varlength(pb, gatetime);
00156 avio_write(pb, "\xff\x00", 2);
00157
00158
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
00168
00169 static int mmf_probe(AVProbeData *p)
00170 {
00171
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
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);
00196
00197
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
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);
00217 avio_r8(pb);
00218 params = avio_r8(pb);
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);
00225 avio_r8(pb);
00226 avio_r8(pb);
00227
00228
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
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 (url_feof(s->pb))
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