mirror of https://github.com/FFmpeg/FFmpeg.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
3.8 KiB
178 lines
3.8 KiB
/* |
|
* Linux audio play and grab interface |
|
* Copyright (c) 2000, 2001 Gerard Lantau. |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; either version 2 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
*/ |
|
#include "avformat.h" |
|
|
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <linux/soundcard.h> |
|
#include <unistd.h> |
|
#include <fcntl.h> |
|
#include <sys/ioctl.h> |
|
#include <sys/mman.h> |
|
#include <sys/time.h> |
|
|
|
const char *audio_device = "/dev/dsp"; |
|
|
|
typedef struct { |
|
int fd; |
|
int rate; |
|
int channels; |
|
} AudioData; |
|
|
|
#define AUDIO_BLOCK_SIZE 4096 |
|
|
|
/* audio read support */ |
|
|
|
static int audio_read(URLContext *h, UINT8 *buf, int size) |
|
{ |
|
AudioData *s = h->priv_data; |
|
int ret; |
|
|
|
ret = read(s->fd, buf, size); |
|
if (ret < 0) |
|
return -errno; |
|
else |
|
return ret; |
|
} |
|
|
|
static int audio_write(URLContext *h, UINT8 *buf, int size) |
|
{ |
|
AudioData *s = h->priv_data; |
|
int ret; |
|
|
|
ret = write(s->fd, buf, size); |
|
if (ret < 0) |
|
return -errno; |
|
else |
|
return ret; |
|
} |
|
|
|
static int audio_get_format(URLContext *h, URLFormat *f) |
|
{ |
|
AudioData *s = h->priv_data; |
|
|
|
strcpy(f->format_name, "pcm"); |
|
f->sample_rate = s->rate; |
|
f->channels = s->channels; |
|
return 0; |
|
} |
|
|
|
/* URI syntax: 'audio:[rate[,channels]]' |
|
default: rate=44100, channels=2 |
|
*/ |
|
static int audio_open(URLContext *h, const char *uri, int flags) |
|
{ |
|
AudioData *s; |
|
const char *p; |
|
int freq, channels, audio_fd; |
|
int tmp, err; |
|
|
|
h->is_streamed = 1; |
|
h->packet_size = AUDIO_BLOCK_SIZE; |
|
|
|
s = malloc(sizeof(AudioData)); |
|
if (!s) |
|
return -ENOMEM; |
|
h->priv_data = s; |
|
|
|
/* extract parameters */ |
|
p = uri; |
|
strstart(p, "audio:", &p); |
|
freq = strtol(p, (char **)&p, 0); |
|
if (freq <= 0) |
|
freq = 44100; |
|
if (*p == ',') |
|
p++; |
|
channels = strtol(p, (char **)&p, 0); |
|
if (channels <= 0) |
|
channels = 2; |
|
s->rate = freq; |
|
s->channels = channels; |
|
|
|
/* open linux audio device */ |
|
if (flags & URL_WRONLY) |
|
audio_fd = open(audio_device,O_WRONLY); |
|
else |
|
audio_fd = open(audio_device,O_RDONLY); |
|
if (audio_fd < 0) { |
|
perror(audio_device); |
|
return -EIO; |
|
} |
|
|
|
/* non blocking mode */ |
|
fcntl(audio_fd, F_SETFL, O_NONBLOCK); |
|
|
|
#if 0 |
|
tmp=(NB_FRAGMENTS << 16) | FRAGMENT_BITS; |
|
err=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp); |
|
if (err < 0) { |
|
perror("SNDCTL_DSP_SETFRAGMENT"); |
|
} |
|
#endif |
|
|
|
tmp=AFMT_S16_LE; |
|
err=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&tmp); |
|
if (err < 0) { |
|
perror("SNDCTL_DSP_SETFMT"); |
|
goto fail; |
|
} |
|
|
|
tmp= (channels == 2); |
|
err=ioctl(audio_fd,SNDCTL_DSP_STEREO,&tmp); |
|
if (err < 0) { |
|
perror("SNDCTL_DSP_STEREO"); |
|
goto fail; |
|
} |
|
|
|
tmp = freq; |
|
err=ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp); |
|
if (err < 0) { |
|
perror("SNDCTL_DSP_SPEED"); |
|
goto fail; |
|
} |
|
|
|
s->rate = tmp; |
|
s->fd = audio_fd; |
|
|
|
return 0; |
|
fail: |
|
close(audio_fd); |
|
free(s); |
|
return -EIO; |
|
} |
|
|
|
static int audio_close(URLContext *h) |
|
{ |
|
AudioData *s = h->priv_data; |
|
|
|
close(s->fd); |
|
free(s); |
|
return 0; |
|
} |
|
|
|
URLProtocol audio_protocol = { |
|
"audio", |
|
audio_open, |
|
audio_read, |
|
audio_write, |
|
NULL, /* seek */ |
|
audio_close, |
|
audio_get_format, |
|
};
|
|
|