[FFmpeg-devel] [WIP][PROOF OF CONCEPT][PATCH] lavd/oss: use libswr for channel reordering

Paul B Mahol onemda at gmail.com
Thu Jan 17 18:55:05 CET 2013


Signed-off-by: Paul B Mahol <onemda at gmail.com>
---

No reordering is done, yet. (swr_set_channel_mapping() call is needed
                             instead of adding extra nonsense code)
Alsa should be fixed too.

---
 libavdevice/oss_audio.c | 55 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c
index aa40034..a6ba922 100644
--- a/libavdevice/oss_audio.c
+++ b/libavdevice/oss_audio.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libswresample/swresample.h"
 #include "config.h"
 #include <stdlib.h>
 #include <stdio.h>
@@ -53,6 +54,7 @@ typedef struct {
     unsigned int flip_left : 1;
     uint8_t buffer[AUDIO_BLOCK_SIZE];
     int buffer_ptr;
+    struct SwrContext *swr;
 } AudioData;
 
 static int audio_open(AVFormatContext *s1, int is_output, const char *audio_device)
@@ -123,10 +125,10 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
         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 +141,20 @@ 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->swr = swr_alloc_set_opts(s->swr,
+                                0, AV_SAMPLE_FMT_S16, s->sample_rate,
+                                0, AV_SAMPLE_FMT_S16, s->sample_rate,
+                                0, s1);
+    if (!s->swr) {
+        close(audio_fd);
+        return AVERROR(ENOMEM);
+    }
+    av_opt_set_int(s->swr, "uch", s->channels, 0);
+    av_opt_set_int(s->swr, "och", s->channels, 0);
+    err = swr_init(s->swr);
+    if (err < 0)
+        return err;
+
     return 0;
  fail:
     close(audio_fd);
@@ -148,6 +164,7 @@ static int audio_open(AVFormatContext *s1, int is_output, const char *audio_devi
 static int audio_close(AudioData *s)
 {
     close(s->fd);
+    swr_free(&s->swr);
     return 0;
 }
 
@@ -172,26 +189,26 @@ static int audio_write_header(AVFormatContext *s1)
 static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
 {
     AudioData *s = s1->priv_data;
-    int len, ret;
+    int ret;
     int size= pkt->size;
-    uint8_t *buf= pkt->data;
+    int in_samples = size / (2 * s->channels);
+    int out_samples = AUDIO_BLOCK_SIZE / (2 * s->channels);
+    uint8_t *out[] = {s->buffer};
+    const uint8_t *in[] = {pkt->data};
 
+    swr_convert(s->swr, out, 0, in, in_samples);
     while (size > 0) {
-        len = FFMIN(AUDIO_BLOCK_SIZE - s->buffer_ptr, size);
-        memcpy(s->buffer + s->buffer_ptr, buf, len);
-        s->buffer_ptr += len;
-        if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
-            for(;;) {
-                ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
-                if (ret > 0)
-                    break;
-                if (ret < 0 && (errno != EAGAIN && errno != EINTR))
-                    return AVERROR(EIO);
-            }
-            s->buffer_ptr = 0;
+        out_samples = FFMIN(size, AUDIO_BLOCK_SIZE);
+        out_samples /= (2 * s->channels);
+        swr_convert(s->swr, out, out_samples, in, 0);
+        for(;;) {
+            ret = write(s->fd, s->buffer, FFMIN(size, AUDIO_BLOCK_SIZE));
+            if (ret > 0)
+                break;
+            if (ret < 0 && (errno != EAGAIN && errno != EINTR))
+                return AVERROR(EIO);
         }
-        buf += len;
-        size -= len;
+        size -= AUDIO_BLOCK_SIZE;
     }
     return 0;
 }
-- 
1.7.11.4



More information about the ffmpeg-devel mailing list