changeset 96:2d3083edb99f libavformat

experimental BeOS audio input support. (needs unreleased library)
author mmu_man
date Thu, 27 Mar 2003 14:44:30 +0000
parents 89e992063014
children 265d01c2248f
files beosaudio.cpp
diffstat 1 files changed, 110 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/beosaudio.cpp	Thu Mar 27 13:37:47 2003 +0000
+++ b/beosaudio.cpp	Thu Mar 27 14:44:30 2003 +0000
@@ -31,6 +31,10 @@
 #include "avformat.h"
 }
 
+#ifdef HAVE_BSOUNDRECORDER
+#include <SoundRecorder.h>
+#endif
+
 /* enable performance checks */
 //#define PERF_CHECK
 
@@ -55,6 +59,9 @@
     int output_index;
     int queued;
     BSoundPlayer *player;
+#ifdef HAVE_BSOUNDRECORDER
+    BSoundRecorder *recorder;
+#endif
     int has_quit; /* signal callbacks not to wait */
     volatile bigtime_t starve_time;
 } AudioData;
@@ -139,14 +146,52 @@
     }
 }
 
+#ifdef HAVE_BSOUNDRECORDER
+/* called back by BSoundRecorder */
+static void audiorecord_callback(void *cookie, bigtime_t timestamp, void *buffer, size_t bufferSize, const media_multi_audio_format &format)
+{
+    AudioData *s;
+    size_t len, amount;
+    unsigned char *buf = (unsigned char *)buffer;
+
+    s = (AudioData *)cookie;
+    if (s->has_quit)
+        return;
+
+    while (bufferSize > 0) {
+        len = MIN(bufferSize, AUDIO_BLOCK_SIZE);
+        //printf("acquire_sem(input, %d)\n", len);
+        if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
+            s->has_quit = 1;
+            return;
+        }
+        amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
+        memcpy(&s->buffer[s->input_index], buf, amount);
+        s->input_index += amount;
+        if (s->input_index >= AUDIO_BUFFER_SIZE) {
+            s->input_index %= AUDIO_BUFFER_SIZE;
+            memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
+            s->input_index += len - amount;
+        }
+        release_sem_etc(s->output_sem, len, 0);
+        //printf("release_sem(output, %d)\n", len);
+        buf += len;
+        bufferSize -= len;
+    }
+}
+#endif
+
 static int audio_open(AudioData *s, int is_output)
 {
     int p[2];
     int ret;
     media_raw_audio_format format;
+    media_multi_audio_format iformat;
 
+#ifndef HAVE_BSOUNDRECORDER
     if (!is_output)
         return -EIO; /* not for now */
+#endif
     s->input_sem = create_sem(AUDIO_BUFFER_SIZE, "ffmpeg_ringbuffer_input");
 //    s->input_sem = create_sem(AUDIO_BLOCK_SIZE, "ffmpeg_ringbuffer_input");
     if (s->input_sem < B_OK)
@@ -161,6 +206,30 @@
     s->queued = 0;
     create_bapp_if_needed();
     s->frame_size = AUDIO_BLOCK_SIZE;
+    /* bump up the priority (avoid realtime though) */
+    set_thread_priority(find_thread(NULL), B_DISPLAY_PRIORITY+1);
+#ifdef HAVE_BSOUNDRECORDER
+    if (!is_output) {
+        s->recorder = new BSoundRecorder(&iformat, false, "ffmpeg input", audiorecord_callback);
+        if (s->recorder->InitCheck() != B_OK || iformat.format != media_raw_audio_format::B_AUDIO_SHORT) {
+            delete s->recorder;
+            s->recorder = NULL;
+            if (s->input_sem)
+                delete_sem(s->input_sem);
+            if (s->output_sem)
+                delete_sem(s->output_sem);
+            return -EIO;
+        }
+        s->codec_id = (iformat.byte_order == B_MEDIA_LITTLE_ENDIAN)?CODEC_ID_PCM_S16LE:CODEC_ID_PCM_S16BE;
+        s->channels = iformat.channel_count;
+        s->sample_rate = (int)iformat.frame_rate;
+        s->frame_size = iformat.buffer_size;
+        s->recorder->SetCookie(s);
+        s->recorder->SetVolume(1.0);
+        s->recorder->Start();
+        return 0;
+    }
+#endif
     format = media_raw_audio_format::wildcard;
     format.format = media_raw_audio_format::B_AUDIO_SHORT;
     format.byte_order = B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN;
@@ -171,18 +240,16 @@
     if (s->player->InitCheck() != B_OK) {
         delete s->player;
         s->player = NULL;
-    if (s->input_sem)
-        delete_sem(s->input_sem);
-    if (s->output_sem)
-        delete_sem(s->output_sem);
+        if (s->input_sem)
+            delete_sem(s->input_sem);
+        if (s->output_sem)
+            delete_sem(s->output_sem);
         return -EIO;
     }
     s->player->SetCookie(s);
     s->player->SetVolume(1.0);
     s->player->Start();
     s->player->SetHasData(true);
-    /* bump up the priority (avoid realtime though) */
-    set_thread_priority(find_thread(NULL), B_DISPLAY_PRIORITY+1);
     return 0;
 }
 
