X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fau.c;h=670ec79e5928108affddf22476fc83cda65f4109;hb=bdd00e2d1be31059bb772266d12ba418aa0f391a;hp=5121574c3ce6439a1b85f7393bdba2cc4c8f1abd;hpb=3b3bbdd3e63a3a1eaf69b861f72cf74f1669afe1;p=ffmpeg diff --git a/libavformat/au.c b/libavformat/au.c index 5121574c3ce..670ec79e592 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -28,83 +28,24 @@ */ #include "avformat.h" +#include "internal.h" #include "avio_internal.h" #include "pcm.h" -#include "riff.h" -/* if we don't know the size in advance */ -#define AU_UNKNOWN_SIZE ((uint32_t)(~0)) - -/* The ffmpeg codecs we support, and the IDs they have in the file */ +/* The libavcodec codecs we support, and the IDs they have in the file */ static const AVCodecTag codec_au_tags[] = { - { CODEC_ID_PCM_MULAW, 1 }, - { CODEC_ID_PCM_S8, 2 }, - { CODEC_ID_PCM_S16BE, 3 }, - { CODEC_ID_PCM_S24BE, 4 }, - { CODEC_ID_PCM_S32BE, 5 }, - { CODEC_ID_PCM_F32BE, 6 }, - { CODEC_ID_PCM_F64BE, 7 }, - { CODEC_ID_PCM_ALAW, 27 }, - { CODEC_ID_NONE, 0 }, + { AV_CODEC_ID_PCM_MULAW, 1 }, + { AV_CODEC_ID_PCM_S8, 2 }, + { AV_CODEC_ID_PCM_S16BE, 3 }, + { AV_CODEC_ID_PCM_S24BE, 4 }, + { AV_CODEC_ID_PCM_S32BE, 5 }, + { AV_CODEC_ID_PCM_F32BE, 6 }, + { AV_CODEC_ID_PCM_F64BE, 7 }, + { AV_CODEC_ID_PCM_ALAW, 27 }, + { AV_CODEC_ID_NONE, 0 }, }; -#if CONFIG_AU_MUXER -/* AUDIO_FILE header */ -static int put_au_header(AVIOContext *pb, AVCodecContext *enc) -{ - if(!enc->codec_tag) - return -1; - ffio_wfourcc(pb, ".snd"); /* magic number */ - avio_wb32(pb, 24); /* header size */ - avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */ - avio_wb32(pb, (uint32_t)enc->codec_tag); /* codec ID */ - avio_wb32(pb, enc->sample_rate); - avio_wb32(pb, (uint32_t)enc->channels); - return 0; -} - -static int au_write_header(AVFormatContext *s) -{ - AVIOContext *pb = s->pb; - - s->priv_data = NULL; - - /* format header */ - if (put_au_header(pb, s->streams[0]->codec) < 0) { - return -1; - } - - avio_flush(pb); - - return 0; -} - -static int au_write_packet(AVFormatContext *s, AVPacket *pkt) -{ - AVIOContext *pb = s->pb; - avio_write(pb, pkt->data, pkt->size); - return 0; -} - -static int au_write_trailer(AVFormatContext *s) -{ - AVIOContext *pb = s->pb; - int64_t file_size; - - if (s->pb->seekable) { - - /* update file size */ - file_size = avio_tell(pb); - avio_seek(pb, 8, SEEK_SET); - avio_wb32(pb, (uint32_t)(file_size - 24)); - avio_seek(pb, file_size, SEEK_SET); - - avio_flush(pb); - } - - return 0; -} -#endif /* CONFIG_AU_MUXER */ +#if CONFIG_AU_DEMUXER static int au_probe(AVProbeData *p) { @@ -116,15 +57,17 @@ static int au_probe(AVProbeData *p) return 0; } +#define BLOCK_SIZE 1024 + /* au input */ -static int au_read_header(AVFormatContext *s, - AVFormatParameters *ap) +static int au_read_header(AVFormatContext *s) { int size; unsigned int tag; AVIOContext *pb = s->pb; unsigned int id, channels, rate; - enum CodecID codec; + int bps; + enum AVCodecID codec; AVStream *st; /* check ".snd" header */ @@ -138,16 +81,32 @@ static int au_read_header(AVFormatContext *s, rate = avio_rb32(pb); channels = avio_rb32(pb); + if (size > 24) { + /* skip unused data */ + avio_skip(pb, size - 24); + } + codec = ff_codec_get_id(codec_au_tags, id); - if (!av_get_bits_per_sample(codec)) { + if (codec == AV_CODEC_ID_NONE) { + av_log_ask_for_sample(s, "unknown or unsupported codec tag: %u\n", id); + return AVERROR_PATCHWELCOME; + } + + bps = av_get_bits_per_sample(codec); + if (!bps) { av_log_ask_for_sample(s, "could not determine bits per sample\n"); + return AVERROR_PATCHWELCOME; + } + + if (channels == 0 || channels >= INT_MAX / (BLOCK_SIZE * bps >> 3)) { + av_log(s, AV_LOG_ERROR, "Invalid number of channels %u\n", channels); return AVERROR_INVALIDDATA; } - if (size >= 24) { - /* skip unused data */ - avio_skip(pb, size - 24); + if (rate == 0 || rate > INT_MAX) { + av_log(s, AV_LOG_ERROR, "Invalid sample rate: %u\n", rate); + return AVERROR_INVALIDDATA; } /* now we are ready: build format streams */ @@ -159,53 +118,111 @@ static int au_read_header(AVFormatContext *s, st->codec->codec_id = codec; st->codec->channels = channels; st->codec->sample_rate = rate; - av_set_pts_info(st, 64, 1, rate); + st->codec->bit_rate = channels * rate * bps; + st->codec->block_align = channels * bps >> 3; + + st->start_time = 0; + avpriv_set_pts_info(st, 64, 1, rate); return 0; } -#define BLOCK_SIZE 1024 - static int au_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret; - ret= av_get_packet(s->pb, pkt, BLOCK_SIZE * - s->streams[0]->codec->channels * - av_get_bits_per_sample(s->streams[0]->codec->codec_id) >> 3); + ret = av_get_packet(s->pb, pkt, BLOCK_SIZE * + s->streams[0]->codec->block_align); if (ret < 0) return ret; pkt->stream_index = 0; + pkt->duration = ret / s->streams[0]->codec->block_align; - /* note: we need to modify the packet size here to handle the last - packet */ - pkt->size = ret; return 0; } -#if CONFIG_AU_DEMUXER AVInputFormat ff_au_demuxer = { .name = "au", - .long_name = NULL_IF_CONFIG_SMALL("SUN AU format"), + .long_name = NULL_IF_CONFIG_SMALL("Sun AU"), .read_probe = au_probe, .read_header = au_read_header, .read_packet = au_read_packet, - .read_seek = pcm_read_seek, - .codec_tag= (const AVCodecTag* const []){codec_au_tags, 0}, + .read_seek = ff_pcm_read_seek, + .codec_tag = (const AVCodecTag* const []){ codec_au_tags, 0 }, }; -#endif +#endif /* CONFIG_AU_DEMUXER */ #if CONFIG_AU_MUXER + +/* if we don't know the size in advance */ +#define AU_UNKNOWN_SIZE ((uint32_t)(~0)) + +/* AUDIO_FILE header */ +static int put_au_header(AVIOContext *pb, AVCodecContext *enc) +{ + if(!enc->codec_tag) + return -1; + ffio_wfourcc(pb, ".snd"); /* magic number */ + avio_wb32(pb, 24); /* header size */ + avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */ + avio_wb32(pb, (uint32_t)enc->codec_tag); /* codec ID */ + avio_wb32(pb, enc->sample_rate); + avio_wb32(pb, (uint32_t)enc->channels); + return 0; +} + +static int au_write_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + + s->priv_data = NULL; + + /* format header */ + if (put_au_header(pb, s->streams[0]->codec) < 0) { + return -1; + } + + avio_flush(pb); + + return 0; +} + +static int au_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + avio_write(pb, pkt->data, pkt->size); + return 0; +} + +static int au_write_trailer(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + int64_t file_size; + + if (s->pb->seekable) { + + /* update file size */ + file_size = avio_tell(pb); + avio_seek(pb, 8, SEEK_SET); + avio_wb32(pb, (uint32_t)(file_size - 24)); + avio_seek(pb, file_size, SEEK_SET); + + avio_flush(pb); + } + + return 0; +} + AVOutputFormat ff_au_muxer = { .name = "au", - .long_name = NULL_IF_CONFIG_SMALL("SUN AU format"), + .long_name = NULL_IF_CONFIG_SMALL("Sun AU"), .mime_type = "audio/basic", .extensions = "au", - .audio_codec = CODEC_ID_PCM_S16BE, - .video_codec = CODEC_ID_NONE, + .audio_codec = AV_CODEC_ID_PCM_S16BE, + .video_codec = AV_CODEC_ID_NONE, .write_header = au_write_header, .write_packet = au_write_packet, .write_trailer = au_write_trailer, - .codec_tag= (const AVCodecTag* const []){codec_au_tags, 0}, + .codec_tag = (const AVCodecTag* const []){ codec_au_tags, 0 }, }; -#endif //CONFIG_AU_MUXER +#endif /* CONFIG_AU_MUXER */