libavdevice/sndio_dec.c
15d59d2c
 /*
  * sndio play and grab interface
  * Copyright (c) 2010 Jacob Meuser
  *
e93d9715
  * This file is part of FFmpeg.
15d59d2c
  *
e93d9715
  * FFmpeg is free software; you can redistribute it and/or
15d59d2c
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
e93d9715
  * FFmpeg is distributed in the hope that it will be useful,
15d59d2c
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
e93d9715
  * License along with FFmpeg; if not, write to the Free Software
15d59d2c
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <stdint.h>
 #include <sndio.h>
 
 #include "libavformat/avformat.h"
c3f9ebf7
 #include "libavformat/internal.h"
a1a15a99
 #include "libavutil/opt.h"
79b18357
 #include "libavutil/time.h"
15d59d2c
 
 #include "sndio_common.h"
 
6e9651d1
 static av_cold int audio_read_header(AVFormatContext *s1)
15d59d2c
 {
     SndioData *s = s1->priv_data;
     AVStream *st;
     int ret;
 
3b3bbdd3
     st = avformat_new_stream(s1, NULL);
15d59d2c
     if (!st)
         return AVERROR(ENOMEM);
 
     ret = ff_sndio_open(s1, 0, s1->filename);
     if (ret < 0)
         return ret;
 
     /* take real parameters */
     st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
     st->codec->codec_id    = s->codec_id;
     st->codec->sample_rate = s->sample_rate;
     st->codec->channels    = s->channels;
 
c3f9ebf7
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
15d59d2c
 
     return 0;
 }
 
 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
 {
     SndioData *s = s1->priv_data;
     int64_t bdelay, cur_time;
     int ret;
 
     if ((ret = av_new_packet(pkt, s->buffer_size)) < 0)
         return ret;
 
     ret = sio_read(s->hdl, pkt->data, pkt->size);
     if (ret == 0 || sio_eof(s->hdl)) {
         av_free_packet(pkt);
         return AVERROR_EOF;
     }
 
     pkt->size   = ret;
     s->softpos += ret;
 
     /* compute pts of the start of the packet */
     cur_time = av_gettime();
 
     bdelay = ret + s->hwpos - s->softpos;
 
     /* convert to pts */
     pkt->pts = cur_time - ((bdelay * 1000000) /
         (s->bps * s->channels * s->sample_rate));
 
     return 0;
 }
 
 static av_cold int audio_read_close(AVFormatContext *s1)
 {
     SndioData *s = s1->priv_data;
 
     ff_sndio_close(s);
 
     return 0;
 }
 
a1a15a99
 static const AVOption options[] = {
e6153f17
     { "sample_rate", "", offsetof(SndioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { "channels",    "", offsetof(SndioData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
a1a15a99
     { NULL },
 };
 
 static const AVClass sndio_demuxer_class = {
     .class_name     = "sndio indev",
     .item_name      = av_default_item_name,
     .option         = options,
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
15d59d2c
 AVInputFormat ff_sndio_demuxer = {
     .name           = "sndio",
     .long_name      = NULL_IF_CONFIG_SMALL("sndio audio capture"),
     .priv_data_size = sizeof(SndioData),
     .read_header    = audio_read_header,
     .read_packet    = audio_read_packet,
     .read_close     = audio_read_close,
     .flags          = AVFMT_NOFILE,
a1a15a99
     .priv_class     = &sndio_demuxer_class,
15d59d2c
 };