[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