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