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 "internal.h"
00023 #include "avio_internal.h"
00024 #include "pcm.h"
00025 #include "riff.h"
00026
00027 typedef struct {
00028 int64_t atrpos, atsqpos, awapos;
00029 int64_t data_size;
00030 } MMFContext;
00031
00032 static const int mmf_rates[] = { 4000, 8000, 11025, 22050, 44100 };
00033
00034 static int mmf_rate(int code)
00035 {
00036 if((code < 0) || (code > 4))
00037 return -1;
00038 return mmf_rates[code];
00039 }
00040
00041 #if CONFIG_MMF_MUXER
00042 static int mmf_rate_code(int rate)
00043 {
00044 int i;
00045 for(i = 0; i < 5; i++)
00046 if(mmf_rates[i] == rate)
00047 return i;
00048 return -1;
00049 }
00050
00051
00052 static void end_tag_be(AVIOContext *pb, int64_t start)
00053 {
00054 int64_t pos;
00055
00056 pos = avio_tell(pb);
00057 avio_seek(pb, start - 4, SEEK_SET);
00058 avio_wb32(pb, (uint32_t)(pos - start));
00059 avio_seek(pb, pos, SEEK_SET);
00060 }
00061
00062 static int mmf_write_header(AVFormatContext *s)
00063 {
00064 MMFContext *mmf = s->priv_data;
00065 AVIOContext *pb = s->pb;
00066 int64_t pos;
00067 int rate;
00068
00069 rate = mmf_rate_code(s->streams[0]->codec->sample_rate);
00070 if(rate < 0) {
00071 av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d\n", s->streams[0]->codec->sample_rate);
00072 return -1;
00073 }
00074
00075 ffio_wfourcc(pb, "MMMD");
00076 avio_wb32(pb, 0);
00077 pos = ff_start_tag(pb, "CNTI");
00078 avio_w8(pb, 0);
00079 avio_w8(pb, 0);
00080 avio_w8(pb, 0);
00081 avio_w8(pb, 0);
00082 avio_w8(pb, 0);
00083 avio_write(pb, "VN:libavcodec,", sizeof("VN:libavcodec,") -1);
00084 end_tag_be(pb, pos);
00085
00086 avio_write(pb, "ATR\x00", 4);
00087 avio_wb32(pb, 0);
00088 mmf->atrpos = avio_tell(pb);
00089 avio_w8(pb, 0);
00090 avio_w8(pb, 0);
00091 avio_w8(pb, (0 << 7) | (1 << 4) | rate);
00092 avio_w8(pb, 0);
00093 avio_w8(pb, 2);
00094 avio_w8(pb, 2);
00095
00096 ffio_wfourcc(pb, "Atsq");
00097 avio_wb32(pb, 16);
00098 mmf->atsqpos = avio_tell(pb);
00099
00100 avio_write(pb, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
00101
00102 mmf->awapos = ff_start_tag(pb, "Awa\x01");
00103
00104 avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
00105
00106 avio_flush(pb);
00107
00108 return 0;
00109 }
00110
00111 static int mmf_write_packet(AVFormatContext *s, AVPacket *pkt)
00112 {
00113 AVIOContext *pb = s->pb;
00114 avio_write(pb, pkt->data, pkt->size);
00115 return 0;
00116 }
00117
00118
00119 static void put_varlength(AVIOContext *pb, int val)
00120 {
00121 if(val < 128)
00122 avio_w8(pb, val);
00123 else {
00124 val -= 128;
00125 avio_w8(pb, 0x80 | val >> 7);
00126 avio_w8(pb, 0x7f & val);
00127 }
00128 }
00129
00130 static int mmf_write_trailer(AVFormatContext *s)
00131 {
00132 AVIOContext *pb = s->pb;
00133 MMFContext *mmf = s->priv_data;
00134 int64_t pos, size;
00135 int gatetime;
00136
00137 if (s->pb->seekable) {
00138
00139 end_tag_be(pb, mmf->awapos);
00140 end_tag_be(pb, mmf->atrpos);
00141 end_tag_be(pb, 8);
00142
00143 pos = avio_tell(pb);
00144 size = pos - mmf->awapos;
00145
00146
00147 avio_seek(pb, mmf->atsqpos, SEEK_SET);
00148
00149
00150 avio_w8(pb, 0);
00151 avio_w8(pb, 1);
00152 gatetime = size * 500 / s->streams[0]->codec->sample_rate;
00153 put_varlength(pb, gatetime);
00154
00155
00156 put_varlength(pb, gatetime);
00157 avio_write(pb, "\xff\x00", 2);
00158
00159
00160 avio_write(pb, "\x00\x00\x00\x00", 4);
00161
00162 avio_seek(pb, pos, SEEK_SET);
00163
00164 avio_flush(pb);
00165 }
00166 return 0;
00167 }
00168 #endif
00169
00170 static int mmf_probe(AVProbeData *p)
00171 {
00172
00173 if (p->buf[0] == 'M' && p->buf[1] == 'M' &&
00174 p->buf[2] == 'M' && p->buf[3] == 'D' &&
00175 p->buf[8] == 'C' && p->buf[9] == 'N' &&
00176 p->buf[10] == 'T' && p->buf[11] == 'I')
00177 return AVPROBE_SCORE_MAX;
00178 else
00179 return 0;
00180 }
00181
00182
00183 static int mmf_read_header(AVFormatContext *s,
00184 AVFormatParameters *ap)
00185 {
00186 MMFContext *mmf = s->priv_data;
00187 unsigned int tag;
00188 AVIOContext *pb = s->pb;
00189 AVStream *st;
00190 int64_t size;
00191 int rate, params;
00192
00193 tag = avio_rl32(pb);
00194 if (tag != MKTAG('M', 'M', 'M', 'D'))
00195 return -1;
00196 avio_skip(pb, 4);
00197
00198
00199 for(;; avio_skip(pb, size)) {
00200 tag = avio_rl32(pb);
00201 size = avio_rb32(pb);
00202 if(tag == MKTAG('C','N','T','I')) continue;
00203 if(tag == MKTAG('O','P','D','A')) continue;
00204 break;
00205 }
00206
00207
00208 if ((tag & 0xffffff) == MKTAG('M', 'T', 'R', 0)) {
00209 av_log(s, AV_LOG_ERROR, "MIDI like format found, unsupported\n");
00210 return -1;
00211 }
00212 if ((tag & 0xffffff) != MKTAG('A', 'T', 'R', 0)) {
00213 av_log(s, AV_LOG_ERROR, "Unsupported SMAF chunk %08x\n", tag);
00214 return -1;
00215 }
00216
00217 avio_r8(pb);
00218 avio_r8(pb);
00219 params = avio_r8(pb);
00220 rate = mmf_rate(params & 0x0f);
00221 if(rate < 0) {
00222 av_log(s, AV_LOG_ERROR, "Invalid sample rate\n");
00223 return -1;
00224 }
00225 avio_r8(pb);
00226 avio_r8(pb);
00227 avio_r8(pb);
00228
00229
00230 for(;; avio_skip(pb, size)) {
00231 tag = avio_rl32(pb);
00232 size = avio_rb32(pb);
00233 if(tag == MKTAG('A','t','s','q')) continue;
00234 if(tag == MKTAG('A','s','p','I')) continue;
00235 break;
00236 }
00237
00238
00239 if ((tag & 0xffffff) != MKTAG('A', 'w', 'a', 0)) {
00240 av_log(s, AV_LOG_ERROR, "Unexpected SMAF chunk %08x\n", tag);
00241 return -1;
00242 }
00243 mmf->data_size = size;
00244
00245 st = avformat_new_stream(s, NULL);
00246 if (!st)
00247 return AVERROR(ENOMEM);
00248
00249 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00250 st->codec->codec_id = CODEC_ID_ADPCM_YAMAHA;
00251 st->codec->sample_rate = rate;
00252 st->codec->channels = 1;
00253 st->codec->bits_per_coded_sample = 4;
00254 st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample;
00255
00256 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00257
00258 return 0;
00259 }
00260
00261 #define MAX_SIZE 4096
00262
00263 static int mmf_read_packet(AVFormatContext *s,
00264 AVPacket *pkt)
00265 {
00266 MMFContext *mmf = s->priv_data;
00267 int ret, size;
00268
00269 if (url_feof(s->pb))
00270 return AVERROR(EIO);
00271
00272 size = MAX_SIZE;
00273 if(size > mmf->data_size)
00274 size = mmf->data_size;
00275
00276 if(!size)
00277 return AVERROR(EIO);
00278
00279 if (av_new_packet(pkt, size))
00280 return AVERROR(EIO);
00281 pkt->stream_index = 0;
00282
00283 ret = avio_read(s->pb, pkt->data, pkt->size);
00284 if (ret < 0)
00285 av_free_packet(pkt);
00286
00287 mmf->data_size -= ret;
00288
00289 pkt->size = ret;
00290 return ret;
00291 }
00292
00293 #if CONFIG_MMF_DEMUXER
00294 AVInputFormat ff_mmf_demuxer = {
00295 .name = "mmf",
00296 .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
00297 .priv_data_size = sizeof(MMFContext),
00298 .read_probe = mmf_probe,
00299 .read_header = mmf_read_header,
00300 .read_packet = mmf_read_packet,
00301 .read_seek = pcm_read_seek,
00302 };
00303 #endif
00304 #if CONFIG_MMF_MUXER
00305 AVOutputFormat ff_mmf_muxer = {
00306 .name = "mmf",
00307 .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
00308 .mime_type = "application/vnd.smaf",
00309 .extensions = "mmf",
00310 .priv_data_size = sizeof(MMFContext),
00311 .audio_codec = CODEC_ID_ADPCM_YAMAHA,
00312 .video_codec = CODEC_ID_NONE,
00313 .write_header = mmf_write_header,
00314 .write_packet = mmf_write_packet,
00315 .write_trailer = mmf_write_trailer,
00316 };
00317 #endif