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