audio.c
上传用户:gzhwww
上传日期:2007-12-07
资源大小:1453k
文件大小:8k
源码类别:

多媒体

开发平台:

Unix_Linux

  1. /*
  2.  * Linux audio play and grab interface
  3.  * Copyright (c) 2000, 2001 Fabrice Bellard.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #include "avformat.h"
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <sys/soundcard.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/mman.h>
  28. #include <sys/time.h>
  29. #define AUDIO_BLOCK_SIZE 4096
  30. typedef struct {
  31.     int fd;
  32.     int sample_rate;
  33.     int channels;
  34.     int frame_size; /* in bytes ! */
  35.     int codec_id;
  36.     int flip_left : 1;
  37.     uint8_t buffer[AUDIO_BLOCK_SIZE];
  38.     int buffer_ptr;
  39. } AudioData;
  40. static int audio_open(AudioData *s, int is_output, const char *audio_device)
  41. {
  42.     int audio_fd;
  43.     int tmp, err;
  44.     char *flip = getenv("AUDIO_FLIP_LEFT");
  45.     /* open linux audio device */
  46.     if (!audio_device)
  47.         audio_device = "/dev/dsp";
  48.     if (is_output)
  49.         audio_fd = open(audio_device, O_WRONLY);
  50.     else
  51.         audio_fd = open(audio_device, O_RDONLY);
  52.     if (audio_fd < 0) {
  53.         perror(audio_device);
  54.         return AVERROR_IO;
  55.     }
  56.     if (flip && *flip == '1') {
  57.         s->flip_left = 1;
  58.     }
  59.     /* non blocking mode */
  60.     if (!is_output)
  61.         fcntl(audio_fd, F_SETFL, O_NONBLOCK);
  62.     s->frame_size = AUDIO_BLOCK_SIZE;
  63. #if 0
  64.     tmp = (NB_FRAGMENTS << 16) | FRAGMENT_BITS;
  65.     err = ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
  66.     if (err < 0) {
  67.         perror("SNDCTL_DSP_SETFRAGMENT");
  68.     }
  69. #endif
  70.     /* select format : favour native format */
  71.     err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
  72.     
  73. #ifdef WORDS_BIGENDIAN
  74.     if (tmp & AFMT_S16_BE) {
  75.         tmp = AFMT_S16_BE;
  76.     } else if (tmp & AFMT_S16_LE) {
  77.         tmp = AFMT_S16_LE;
  78.     } else {
  79.         tmp = 0;
  80.     }
  81. #else
  82.     if (tmp & AFMT_S16_LE) {
  83.         tmp = AFMT_S16_LE;
  84.     } else if (tmp & AFMT_S16_BE) {
  85.         tmp = AFMT_S16_BE;
  86.     } else {
  87.         tmp = 0;
  88.     }
  89. #endif
  90.     switch(tmp) {
  91.     case AFMT_S16_LE:
  92.         s->codec_id = CODEC_ID_PCM_S16LE;
  93.         break;
  94.     case AFMT_S16_BE:
  95.         s->codec_id = CODEC_ID_PCM_S16BE;
  96.         break;
  97.     default:
  98.         av_log(NULL, AV_LOG_ERROR, "Soundcard does not support 16 bit sample formatn");
  99.         close(audio_fd);
  100.         return AVERROR_IO;
  101.     }
  102.     err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
  103.     if (err < 0) {
  104.         perror("SNDCTL_DSP_SETFMT");
  105.         goto fail;
  106.     }
  107.     
  108.     tmp = (s->channels == 2);
  109.     err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
  110.     if (err < 0) {
  111.         perror("SNDCTL_DSP_STEREO");
  112.         goto fail;
  113.     }
  114.     if (tmp)
  115.         s->channels = 2;
  116.     
  117.     tmp = s->sample_rate;
  118.     err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
  119.     if (err < 0) {
  120.         perror("SNDCTL_DSP_SPEED");
  121.         goto fail;
  122.     }
  123.     s->sample_rate = tmp; /* store real sample rate */
  124.     s->fd = audio_fd;
  125.     return 0;
  126.  fail:
  127.     close(audio_fd);
  128.     return AVERROR_IO;
  129. }
  130. static int audio_close(AudioData *s)
  131. {
  132.     close(s->fd);
  133.     return 0;
  134. }
  135. /* sound output support */
  136. static int audio_write_header(AVFormatContext *s1)
  137. {
  138.     AudioData *s = s1->priv_data;
  139.     AVStream *st;
  140.     int ret;
  141.     st = s1->streams[0];
  142.     s->sample_rate = st->codec.sample_rate;
  143.     s->channels = st->codec.channels;
  144.     ret = audio_open(s, 1, NULL);
  145.     if (ret < 0) {
  146.         return AVERROR_IO;
  147.     } else {
  148.         return 0;
  149.     }
  150. }
  151. static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
  152. {
  153.     AudioData *s = s1->priv_data;
  154.     int len, ret;
  155.     int size= pkt->size;
  156.     uint8_t *buf= pkt->data;
  157.     while (size > 0) {
  158.         len = AUDIO_BLOCK_SIZE - s->buffer_ptr;
  159.         if (len > size)
  160.             len = size;
  161.         memcpy(s->buffer + s->buffer_ptr, buf, len);
  162.         s->buffer_ptr += len;
  163.         if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
  164.             for(;;) {
  165.                 ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
  166.                 if (ret > 0)
  167.                     break;
  168.                 if (ret < 0 && (errno != EAGAIN && errno != EINTR))
  169.                     return AVERROR_IO;
  170.             }
  171.             s->buffer_ptr = 0;
  172.         }
  173.         buf += len;
  174.         size -= len;
  175.     }
  176.     return 0;
  177. }
  178. static int audio_write_trailer(AVFormatContext *s1)
  179. {
  180.     AudioData *s = s1->priv_data;
  181.     audio_close(s);
  182.     return 0;
  183. }
  184. /* grab support */
  185. static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
  186. {
  187.     AudioData *s = s1->priv_data;
  188.     AVStream *st;
  189.     int ret;
  190.     if (!ap || ap->sample_rate <= 0 || ap->channels <= 0)
  191.         return -1;
  192.     st = av_new_stream(s1, 0);
  193.     if (!st) {
  194.         return -ENOMEM;
  195.     }
  196.     s->sample_rate = ap->sample_rate;
  197.     s->channels = ap->channels;
  198.     ret = audio_open(s, 0, ap->device);
  199.     if (ret < 0) {
  200.         av_free(st);
  201.         return AVERROR_IO;
  202.     }
  203.     /* take real parameters */
  204.     st->codec.codec_type = CODEC_TYPE_AUDIO;
  205.     st->codec.codec_id = s->codec_id;
  206.     st->codec.sample_rate = s->sample_rate;
  207.     st->codec.channels = s->channels;
  208.     av_set_pts_info(st, 48, 1, 1000000);  /* 48 bits pts in us */
  209.     return 0;
  210. }
  211. static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
  212. {
  213.     AudioData *s = s1->priv_data;
  214.     int ret, bdelay;
  215.     int64_t cur_time;
  216.     struct audio_buf_info abufi;
  217.     
  218.     if (av_new_packet(pkt, s->frame_size) < 0)
  219.         return AVERROR_IO;
  220.     for(;;) {
  221.         struct timeval tv;
  222.         fd_set fds;
  223.         tv.tv_sec = 0;
  224.         tv.tv_usec = 30 * 1000; /* 30 msecs -- a bit shorter than 1 frame at 30fps */
  225.         FD_ZERO(&fds);
  226.         FD_SET(s->fd, &fds);
  227.         /* This will block until data is available or we get a timeout */
  228.         (void) select(s->fd + 1, &fds, 0, 0, &tv);
  229.         ret = read(s->fd, pkt->data, pkt->size);
  230.         if (ret > 0)
  231.             break;
  232.         if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
  233.             av_free_packet(pkt);
  234.             pkt->size = 0;
  235.             pkt->pts = av_gettime() & ((1LL << 48) - 1);
  236.             return 0;
  237.         }
  238.         if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
  239.             av_free_packet(pkt);
  240.             return AVERROR_IO;
  241.         }
  242.     }
  243.     pkt->size = ret;
  244.     /* compute pts of the start of the packet */
  245.     cur_time = av_gettime();
  246.     bdelay = ret;
  247.     if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
  248.         bdelay += abufi.bytes;
  249.     }
  250.     /* substract time represented by the number of bytes in the audio fifo */
  251.     cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
  252.     /* convert to wanted units */
  253.     pkt->pts = cur_time & ((1LL << 48) - 1);
  254.     if (s->flip_left && s->channels == 2) {
  255.         int i;
  256.         short *p = (short *) pkt->data;
  257.         for (i = 0; i < ret; i += 4) {
  258.             *p = ~*p;
  259.             p += 2;
  260.         }
  261.     }
  262.     return 0;
  263. }
  264. static int audio_read_close(AVFormatContext *s1)
  265. {
  266.     AudioData *s = s1->priv_data;
  267.     audio_close(s);
  268.     return 0;
  269. }
  270. static AVInputFormat audio_in_format = {
  271.     "audio_device",
  272.     "audio grab and output",
  273.     sizeof(AudioData),
  274.     NULL,
  275.     audio_read_header,
  276.     audio_read_packet,
  277.     audio_read_close,
  278.     .flags = AVFMT_NOFILE,
  279. };
  280. static AVOutputFormat audio_out_format = {
  281.     "audio_device",
  282.     "audio grab and output",
  283.     "",
  284.     "",
  285.     sizeof(AudioData),
  286.     /* XXX: we make the assumption that the soundcard accepts this format */
  287.     /* XXX: find better solution with "preinit" method, needed also in
  288.        other formats */
  289. #ifdef WORDS_BIGENDIAN
  290.     CODEC_ID_PCM_S16BE,
  291. #else
  292.     CODEC_ID_PCM_S16LE,
  293. #endif
  294.     CODEC_ID_NONE,
  295.     audio_write_header,
  296.     audio_write_packet,
  297.     audio_write_trailer,
  298.     .flags = AVFMT_NOFILE,
  299. };
  300. int audio_init(void)
  301. {
  302.     av_register_input_format(&audio_in_format);
  303.     av_register_output_format(&audio_out_format);
  304.     return 0;
  305. }