00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdint.h>
00023 #include <sndio.h>
00024
00025 #include "libavformat/avformat.h"
00026 #include "libavutil/opt.h"
00027
00028 #include "sndio_common.h"
00029
00030 static av_cold int audio_read_header(AVFormatContext *s1,
00031 AVFormatParameters *ap)
00032 {
00033 SndioData *s = s1->priv_data;
00034 AVStream *st;
00035 int ret;
00036
00037 #if FF_API_FORMAT_PARAMETERS
00038 if (ap->sample_rate > 0)
00039 s->sample_rate = ap->sample_rate;
00040 if (ap->channels > 0)
00041 s->channels = ap->channels;
00042 #endif
00043
00044 st = av_new_stream(s1, 0);
00045 if (!st)
00046 return AVERROR(ENOMEM);
00047
00048 ret = ff_sndio_open(s1, 0, s1->filename);
00049 if (ret < 0)
00050 return ret;
00051
00052
00053 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00054 st->codec->codec_id = s->codec_id;
00055 st->codec->sample_rate = s->sample_rate;
00056 st->codec->channels = s->channels;
00057
00058 av_set_pts_info(st, 64, 1, 1000000);
00059
00060 return 0;
00061 }
00062
00063 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
00064 {
00065 SndioData *s = s1->priv_data;
00066 int64_t bdelay, cur_time;
00067 int ret;
00068
00069 if ((ret = av_new_packet(pkt, s->buffer_size)) < 0)
00070 return ret;
00071
00072 ret = sio_read(s->hdl, pkt->data, pkt->size);
00073 if (ret == 0 || sio_eof(s->hdl)) {
00074 av_free_packet(pkt);
00075 return AVERROR_EOF;
00076 }
00077
00078 pkt->size = ret;
00079 s->softpos += ret;
00080
00081
00082 cur_time = av_gettime();
00083
00084 bdelay = ret + s->hwpos - s->softpos;
00085
00086
00087 pkt->pts = cur_time - ((bdelay * 1000000) /
00088 (s->bps * s->channels * s->sample_rate));
00089
00090 return 0;
00091 }
00092
00093 static av_cold int audio_read_close(AVFormatContext *s1)
00094 {
00095 SndioData *s = s1->priv_data;
00096
00097 ff_sndio_close(s);
00098
00099 return 0;
00100 }
00101
00102 static const AVOption options[] = {
00103 { "sample_rate", "", offsetof(SndioData, sample_rate), FF_OPT_TYPE_INT, {.dbl = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
00104 { "channels", "", offsetof(SndioData, channels), FF_OPT_TYPE_INT, {.dbl = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
00105 { NULL },
00106 };
00107
00108 static const AVClass sndio_demuxer_class = {
00109 .class_name = "sndio indev",
00110 .item_name = av_default_item_name,
00111 .option = options,
00112 .version = LIBAVUTIL_VERSION_INT,
00113 };
00114
00115 AVInputFormat ff_sndio_demuxer = {
00116 .name = "sndio",
00117 .long_name = NULL_IF_CONFIG_SMALL("sndio audio capture"),
00118 .priv_data_size = sizeof(SndioData),
00119 .read_header = audio_read_header,
00120 .read_packet = audio_read_packet,
00121 .read_close = audio_read_close,
00122 .flags = AVFMT_NOFILE,
00123 .priv_class = &sndio_demuxer_class,
00124 };