mmf.c
Go to the documentation of this file.
1 /*
2  * Yamaha SMAF format
3  * Copyright (c) 2005 Vidar Madsen
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21 
23 #include "avformat.h"
24 #include "internal.h"
25 #include "avio_internal.h"
26 #include "pcm.h"
27 #include "rawenc.h"
28 #include "riff.h"
29 
30 typedef struct {
31  int64_t atrpos, atsqpos, awapos;
32  int64_t data_end;
33  int stereo;
34 } MMFContext;
35 
36 static const int mmf_rates[] = { 4000, 8000, 11025, 22050, 44100 };
37 
38 static int mmf_rate(int code)
39 {
40  if((code < 0) || (code > 4))
41  return -1;
42  return mmf_rates[code];
43 }
44 
45 #if CONFIG_MMF_MUXER
46 static int mmf_rate_code(int rate)
47 {
48  int i;
49  for(i = 0; i < 5; i++)
50  if(mmf_rates[i] == rate)
51  return i;
52  return -1;
53 }
54 
55 /* Copy of end_tag() from avienc.c, but for big-endian chunk size */
56 static void end_tag_be(AVIOContext *pb, int64_t start)
57 {
58  int64_t pos;
59 
60  pos = avio_tell(pb);
61  avio_seek(pb, start - 4, SEEK_SET);
62  avio_wb32(pb, (uint32_t)(pos - start));
63  avio_seek(pb, pos, SEEK_SET);
64 }
65 
66 static int mmf_write_header(AVFormatContext *s)
67 {
68  MMFContext *mmf = s->priv_data;
69  AVIOContext *pb = s->pb;
70  int64_t pos;
71  int rate;
72  const char *version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ?
73  "VN:Lavf," :
74  "VN:"LIBAVFORMAT_IDENT",";
75 
76  rate = mmf_rate_code(s->streams[0]->codec->sample_rate);
77  if(rate < 0) {
78  av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d, supported are 4000, 8000, 11025, 22050 and 44100\n", s->streams[0]->codec->sample_rate);
79  return AVERROR(EINVAL);
80  }
81 
82  mmf->stereo = s->streams[0]->codec->channels > 1;
83  if (mmf->stereo &&
85  av_log(s, AV_LOG_ERROR, "Yamaha SMAF stereo is experimental, "
86  "add '-strict %d' if you want to use it.\n",
88  return AVERROR(EINVAL);
89  }
90 
91  ffio_wfourcc(pb, "MMMD");
92  avio_wb32(pb, 0);
93  pos = ff_start_tag(pb, "CNTI");
94  avio_w8(pb, 0); /* class */
95  avio_w8(pb, 1); /* type */
96  avio_w8(pb, 1); /* code type */
97  avio_w8(pb, 0); /* status */
98  avio_w8(pb, 0); /* counts */
99  end_tag_be(pb, pos);
100  pos = ff_start_tag(pb, "OPDA");
101  avio_write(pb, version, strlen(version)); /* metadata ("ST:songtitle,VN:version,...") */
102  end_tag_be(pb, pos);
103 
104  avio_write(pb, "ATR\x00", 4);
105  avio_wb32(pb, 0);
106  mmf->atrpos = avio_tell(pb);
107  avio_w8(pb, 0); /* format type */
108  avio_w8(pb, 0); /* sequence type */
109  avio_w8(pb, (mmf->stereo << 7) | (1 << 4) | rate); /* (channel << 7) | (format << 4) | rate */
110  avio_w8(pb, 0); /* wave base bit */
111  avio_w8(pb, 2); /* time base d */
112  avio_w8(pb, 2); /* time base g */
113 
114  ffio_wfourcc(pb, "Atsq");
115  avio_wb32(pb, 16);
116  mmf->atsqpos = avio_tell(pb);
117  /* Will be filled on close */
118  avio_write(pb, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
119 
120  mmf->awapos = ff_start_tag(pb, "Awa\x01");
121 
122  avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
123 
124  avio_flush(pb);
125 
126  return 0;
127 }
128 
129 /* Write a variable-length symbol */
130 static void put_varlength(AVIOContext *pb, int val)
131 {
132  if(val < 128)
133  avio_w8(pb, val);
134  else {
135  val -= 128;
136  avio_w8(pb, 0x80 | val >> 7);
137  avio_w8(pb, 0x7f & val);
138  }
139 }
140 
141 static int mmf_write_trailer(AVFormatContext *s)
142 {
143  AVIOContext *pb = s->pb;
144  MMFContext *mmf = s->priv_data;
145  int64_t pos, size;
146  int gatetime;
147 
148  if (s->pb->seekable) {
149  /* Fill in length fields */
150  end_tag_be(pb, mmf->awapos);
151  end_tag_be(pb, mmf->atrpos);
152  end_tag_be(pb, 8);
153 
154  pos = avio_tell(pb);
155  size = pos - mmf->awapos;
156 
157  /* Fill Atsq chunk */
158  avio_seek(pb, mmf->atsqpos, SEEK_SET);
159 
160  /* "play wav" */
161  avio_w8(pb, 0); /* start time */
162  avio_w8(pb, (mmf->stereo << 6) | 1); /* (channel << 6) | wavenum */
163  gatetime = size * 500 / s->streams[0]->codec->sample_rate;
164  put_varlength(pb, gatetime); /* duration */
165 
166  /* "nop" */
167  put_varlength(pb, gatetime); /* start time */
168  avio_write(pb, "\xff\x00", 2); /* nop */
169 
170  /* "end of sequence" */
171  avio_write(pb, "\x00\x00\x00\x00", 4);
172 
173  avio_seek(pb, pos, SEEK_SET);
174 
175  avio_flush(pb);
176  }
177  return 0;
178 }
179 #endif /* CONFIG_MMF_MUXER */
180 
181 static int mmf_probe(AVProbeData *p)
182 {
183  /* check file header */
184  if (p->buf[0] == 'M' && p->buf[1] == 'M' &&
185  p->buf[2] == 'M' && p->buf[3] == 'D' &&
186  p->buf[8] == 'C' && p->buf[9] == 'N' &&
187  p->buf[10] == 'T' && p->buf[11] == 'I')
188  return AVPROBE_SCORE_MAX;
189  else
190  return 0;
191 }
192 
193 /* mmf input */
195 {
196  MMFContext *mmf = s->priv_data;
197  unsigned int tag;
198  AVIOContext *pb = s->pb;
199  AVStream *st;
200  int64_t size;
201  int rate, params;
202 
203  tag = avio_rl32(pb);
204  if (tag != MKTAG('M', 'M', 'M', 'D'))
205  return AVERROR_INVALIDDATA;
206  avio_skip(pb, 4); /* file_size */
207 
208  /* Skip some unused chunks that may or may not be present */
209  for(;; avio_skip(pb, size)) {
210  tag = avio_rl32(pb);
211  size = avio_rb32(pb);
212  if(tag == MKTAG('C','N','T','I')) continue;
213  if(tag == MKTAG('O','P','D','A')) continue;
214  break;
215  }
216 
217  /* Tag = "ATRx", where "x" = track number */
218  if ((tag & 0xffffff) == MKTAG('M', 'T', 'R', 0)) {
219  av_log(s, AV_LOG_ERROR, "MIDI like format found, unsupported\n");
220  return AVERROR_PATCHWELCOME;
221  }
222  if ((tag & 0xffffff) != MKTAG('A', 'T', 'R', 0)) {
223  av_log(s, AV_LOG_ERROR, "Unsupported SMAF chunk %08x\n", tag);
224  return AVERROR_PATCHWELCOME;
225  }
226 
227  avio_r8(pb); /* format type */
228  avio_r8(pb); /* sequence type */
229  params = avio_r8(pb); /* (channel << 7) | (format << 4) | rate */
230  rate = mmf_rate(params & 0x0f);
231  if(rate < 0) {
232  av_log(s, AV_LOG_ERROR, "Invalid sample rate\n");
233  return AVERROR_INVALIDDATA;
234  }
235  avio_r8(pb); /* wave base bit */
236  avio_r8(pb); /* time base d */
237  avio_r8(pb); /* time base g */
238 
239  /* Skip some unused chunks that may or may not be present */
240  for(;; avio_skip(pb, size)) {
241  tag = avio_rl32(pb);
242  size = avio_rb32(pb);
243  if(tag == MKTAG('A','t','s','q')) continue;
244  if(tag == MKTAG('A','s','p','I')) continue;
245  break;
246  }
247 
248  /* Make sure it's followed by an Awa chunk, aka wave data */
249  if ((tag & 0xffffff) != MKTAG('A', 'w', 'a', 0)) {
250  av_log(s, AV_LOG_ERROR, "Unexpected SMAF chunk %08x\n", tag);
251  return AVERROR_INVALIDDATA;
252  }
253  mmf->data_end = avio_tell(pb) + size;
254 
255  st = avformat_new_stream(s, NULL);
256  if (!st)
257  return AVERROR(ENOMEM);
258 
261  st->codec->sample_rate = rate;
262  st->codec->channels = (params >> 7) + 1;
264  st->codec->bits_per_coded_sample = 4;
266 
267  avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
268 
269  return 0;
270 }
271 
272 #define MAX_SIZE 4096
273 
275  AVPacket *pkt)
276 {
277  MMFContext *mmf = s->priv_data;
278  int64_t left, size;
279  int ret;
280 
281  left = mmf->data_end - avio_tell(s->pb);
282  size = FFMIN(left, MAX_SIZE);
283  if (url_feof(s->pb) || size <= 0)
284  return AVERROR_EOF;
285 
286  ret = av_get_packet(s->pb, pkt, size);
287  if (ret < 0)
288  return ret;
289 
290  pkt->stream_index = 0;
291 
292  return ret;
293 }
294 
295 #if CONFIG_MMF_DEMUXER
296 AVInputFormat ff_mmf_demuxer = {
297  .name = "mmf",
298  .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
299  .priv_data_size = sizeof(MMFContext),
304 };
305 #endif
306 #if CONFIG_MMF_MUXER
307 AVOutputFormat ff_mmf_muxer = {
308  .name = "mmf",
309  .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
310  .mime_type = "application/vnd.smaf",
311  .extensions = "mmf",
312  .priv_data_size = sizeof(MMFContext),
313  .audio_codec = AV_CODEC_ID_ADPCM_YAMAHA,
314  .video_codec = AV_CODEC_ID_NONE,
315  .write_header = mmf_write_header,
317  .write_trailer = mmf_write_trailer,
318 };
319 #endif
Definition: start.py:1
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int64_t awapos
Definition: mmf.c:31
int64_t ff_start_tag(AVIOContext *pb, const char *tag)
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
static int write_packet(AVFormatContext *s, AVPacket *pkt)
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
Definition: mmf.c:30
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:256
int version
Definition: avisynth_c.h:666
#define AV_CH_LAYOUT_STEREO
int stereo
Definition: mmf.c:33
static int mmf_probe(AVProbeData *p)
Definition: mmf.c:181
Format I/O context.
Definition: avformat.h:944
static int mmf_rate(int code)
Definition: mmf.c:38
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:610
static AVPacket pkt
Definition: demuxing.c:56
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVStream ** streams
Definition: avformat.h:992
uint32_t tag
Definition: movenc.c:894
#define AVERROR_EOF
End of file.
Definition: error.h:55
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
#define CODEC_FLAG_BITEXACT
Use only bitexact stuff (except (I)DCT).
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:173
#define MAX_SIZE
Definition: mmf.c:272
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:50
static int write_trailer(AVFormatContext *s)
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:579
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
int flags
CODEC_FLAG_*.
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int size
uint64_t channel_layout
Audio channel layout.
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
#define LIBAVFORMAT_IDENT
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:117
int bit_rate
the average bitrate
int void avio_flush(AVIOContext *s)
Force flushing of buffered data to the output s.
Definition: aviobuf.c:193
audio channel layout utility functions
#define FFMIN(a, b)
Definition: common.h:58
static int read_probe(AVProbeData *pd)
int64_t data_end
Definition: mmf.c:32
ret
Definition: avfilter.c:821
const char * name
Definition: avformat.h:378
internal header for RIFF based (de)muxers do NOT include this in end user applications ...
int ff_raw_write_packet(AVFormatContext *s, AVPacket *pkt)
int64_t atsqpos
Definition: mmf.c:31
int url_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:280
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
Stream structure.
Definition: avformat.h:643
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
NULL
Definition: eval.c:55
or the Software in violation of any applicable export control laws in any jurisdiction Except as provided by mandatorily applicable UPF has no obligation to provide you with source code to the Software In the event Software contains any source code
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:151
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:353
synthesis window for stochastic i
static int mmf_read_header(AVFormatContext *s)
Definition: mmf.c:194
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
static const int mmf_rates[]
Definition: mmf.c:36
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
const char const char * params
Definition: avisynth_c.h:675
Main libavformat public API header.
static int mmf_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mmf.c:274
int channels
number of audio channels
void * priv_data
Format private data.
Definition: avformat.h:964
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:470
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:299
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
#define AV_CH_LAYOUT_MONO
#define MKTAG(a, b, c, d)
Definition: common.h:282
This structure stores compressed data.
int strict_std_compliance
strictly follow the standard (MPEG4, ...).
int64_t atrpos
Definition: mmf.c:31