# HG changeset patch # User mmu_man # Date 1048776270 0 # Node ID 2d3083edb99f907aeac51c133782e48c56ae3edb # Parent 89e992063014989efc12f8feac189bed28b24a9b experimental BeOS audio input support. (needs unreleased library) diff -r 89e992063014 -r 2d3083edb99f beosaudio.cpp --- 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 +#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),