[FFmpeg-devel] [PATCH 3/3] lavd/oss: implement surround playback.
Nicolas George
nicolas.george at normalesup.org
Thu Nov 22 19:13:59 CET 2012
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/oss_audio.c | 48 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 39 insertions(+), 9 deletions(-)
diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c
index aa40034..1705619 100644
--- a/libavdevice/oss_audio.c
+++ b/libavdevice/oss_audio.c
@@ -34,6 +34,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
+#include "libavutil/channels_reorder.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/time.h"
@@ -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];
+ AVChannelsReorderFunc reorder_func;
int buffer_ptr;
} AudioData;
@@ -61,6 +64,8 @@ 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");
+ enum AVSampleFormat sample_format;
+ int64_t channel_layout = s1->streams[0]->codec->channel_layout;
if (is_output)
audio_fd = open(audio_device, O_WRONLY);
@@ -82,8 +87,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 +120,19 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
close(audio_fd);
return AVERROR(EIO);
}
+ sample_format = AV_SAMPLE_FMT_S16;
+ 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 +145,25 @@ 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 = av_get_channels_reorder_func(&s->reorder_func, sample_format,
+ s->channels, channel_layout,
+ AV_CH_ORDER_INTERNAL,
+ AV_CH_ORDER_ALSA, 0);
+ 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 +202,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(&dst, &buf, 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