mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 04:26:37 +08:00 
			
		
		
		
	experimental BeOS audio input support. (needs unreleased library)
Originally committed as revision 1712 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		| @@ -31,6 +31,10 @@ extern "C" { | ||||
| #include "avformat.h" | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_BSOUNDRECORDER | ||||
| #include <SoundRecorder.h> | ||||
| #endif | ||||
|  | ||||
| /* enable performance checks */ | ||||
| //#define PERF_CHECK | ||||
|  | ||||
| @@ -55,6 +59,9 @@ typedef struct { | ||||
|     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 @@ static void audioplay_callback(void *cookie, void *buffer, size_t bufferSize, co | ||||
|     } | ||||
| } | ||||
|  | ||||
| #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 @@ static int audio_open(AudioData *s, int is_output) | ||||
|     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 @@ static int audio_open(AudioData *s, int is_output) | ||||
|     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 @@ static int audio_close(AudioData *s) | ||||
|     } | ||||
|     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 @@ static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap) | ||||
|     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 @@ static int audio_read_close(AVFormatContext *s1) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| AVInputFormat audio_in_format = { | ||||
| static AVInputFormat audio_in_format = { | ||||
|     "audio_device", | ||||
|     "audio grab and output", | ||||
|     sizeof(AudioData), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 François Revol
					François Revol