3 * Copyright (c) 2001 Fabrice Bellard
5 * first version by Francois Revol <revol@free.fr>
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Reference documents:
26 * http://www.opengroup.org/public/pubs/external/auformat.html
27 * http://www.goice.co.jp/member/mo/formats/au.html
32 #include "avio_internal.h"
34 #include "libavutil/avassert.h"
36 /* if we don't know the size in advance */
37 #define AU_UNKNOWN_SIZE ((uint32_t)(~0))
38 /* the specification requires an annotation field of at least eight bytes */
39 #define AU_HEADER_SIZE (24+8)
41 static const AVCodecTag codec_au_tags
[] = {
42 { AV_CODEC_ID_PCM_MULAW
, 1 },
43 { AV_CODEC_ID_PCM_S8
, 2 },
44 { AV_CODEC_ID_PCM_S16BE
, 3 },
45 { AV_CODEC_ID_PCM_S24BE
, 4 },
46 { AV_CODEC_ID_PCM_S32BE
, 5 },
47 { AV_CODEC_ID_PCM_F32BE
, 6 },
48 { AV_CODEC_ID_PCM_F64BE
, 7 },
49 { AV_CODEC_ID_ADPCM_G726LE
, 23 },
50 { AV_CODEC_ID_ADPCM_G722
,24 },
51 { AV_CODEC_ID_ADPCM_G726LE
, 25 },
52 { AV_CODEC_ID_ADPCM_G726LE
, 26 },
53 { AV_CODEC_ID_PCM_ALAW
, 27 },
54 { AV_CODEC_ID_ADPCM_G726LE
, MKBETAG('7','2','6','2') },
55 { AV_CODEC_ID_NONE
, 0 },
60 static int au_probe(AVProbeData
*p
)
62 if (p
->buf
[0] == '.' && p
->buf
[1] == 's' &&
63 p
->buf
[2] == 'n' && p
->buf
[3] == 'd')
64 return AVPROBE_SCORE_MAX
;
69 #define BLOCK_SIZE 1024
71 static int au_read_header(AVFormatContext
*s
)
73 int size
, data_size
= 0;
75 AVIOContext
*pb
= s
->pb
;
76 unsigned int id
, channels
, rate
;
82 if (tag
!= MKTAG('.', 's', 'n', 'd'))
83 return AVERROR_INVALIDDATA
;
84 size
= avio_rb32(pb
); /* header size */
85 data_size
= avio_rb32(pb
); /* data size in bytes */
87 if (data_size
< 0 && data_size
!= AU_UNKNOWN_SIZE
) {
88 av_log(s
, AV_LOG_ERROR
, "Invalid negative data size '%d' found\n", data_size
);
89 return AVERROR_INVALIDDATA
;
94 channels
= avio_rb32(pb
);
97 /* skip unused data */
98 avio_skip(pb
, size
- 24);
101 codec
= ff_codec_get_id(codec_au_tags
, id
);
103 if (codec
== AV_CODEC_ID_NONE
) {
104 avpriv_request_sample(s
, "unknown or unsupported codec tag: %u", id
);
105 return AVERROR_PATCHWELCOME
;
108 bps
= av_get_bits_per_sample(codec
);
109 if (codec
== AV_CODEC_ID_ADPCM_G726LE
) {
110 if (id
== MKBETAG('7','2','6','2')) {
113 const uint8_t bpcss
[] = {4, 0, 3, 5};
114 av_assert0(id
>= 23 && id
< 23 + 4);
115 bps
= bpcss
[id
- 23];
118 avpriv_request_sample(s
, "Unknown bits per sample");
119 return AVERROR_PATCHWELCOME
;
122 if (channels
== 0 || channels
>= INT_MAX
/ (BLOCK_SIZE
* bps
>> 3)) {
123 av_log(s
, AV_LOG_ERROR
, "Invalid number of channels %u\n", channels
);
124 return AVERROR_INVALIDDATA
;
127 if (rate
== 0 || rate
> INT_MAX
) {
128 av_log(s
, AV_LOG_ERROR
, "Invalid sample rate: %u\n", rate
);
129 return AVERROR_INVALIDDATA
;
132 st
= avformat_new_stream(s
, NULL
);
134 return AVERROR(ENOMEM
);
135 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
136 st
->codec
->codec_tag
= id
;
137 st
->codec
->codec_id
= codec
;
138 st
->codec
->channels
= channels
;
139 st
->codec
->sample_rate
= rate
;
140 st
->codec
->bits_per_coded_sample
= bps
;
141 st
->codec
->bit_rate
= channels
* rate
* bps
;
142 st
->codec
->block_align
= FFMAX(bps
* st
->codec
->channels
/ 8, 1);
143 if (data_size
!= AU_UNKNOWN_SIZE
)
144 st
->duration
= (((int64_t)data_size
)<<3) / (st
->codec
->channels
* (int64_t)bps
);
147 avpriv_set_pts_info(st
, 64, 1, rate
);
152 AVInputFormat ff_au_demuxer
= {
154 .long_name
= NULL_IF_CONFIG_SMALL("Sun AU"),
155 .read_probe
= au_probe
,
156 .read_header
= au_read_header
,
157 .read_packet
= ff_pcm_read_packet
,
158 .read_seek
= ff_pcm_read_seek
,
159 .codec_tag
= (const AVCodecTag
* const []) { codec_au_tags
, 0 },
162 #endif /* CONFIG_AU_DEMUXER */
168 static int au_write_header(AVFormatContext
*s
)
170 AVIOContext
*pb
= s
->pb
;
171 AVCodecContext
*enc
= s
->streams
[0]->codec
;
173 if (s
->nb_streams
!= 1) {
174 av_log(s
, AV_LOG_ERROR
, "only one stream is supported\n");
175 return AVERROR(EINVAL
);
178 enc
->codec_tag
= ff_codec_get_tag(codec_au_tags
, enc
->codec_id
);
179 if (!enc
->codec_tag
) {
180 av_log(s
, AV_LOG_ERROR
, "unsupported codec\n");
181 return AVERROR(EINVAL
);
184 ffio_wfourcc(pb
, ".snd"); /* magic number */
185 avio_wb32(pb
, AU_HEADER_SIZE
); /* header size */
186 avio_wb32(pb
, AU_UNKNOWN_SIZE
); /* data size */
187 avio_wb32(pb
, enc
->codec_tag
); /* codec ID */
188 avio_wb32(pb
, enc
->sample_rate
);
189 avio_wb32(pb
, enc
->channels
);
190 avio_wb64(pb
, 0); /* annotation field */
196 static int au_write_trailer(AVFormatContext
*s
)
198 AVIOContext
*pb
= s
->pb
;
199 int64_t file_size
= avio_tell(pb
);
201 if (s
->pb
->seekable
&& file_size
< INT32_MAX
) {
202 /* update file size */
203 avio_seek(pb
, 8, SEEK_SET
);
204 avio_wb32(pb
, (uint32_t)(file_size
- AU_HEADER_SIZE
));
205 avio_seek(pb
, file_size
, SEEK_SET
);
212 AVOutputFormat ff_au_muxer
= {
214 .long_name
= NULL_IF_CONFIG_SMALL("Sun AU"),
215 .mime_type
= "audio/basic",
217 .audio_codec
= AV_CODEC_ID_PCM_S16BE
,
218 .video_codec
= AV_CODEC_ID_NONE
,
219 .write_header
= au_write_header
,
220 .write_packet
= ff_raw_write_packet
,
221 .write_trailer
= au_write_trailer
,
222 .codec_tag
= (const AVCodecTag
* const []) { codec_au_tags
, 0 },
223 .flags
= AVFMT_NOTIMESTAMPS
,
226 #endif /* CONFIG_AU_MUXER */