Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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: output
  26.  * @author Luca Abeni ( lucabe72 email it )
  27.  * @author Benoit Fouet ( benoit fouet free fr )
  28.  *
  29.  * This avdevice encoder can play audio to an ALSA (Advanced Linux
  30.  * Sound Architecture) device.
  31.  *
  32.  * The filename parameter is the name of an ALSA PCM device capable of
  33.  * capture, for example "default" or "plughw:1"; see the ALSA documentation
  34.  * for naming conventions. The empty string is equivalent to "default".
  35.  *
  36.  * The playback period is set to the lower value available for the device,
  37.  * which gives a low latency suitable for real-time playback.
  38.  */
  39.  
  40. #include <alsa/asoundlib.h>
  41.  
  42. #include "libavutil/internal.h"
  43. #include "libavutil/time.h"
  44.  
  45.  
  46. #include "libavformat/internal.h"
  47. #include "avdevice.h"
  48. #include "alsa.h"
  49.  
  50. static av_cold int audio_write_header(AVFormatContext *s1)
  51. {
  52.     AlsaData *s = s1->priv_data;
  53.     AVStream *st = NULL;
  54.     unsigned int sample_rate;
  55.     enum AVCodecID codec_id;
  56.     int res;
  57.  
  58.     if (s1->nb_streams != 1 || s1->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
  59.         av_log(s1, AV_LOG_ERROR, "Only a single audio stream is supported.\n");
  60.         return AVERROR(EINVAL);
  61.     }
  62.     st = s1->streams[0];
  63.  
  64.     sample_rate = st->codec->sample_rate;
  65.     codec_id    = st->codec->codec_id;
  66.     res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate,
  67.         st->codec->channels, &codec_id);
  68.     if (sample_rate != st->codec->sample_rate) {
  69.         av_log(s1, AV_LOG_ERROR,
  70.                "sample rate %d not available, nearest is %d\n",
  71.                st->codec->sample_rate, sample_rate);
  72.         goto fail;
  73.     }
  74.     avpriv_set_pts_info(st, 64, 1, sample_rate);
  75.  
  76.     return res;
  77.  
  78. fail:
  79.     snd_pcm_close(s->h);
  80.     return AVERROR(EIO);
  81. }
  82.  
  83. static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
  84. {
  85.     AlsaData *s = s1->priv_data;
  86.     int res;
  87.     int size     = pkt->size;
  88.     uint8_t *buf = pkt->data;
  89.  
  90.     size /= s->frame_size;
  91.     if (pkt->dts != AV_NOPTS_VALUE)
  92.         s->timestamp = pkt->dts;
  93.     s->timestamp += pkt->duration ? pkt->duration : size;
  94.  
  95.     if (s->reorder_func) {
  96.         if (size > s->reorder_buf_size)
  97.             if (ff_alsa_extend_reorder_buf(s, size))
  98.                 return AVERROR(ENOMEM);
  99.         s->reorder_func(buf, s->reorder_buf, size);
  100.         buf = s->reorder_buf;
  101.     }
  102.     while ((res = snd_pcm_writei(s->h, buf, size)) < 0) {
  103.         if (res == -EAGAIN) {
  104.  
  105.             return AVERROR(EAGAIN);
  106.         }
  107.  
  108.         if (ff_alsa_xrun_recover(s1, res) < 0) {
  109.             av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n",
  110.                    snd_strerror(res));
  111.  
  112.             return AVERROR(EIO);
  113.         }
  114.     }
  115.  
  116.     return 0;
  117. }
  118.  
  119. static int audio_write_frame(AVFormatContext *s1, int stream_index,
  120.                              AVFrame **frame, unsigned flags)
  121. {
  122.     AlsaData *s = s1->priv_data;
  123.     AVPacket pkt;
  124.  
  125.     /* ff_alsa_open() should have accepted only supported formats */
  126.     if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
  127.         return av_sample_fmt_is_planar(s1->streams[stream_index]->codec->sample_fmt) ?
  128.                AVERROR(EINVAL) : 0;
  129.     /* set only used fields */
  130.     pkt.data     = (*frame)->data[0];
  131.     pkt.size     = (*frame)->nb_samples * s->frame_size;
  132.     pkt.dts      = (*frame)->pkt_dts;
  133.     pkt.duration = av_frame_get_pkt_duration(*frame);
  134.     return audio_write_packet(s1, &pkt);
  135. }
  136.  
  137. static void
  138. audio_get_output_timestamp(AVFormatContext *s1, int stream,
  139.     int64_t *dts, int64_t *wall)
  140. {
  141.     AlsaData *s  = s1->priv_data;
  142.     snd_pcm_sframes_t delay = 0;
  143.     *wall = av_gettime();
  144.     snd_pcm_delay(s->h, &delay);
  145.     *dts = s->timestamp - delay;
  146. }
  147.  
  148. static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
  149. {
  150.     return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_PLAYBACK);
  151. }
  152.  
  153. static const AVClass alsa_muxer_class = {
  154.     .class_name     = "ALSA muxer",
  155.     .item_name      = av_default_item_name,
  156.     .version        = LIBAVUTIL_VERSION_INT,
  157.     .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
  158. };
  159.  
  160. AVOutputFormat ff_alsa_muxer = {
  161.     .name           = "alsa",
  162.     .long_name      = NULL_IF_CONFIG_SMALL("ALSA audio output"),
  163.     .priv_data_size = sizeof(AlsaData),
  164.     .audio_codec    = DEFAULT_CODEC_ID,
  165.     .video_codec    = AV_CODEC_ID_NONE,
  166.     .write_header   = audio_write_header,
  167.     .write_packet   = audio_write_packet,
  168.     .write_trailer  = ff_alsa_close,
  169.     .write_uncoded_frame = audio_write_frame,
  170.     .get_device_list = audio_get_device_list,
  171.     .get_output_timestamp = audio_get_output_timestamp,
  172.     .flags          = AVFMT_NOFILE,
  173.     .priv_class     = &alsa_muxer_class,
  174. };
  175.