@@ -198,6 +265,10 @@
     }
     if (s->player)
         delete s->player;
+#ifdef HAVE_BSOUNDRECORDER
+    if (s->recorder)
+        delete s->recorder;
+#endif
     destroy_bapp_if_needed();
     return 0;
 }
@@ -278,38 +349,51 @@
     if (ret < 0) {
         av_free(st);
         return -EIO;
-    } else {
-        /* take real parameters */
-        st->codec.codec_type = CODEC_TYPE_AUDIO;
-        st->codec.codec_id = s->codec_id;
-        st->codec.sample_rate = s->sample_rate;
-        st->codec.channels = s->channels;
-        return 0;
     }
+    /* take real parameters */
+    st->codec.codec_type = CODEC_TYPE_AUDIO;
+    st->codec.codec_id = s->codec_id;
+    st->codec.sample_rate = s->sample_rate;
+    st->codec.channels = s->channels;
+    return 0;
+    av_set_pts_info(s1, 48, 1, 1000000);  /* 48 bits pts in us */
 }
 
 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
 {
     AudioData *s = (AudioData *)s1->priv_data;
-    int ret;
+    int size;
+    size_t len, amount;
+    unsigned char *buf;
+    status_t err;
 
     if (av_new_packet(pkt, s->frame_size) < 0)
         return -EIO;
-    for(;;) {
-        ret = read(s->fd, pkt->data, pkt->size);
-        if (ret > 0)
-            break;
-        if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
-            av_free_packet(pkt);
-            pkt->size = 0;
-            return 0;
-        }
-        if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
+    buf = (unsigned char *)pkt->data;
+    size = pkt->size;
+    while (size > 0) {
+        len = MIN(AUDIO_BLOCK_SIZE, size);
+        //printf("acquire_sem(output, %d)\n", len);
+        while ((err=acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL)) == B_INTERRUPTED);
+        if (err < B_OK) {
             av_free_packet(pkt);
             return -EIO;
         }
+        amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
+        memcpy(buf, &s->buffer[s->output_index], amount);
+        s->output_index += amount;
+        if (s->output_index >= AUDIO_BUFFER_SIZE) {
+            s->output_index %= AUDIO_BUFFER_SIZE;
+            memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
+            s->output_index += len-amount;
+            s->output_index %= AUDIO_BUFFER_SIZE;
+        }
+        release_sem_etc(s->input_sem, len, 0);
+        //printf("release_sem(input, %d)\n", len);
+        buf += len;
+        size -= len;
     }
-    pkt->size = ret;
+    //XXX: add pts info
     return 0;
 }
 
@@ -321,7 +405,7 @@
     return 0;
 }
 
-AVInputFormat audio_in_format = {
+static AVInputFormat audio_in_format = {
     "audio_device",
     "audio grab and output",
     sizeof(AudioData),