[FFmpeg-devel] [PATCH 4/4] lavd/oss: implement surround playback.
Nicolas George
nicolas.george at normalesup.org
Sat Feb 2 17:42:25 CET 2013
Alter frame_size to contain an integer number of samples.
Implement channels reordering for playback
(and partially for capture, untested).
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
libavdevice/Makefile | 4 ++--
libavdevice/oss_audio.c | 44 +++++++++++++++++++++++++++++++++++---------
2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index 515742d..99b02aa 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -27,8 +27,8 @@ OBJS-$(CONFIG_IEC61883_INDEV) += iec61883.o
OBJS-$(CONFIG_JACK_INDEV) += jack_audio.o timefilter.o
OBJS-$(CONFIG_LAVFI_INDEV) += lavfi.o
OBJS-$(CONFIG_OPENAL_INDEV) += openal-dec.o
-OBJS-$(CONFIG_OSS_INDEV) += oss_audio.o
-OBJS-$(CONFIG_OSS_OUTDEV) += oss_audio.o
+OBJS-$(CONFIG_OSS_INDEV) += oss_audio.o alsa_reorder.o
+OBJS-$(CONFIG_OSS_OUTDEV) += oss_audio.o alsa_reorder.o
OBJS-$(CONFIG_PULSE_INDEV) += pulse.o
OBJS-$(CONFIG_SDL_OUTDEV) += sdl.o
OBJS-$(CONFIG_SNDIO_INDEV) += sndio_common.o sndio_dec.o
diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c
index aa40034..bf4aad0 100644
--- a/libavdevice/oss_audio.c
+++ b/libavdevice/oss_audio.c
@@ -39,6 +39,7 @@
#include "libavutil/time.h"
#include "libavcodec/avcodec.h"
#include "avdevice.h"
+#include "alsa_reorder.h"
#include "libavformat/internal.h"
#define AUDIO_BLOCK_SIZE 4096
@@ -49,9 +50,11 @@ typedef struct {
int sample_rate;
int channels;
int frame_size; /* in bytes ! */
+ int bytes_per_sample;
enum AVCodecID codec_id;
unsigned int flip_left : 1;
uint8_t buffer[AUDIO_BLOCK_SIZE];
+ FFAlsaReorderFunc reorder_func;
int buffer_ptr;
} AudioData;
@@ -61,6 +64,7 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
int audio_fd;
int tmp, err;
char *flip = getenv("AUDIO_FLIP_LEFT");
+ int64_t channel_layout = s1->streams[0]->codec->channel_layout;
if (is_output)
audio_fd = open(audio_device, O_WRONLY);
@@ -82,8 +86,6 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
}
}
- s->frame_size = AUDIO_BLOCK_SIZE;
-
/* select format : favour native format */
err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
@@ -117,16 +119,18 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
close(audio_fd);
return AVERROR(EIO);
}
+ s->bytes_per_sample = 2 * s->channels;
+
err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
if (err < 0) {
av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SETFMT: %s\n", strerror(errno));
goto fail;
}
- tmp = (s->channels == 2);
- err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
+ tmp = s->channels;
+ err = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
if (err < 0) {
- av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_STEREO: %s\n", strerror(errno));
+ av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_CHANNELS: %s\n", strerror(errno));
goto fail;
}
@@ -139,6 +143,23 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
s->sample_rate = tmp; /* store real sample rate */
s->fd = audio_fd;
+ s->frame_size = AUDIO_BLOCK_SIZE - AUDIO_BLOCK_SIZE % s->bytes_per_sample;
+ if (s->channels > 2) {
+ err = ff_alsa_reorder_find(&s->reorder_func, s->codec_id, s->channels,
+ channel_layout, is_output);
+ if (err < 0) {
+ char name[128];
+ av_get_channel_layout_string(name, sizeof(name),
+ s->channels, channel_layout);
+ av_log(s1, AV_LOG_WARNING,
+ "OSS channel layout unknown or unimplemented for %s %s.\n",
+ name, is_output ? "playback" : "capture");
+ }
+ if (s->reorder_func && !is_output)
+ av_log(s1, AV_LOG_WARNING,
+ "Channels reordering not implemented for capture\n");
+ }
+
return 0;
fail:
close(audio_fd);
@@ -177,12 +198,17 @@ static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
uint8_t *buf= pkt->data;
while (size > 0) {
- len = FFMIN(AUDIO_BLOCK_SIZE - s->buffer_ptr, size);
- memcpy(s->buffer + s->buffer_ptr, buf, len);
+ len = FFMIN(s->frame_size - s->buffer_ptr, size);
+ if (s->reorder_func) {
+ uint8_t *dst = s->buffer + s->buffer_ptr;
+ s->reorder_func(buf, dst, len / s->bytes_per_sample);
+ } else {
+ memcpy(s->buffer + s->buffer_ptr, buf, len);
+ }
s->buffer_ptr += len;
- if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
+ if (s->buffer_ptr >= s->frame_size) {
for(;;) {
- ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
+ ret = write(s->fd, s->buffer, s->frame_size);
if (ret > 0)
break;
if (ret < 0 && (errno != EAGAIN && errno != EINTR))
--
1.7.10.4
More information about the ffmpeg-devel
mailing list