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