00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "avformat.h"
00031 #include "avio_internal.h"
00032 #include "pcm.h"
00033 #include "riff.h"
00034
00035
00036 #define AU_UNKNOWN_SIZE ((uint32_t)(~0))
00037
00038
00039 static const AVCodecTag codec_au_tags[] = {
00040 { CODEC_ID_PCM_MULAW, 1 },
00041 { CODEC_ID_PCM_S8, 2 },
00042 { CODEC_ID_PCM_S16BE, 3 },
00043 { CODEC_ID_PCM_S24BE, 4 },
00044 { CODEC_ID_PCM_S32BE, 5 },
00045 { CODEC_ID_PCM_F32BE, 6 },
00046 { CODEC_ID_PCM_F64BE, 7 },
00047 { CODEC_ID_PCM_ALAW, 27 },
00048 { CODEC_ID_NONE, 0 },
00049 };
00050
00051 #if CONFIG_AU_MUXER
00052
00053 static int put_au_header(AVIOContext *pb, AVCodecContext *enc)
00054 {
00055 if(!enc->codec_tag)
00056 return -1;
00057 ffio_wfourcc(pb, ".snd");
00058 avio_wb32(pb, 24);
00059 avio_wb32(pb, AU_UNKNOWN_SIZE);
00060 avio_wb32(pb, (uint32_t)enc->codec_tag);
00061 avio_wb32(pb, enc->sample_rate);
00062 avio_wb32(pb, (uint32_t)enc->channels);
00063 return 0;
00064 }
00065
00066 static int au_write_header(AVFormatContext *s)
00067 {
00068 AVIOContext *pb = s->pb;
00069
00070 s->priv_data = NULL;
00071
00072
00073 if (put_au_header(pb, s->streams[0]->codec) < 0) {
00074 return -1;
00075 }
00076
00077 avio_flush(pb);
00078
00079 return 0;
00080 }
00081
00082 static int au_write_packet(AVFormatContext *s, AVPacket *pkt)
00083 {
00084 AVIOContext *pb = s->pb;
00085 avio_write(pb, pkt->data, pkt->size);
00086 return 0;
00087 }
00088
00089 static int au_write_trailer(AVFormatContext *s)
00090 {
00091 AVIOContext *pb = s->pb;
00092 int64_t file_size;
00093
00094 if (s->pb->seekable) {
00095
00096
00097 file_size = avio_tell(pb);
00098 avio_seek(pb, 8, SEEK_SET);
00099 avio_wb32(pb, (uint32_t)(file_size - 24));
00100 avio_seek(pb, file_size, SEEK_SET);
00101
00102 avio_flush(pb);
00103 }
00104
00105 return 0;
00106 }
00107 #endif
00108
00109 static int au_probe(AVProbeData *p)
00110 {
00111
00112 if (p->buf[0] == '.' && p->buf[1] == 's' &&
00113 p->buf[2] == 'n' && p->buf[3] == 'd')
00114 return AVPROBE_SCORE_MAX;
00115 else
00116 return 0;
00117 }
00118
00119
00120 static int au_read_header(AVFormatContext *s,
00121 AVFormatParameters *ap)
00122 {
00123 int size;
00124 unsigned int tag;
00125 AVIOContext *pb = s->pb;
00126 unsigned int id, channels, rate;
00127 enum CodecID codec;
00128 AVStream *st;
00129
00130
00131 tag = avio_rl32(pb);
00132 if (tag != MKTAG('.', 's', 'n', 'd'))
00133 return -1;
00134 size = avio_rb32(pb);
00135 avio_rb32(pb);
00136
00137 id = avio_rb32(pb);
00138 rate = avio_rb32(pb);
00139 channels = avio_rb32(pb);
00140
00141 codec = ff_codec_get_id(codec_au_tags, id);
00142
00143 if (!av_get_bits_per_sample(codec)) {
00144 av_log_ask_for_sample(s, "could not determine bits per sample\n");
00145 return AVERROR_INVALIDDATA;
00146 }
00147
00148 if (size >= 24) {
00149
00150 avio_skip(pb, size - 24);
00151 }
00152
00153
00154 st = av_new_stream(s, 0);
00155 if (!st)
00156 return -1;
00157 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00158 st->codec->codec_tag = id;
00159 st->codec->codec_id = codec;
00160 st->codec->channels = channels;
00161 st->codec->sample_rate = rate;
00162 av_set_pts_info(st, 64, 1, rate);
00163 return 0;
00164 }
00165
00166 #define BLOCK_SIZE 1024
00167
00168 static int au_read_packet(AVFormatContext *s,
00169 AVPacket *pkt)
00170 {
00171 int ret;
00172
00173 ret= av_get_packet(s->pb, pkt, BLOCK_SIZE *
00174 s->streams[0]->codec->channels *
00175 av_get_bits_per_sample(s->streams[0]->codec->codec_id) >> 3);
00176 if (ret < 0)
00177 return ret;
00178 pkt->stream_index = 0;
00179
00180
00181
00182 pkt->size = ret;
00183 return 0;
00184 }
00185
00186 #if CONFIG_AU_DEMUXER
00187 AVInputFormat ff_au_demuxer = {
00188 "au",
00189 NULL_IF_CONFIG_SMALL("SUN AU format"),
00190 0,
00191 au_probe,
00192 au_read_header,
00193 au_read_packet,
00194 NULL,
00195 pcm_read_seek,
00196 .codec_tag= (const AVCodecTag* const []){codec_au_tags, 0},
00197 };
00198 #endif
00199
00200 #if CONFIG_AU_MUXER
00201 AVOutputFormat ff_au_muxer = {
00202 "au",
00203 NULL_IF_CONFIG_SMALL("SUN AU format"),
00204 "audio/basic",
00205 "au",
00206 0,
00207 CODEC_ID_PCM_S16BE,
00208 CODEC_ID_NONE,
00209 au_write_header,
00210 au_write_packet,
00211 au_write_trailer,
00212 .codec_tag= (const AVCodecTag* const []){codec_au_tags, 0},
00213 };
00214 #endif //CONFIG_AU_MUXER