LCOV - code coverage report
Current view: top level - libavdevice - alsa_dec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 47 0.0 %
Date: 2017-10-24 00:14:43 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /*
       2             :  * ALSA input and output
       3             :  * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
       4             :  * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
       5             :  *
       6             :  * This file is part of FFmpeg.
       7             :  *
       8             :  * FFmpeg is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public
      10             :  * License as published by the Free Software Foundation; either
      11             :  * version 2.1 of the License, or (at your option) any later version.
      12             :  *
      13             :  * FFmpeg is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with FFmpeg; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : /**
      24             :  * @file
      25             :  * ALSA input and output: input
      26             :  * @author Luca Abeni ( lucabe72 email it )
      27             :  * @author Benoit Fouet ( benoit fouet free fr )
      28             :  * @author Nicolas George ( nicolas george normalesup org )
      29             :  *
      30             :  * This avdevice decoder can capture audio from an ALSA (Advanced
      31             :  * Linux Sound Architecture) device.
      32             :  *
      33             :  * The filename parameter is the name of an ALSA PCM device capable of
      34             :  * capture, for example "default" or "plughw:1"; see the ALSA documentation
      35             :  * for naming conventions. The empty string is equivalent to "default".
      36             :  *
      37             :  * The capture period is set to the lower value available for the device,
      38             :  * which gives a low latency suitable for real-time capture.
      39             :  *
      40             :  * The PTS are an Unix time in microsecond.
      41             :  *
      42             :  * Due to a bug in the ALSA library
      43             :  * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4308), this
      44             :  * decoder does not work with certain ALSA plugins, especially the dsnoop
      45             :  * plugin.
      46             :  */
      47             : 
      48             : #include <alsa/asoundlib.h>
      49             : 
      50             : #include "libavutil/internal.h"
      51             : #include "libavutil/mathematics.h"
      52             : #include "libavutil/opt.h"
      53             : #include "libavutil/time.h"
      54             : 
      55             : #include "libavformat/internal.h"
      56             : 
      57             : #include "avdevice.h"
      58             : #include "alsa.h"
      59             : 
      60           0 : static av_cold int audio_read_header(AVFormatContext *s1)
      61             : {
      62           0 :     AlsaData *s = s1->priv_data;
      63             :     AVStream *st;
      64             :     int ret;
      65             :     enum AVCodecID codec_id;
      66             : 
      67           0 :     st = avformat_new_stream(s1, NULL);
      68           0 :     if (!st) {
      69           0 :         av_log(s1, AV_LOG_ERROR, "Cannot add stream\n");
      70             : 
      71           0 :         return AVERROR(ENOMEM);
      72             :     }
      73           0 :     codec_id    = s1->audio_codec_id;
      74             : 
      75           0 :     ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels,
      76             :         &codec_id);
      77           0 :     if (ret < 0) {
      78           0 :         return AVERROR(EIO);
      79             :     }
      80             : 
      81             :     /* take real parameters */
      82           0 :     st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
      83           0 :     st->codecpar->codec_id    = codec_id;
      84           0 :     st->codecpar->sample_rate = s->sample_rate;
      85           0 :     st->codecpar->channels    = s->channels;
      86           0 :     st->codecpar->frame_size = s->frame_size;
      87           0 :     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
      88             :     /* microseconds instead of seconds, MHz instead of Hz */
      89           0 :     s->timefilter = ff_timefilter_new(1000000.0 / s->sample_rate,
      90           0 :                                       s->period_size, 1.5E-6);
      91           0 :     if (!s->timefilter)
      92           0 :         goto fail;
      93             : 
      94           0 :     return 0;
      95             : 
      96           0 : fail:
      97           0 :     snd_pcm_close(s->h);
      98           0 :     return AVERROR(EIO);
      99             : }
     100             : 
     101           0 : static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
     102             : {
     103           0 :     AlsaData *s  = s1->priv_data;
     104             :     int res;
     105             :     int64_t dts;
     106           0 :     snd_pcm_sframes_t delay = 0;
     107             : 
     108           0 :     if (av_new_packet(pkt, s->period_size * s->frame_size) < 0) {
     109           0 :         return AVERROR(EIO);
     110             :     }
     111             : 
     112           0 :     while ((res = snd_pcm_readi(s->h, pkt->data, s->period_size)) < 0) {
     113           0 :         if (res == -EAGAIN) {
     114           0 :             av_packet_unref(pkt);
     115             : 
     116           0 :             return AVERROR(EAGAIN);
     117             :         }
     118           0 :         if (ff_alsa_xrun_recover(s1, res) < 0) {
     119           0 :             av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n",
     120             :                    snd_strerror(res));
     121           0 :             av_packet_unref(pkt);
     122             : 
     123           0 :             return AVERROR(EIO);
     124             :         }
     125           0 :         ff_timefilter_reset(s->timefilter);
     126             :     }
     127             : 
     128           0 :     dts = av_gettime();
     129           0 :     snd_pcm_delay(s->h, &delay);
     130           0 :     dts -= av_rescale(delay + res, 1000000, s->sample_rate);
     131           0 :     pkt->pts = ff_timefilter_update(s->timefilter, dts, s->last_period);
     132           0 :     s->last_period = res;
     133             : 
     134           0 :     pkt->size = res * s->frame_size;
     135             : 
     136           0 :     return 0;
     137             : }
     138             : 
     139           0 : static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
     140             : {
     141           0 :     return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_CAPTURE);
     142             : }
     143             : 
     144             : static const AVOption options[] = {
     145             :     { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     146             :     { "channels",    "", offsetof(AlsaData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     147             :     { NULL },
     148             : };
     149             : 
     150             : static const AVClass alsa_demuxer_class = {
     151             :     .class_name     = "ALSA demuxer",
     152             :     .item_name      = av_default_item_name,
     153             :     .option         = options,
     154             :     .version        = LIBAVUTIL_VERSION_INT,
     155             :     .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
     156             : };
     157             : 
     158             : AVInputFormat ff_alsa_demuxer = {
     159             :     .name           = "alsa",
     160             :     .long_name      = NULL_IF_CONFIG_SMALL("ALSA audio input"),
     161             :     .priv_data_size = sizeof(AlsaData),
     162             :     .read_header    = audio_read_header,
     163             :     .read_packet    = audio_read_packet,
     164             :     .read_close     = ff_alsa_close,
     165             :     .get_device_list = audio_get_device_list,
     166             :     .flags          = AVFMT_NOFILE,
     167             :     .priv_class     = &alsa_demuxer_class,
     168             : };

Generated by: LCOV version 1.13