3 * Copyright (c) 2005 Vidar Madsen
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "config_components.h"
24 #include "libavutil/channel_layout.h"
26 #include "avio_internal.h"
35 typedef struct MMFContext
{
36 int64_t atrpos
, atsqpos
, awapos
;
41 static const int mmf_rates
[] = { 4000, 8000, 11025, 22050, 44100 };
43 static int mmf_rate(int code
)
45 if ((code
< 0) || (code
> 4))
47 return mmf_rates
[code
];
51 static int mmf_rate_code(int rate
)
54 for (i
= 0; i
< 5; i
++)
55 if (mmf_rates
[i
] == rate
)
60 /* Copy of end_tag() from avienc.c, but for big-endian chunk size */
61 static void end_tag_be(AVIOContext
*pb
, int64_t start
)
66 avio_seek(pb
, start
- 4, SEEK_SET
);
67 avio_wb32(pb
, (uint32_t)(pos
- start
));
68 avio_seek(pb
, pos
, SEEK_SET
);
71 static int mmf_write_header(AVFormatContext
*s
)
73 MMFContext
*mmf
= s
->priv_data
;
74 AVIOContext
*pb
= s
->pb
;
77 const char *version
= s
->flags
& AVFMT_FLAG_BITEXACT
?
79 "VN:"LIBAVFORMAT_IDENT
",";
81 rate
= mmf_rate_code(s
->streams
[0]->codecpar
->sample_rate
);
83 av_log(s
, AV_LOG_ERROR
, "Unsupported sample rate %d, supported are 4000, 8000, 11025, 22050 and 44100\n",
84 s
->streams
[0]->codecpar
->sample_rate
);
85 return AVERROR(EINVAL
);
88 mmf
->stereo
= s
->streams
[0]->codecpar
->ch_layout
.nb_channels
> 1;
90 s
->strict_std_compliance
> FF_COMPLIANCE_EXPERIMENTAL
) {
91 av_log(s
, AV_LOG_ERROR
, "Yamaha SMAF stereo is experimental, "
92 "add '-strict %d' if you want to use it.\n",
93 FF_COMPLIANCE_EXPERIMENTAL
);
94 return AVERROR(EINVAL
);
97 ffio_wfourcc(pb
, "MMMD");
99 pos
= ff_start_tag(pb
, "CNTI");
100 avio_w8(pb
, 0); /* class */
101 avio_w8(pb
, 1); /* type */
102 avio_w8(pb
, 1); /* code type */
103 avio_w8(pb
, 0); /* status */
104 avio_w8(pb
, 0); /* counts */
107 pos
= ff_start_tag(pb
, "OPDA");
108 avio_write(pb
, version
, strlen(version
)); /* metadata ("ST:songtitle,VN:version,...") */
111 avio_write(pb
, "ATR\x00", 4);
113 mmf
->atrpos
= avio_tell(pb
);
114 avio_w8(pb
, 0); /* format type */
115 avio_w8(pb
, 0); /* sequence type */
116 avio_w8(pb
, (mmf
->stereo
<< 7) | (1 << 4) | rate
); /* (channel << 7) | (format << 4) | rate */
117 avio_w8(pb
, 0); /* wave base bit */
118 avio_w8(pb
, 2); /* time base d */
119 avio_w8(pb
, 2); /* time base g */
121 ffio_wfourcc(pb
, "Atsq");
123 mmf
->atsqpos
= avio_tell(pb
);
124 /* Will be filled on close */
125 avio_write(pb
, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
127 mmf
->awapos
= ff_start_tag(pb
, "Awa\x01");
129 avpriv_set_pts_info(s
->streams
[0], 64, 1, s
->streams
[0]->codecpar
->sample_rate
);
134 /* Write a variable-length symbol */
135 static void put_varlength(AVIOContext
*pb
, int val
)
141 avio_w8(pb
, 0x80 | val
>> 7);
142 avio_w8(pb
, 0x7f & val
);
146 static int mmf_write_trailer(AVFormatContext
*s
)
148 AVIOContext
*pb
= s
->pb
;
149 MMFContext
*mmf
= s
->priv_data
;
153 if (s
->pb
->seekable
& AVIO_SEEKABLE_NORMAL
) {
154 /* Fill in length fields */
155 end_tag_be(pb
, mmf
->awapos
);
156 end_tag_be(pb
, mmf
->atrpos
);
160 size
= pos
- mmf
->awapos
;
162 /* Fill Atsq chunk */
163 avio_seek(pb
, mmf
->atsqpos
, SEEK_SET
);
166 avio_w8(pb
, 0); /* start time */
167 avio_w8(pb
, (mmf
->stereo
<< 6) | 1); /* (channel << 6) | wavenum */
168 gatetime
= size
* 500 / s
->streams
[0]->codecpar
->sample_rate
;
169 put_varlength(pb
, gatetime
); /* duration */
172 put_varlength(pb
, gatetime
); /* start time */
173 avio_write(pb
, "\xff\x00", 2); /* nop */
175 /* "end of sequence" */
176 avio_write(pb
, "\x00\x00\x00\x00", 4);
178 avio_seek(pb
, pos
, SEEK_SET
);
182 #endif /* CONFIG_MMF_MUXER */
184 static int mmf_probe(const AVProbeData
*p
)
186 /* check file header */
187 if (p
->buf
[0] == 'M' && p
->buf
[1] == 'M' &&
188 p
->buf
[2] == 'M' && p
->buf
[3] == 'D' &&
189 p
->buf
[8] == 'C' && p
->buf
[9] == 'N' &&
190 p
->buf
[10] == 'T' && p
->buf
[11] == 'I')
191 return AVPROBE_SCORE_MAX
;
197 static int mmf_read_header(AVFormatContext
*s
)
199 MMFContext
*mmf
= s
->priv_data
;
201 AVIOContext
*pb
= s
->pb
;
207 if (tag
!= MKTAG('M', 'M', 'M', 'D'))
208 return AVERROR_INVALIDDATA
;
209 avio_skip(pb
, 4); /* file_size */
211 /* Skip some unused chunks that may or may not be present */
212 for (;; avio_skip(pb
, size
)) {
214 size
= avio_rb32(pb
);
215 if (tag
== MKTAG('C', 'N', 'T', 'I'))
217 if (tag
== MKTAG('O', 'P', 'D', 'A'))
222 /* Tag = "ATRx", where "x" = track number */
223 if ((tag
& 0xffffff) == MKTAG('M', 'T', 'R', 0)) {
224 av_log(s
, AV_LOG_ERROR
, "MIDI like format found, unsupported\n");
225 return AVERROR_PATCHWELCOME
;
227 if ((tag
& 0xffffff) != MKTAG('A', 'T', 'R', 0)) {
228 av_log(s
, AV_LOG_ERROR
, "Unsupported SMAF chunk %08x\n", tag
);
229 return AVERROR_PATCHWELCOME
;
232 avio_r8(pb
); /* format type */
233 avio_r8(pb
); /* sequence type */
234 params
= avio_r8(pb
); /* (channel << 7) | (format << 4) | rate */
235 rate
= mmf_rate(params
& 0x0f);
237 av_log(s
, AV_LOG_ERROR
, "Invalid sample rate\n");
238 return AVERROR_INVALIDDATA
;
240 avio_r8(pb
); /* wave base bit */
241 avio_r8(pb
); /* time base d */
242 avio_r8(pb
); /* time base g */
244 /* Skip some unused chunks that may or may not be present */
245 for (;; avio_skip(pb
, size
)) {
247 size
= avio_rb32(pb
);
248 if (tag
== MKTAG('A', 't', 's', 'q'))
250 if (tag
== MKTAG('A', 's', 'p', 'I'))
255 /* Make sure it's followed by an Awa chunk, aka wave data */
256 if ((tag
& 0xffffff) != MKTAG('A', 'w', 'a', 0)) {
257 av_log(s
, AV_LOG_ERROR
, "Unexpected SMAF chunk %08x\n", tag
);
258 return AVERROR_INVALIDDATA
;
260 mmf
->data_end
= avio_tell(pb
) + size
;
262 st
= avformat_new_stream(s
, NULL
);
264 return AVERROR(ENOMEM
);
266 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
267 st
->codecpar
->codec_id
= AV_CODEC_ID_ADPCM_YAMAHA
;
268 st
->codecpar
->sample_rate
= rate
;
269 av_channel_layout_default(&st
->codecpar
->ch_layout
, (params
>> 7) + 1);
270 st
->codecpar
->bits_per_coded_sample
= 4;
271 st
->codecpar
->bit_rate
= st
->codecpar
->sample_rate
*
272 st
->codecpar
->bits_per_coded_sample
;
274 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
279 #define MAX_SIZE 4096
281 static int mmf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
283 MMFContext
*mmf
= s
->priv_data
;
287 left
= mmf
->data_end
- avio_tell(s
->pb
);
288 size
= FFMIN(left
, MAX_SIZE
);
289 if (avio_feof(s
->pb
) || size
<= 0)
292 ret
= av_get_packet(s
->pb
, pkt
, size
);
296 pkt
->stream_index
= 0;
301 #if CONFIG_MMF_DEMUXER
302 const FFInputFormat ff_mmf_demuxer
= {
304 .p
.long_name
= NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
305 .p
.flags
= AVFMT_GENERIC_INDEX
,
306 .priv_data_size
= sizeof(MMFContext
),
307 .read_probe
= mmf_probe
,
308 .read_header
= mmf_read_header
,
309 .read_packet
= mmf_read_packet
,
314 const FFOutputFormat ff_mmf_muxer
= {
316 .p
.long_name
= NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
317 .p
.mime_type
= "application/vnd.smaf",
318 .p
.extensions
= "mmf",
319 .priv_data_size
= sizeof(MMFContext
),
320 .p
.audio_codec
= AV_CODEC_ID_ADPCM_YAMAHA
,
321 .p
.video_codec
= AV_CODEC_ID_NONE
,
322 .p
.subtitle_codec
= AV_CODEC_ID_NONE
,
323 .flags_internal
= FF_OFMT_FLAG_MAX_ONE_OF_EACH
|
324 FF_OFMT_FLAG_ONLY_DEFAULT_CODECS
,
325 .write_header
= mmf_write_header
,
326 .write_packet
= ff_raw_write_packet
,
327 .write_trailer
= mmf_write_trailer
,