comparison beosaudio.cpp @ 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
comparison
equal deleted inserted replaced
95:89e992063014 96:2d3083edb99f
29 29
30 extern "C" { 30 extern "C" {
31 #include "avformat.h" 31 #include "avformat.h"
32 } 32 }
33 33
34 #ifdef HAVE_BSOUNDRECORDER
35 #include <SoundRecorder.h>
36 #endif
37
34 /* enable performance checks */ 38 /* enable performance checks */
35 //#define PERF_CHECK 39 //#define PERF_CHECK
36 40
37 #define AUDIO_BLOCK_SIZE 4096 41 #define AUDIO_BLOCK_SIZE 4096
38 //#define AUDIO_BLOCK_SIZE 2048 42 //#define AUDIO_BLOCK_SIZE 2048
53 int input_index; 57 int input_index;
54 sem_id output_sem; 58 sem_id output_sem;
55 int output_index; 59 int output_index;
56 int queued; 60 int queued;
57 BSoundPlayer *player; 61 BSoundPlayer *player;
62 #ifdef HAVE_BSOUNDRECORDER
63 BSoundRecorder *recorder;
64 #endif
58 int has_quit; /* signal callbacks not to wait */ 65 int has_quit; /* signal callbacks not to wait */
59 volatile bigtime_t starve_time; 66 volatile bigtime_t starve_time;
60 } AudioData; 67 } AudioData;
61 68
62 static thread_id main_thid; 69 static thread_id main_thid;
137 buf += len; 144 buf += len;
138 bufferSize -= len; 145 bufferSize -= len;
139 } 146 }
140 } 147 }
141 148
149 #ifdef HAVE_BSOUNDRECORDER
150 /* called back by BSoundRecorder */
151 static void audiorecord_callback(void *cookie, bigtime_t timestamp, void *buffer, size_t bufferSize, const media_multi_audio_format &format)
152 {
153 AudioData *s;
154 size_t len, amount;
155 unsigned char *buf = (unsigned char *)buffer;
156
157 s = (AudioData *)cookie;
158 if (s->has_quit)
159 return;
160
161 while (bufferSize > 0) {
162 len = MIN(bufferSize, AUDIO_BLOCK_SIZE);
163 //printf("acquire_sem(input, %d)\n", len);
164 if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
165 s->has_quit = 1;
166 return;
167 }
168 amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
169 memcpy(&s->buffer[s->input_index], buf, amount);
170 s->input_index += amount;
171 if (s->input_index >= AUDIO_BUFFER_SIZE) {
172 s->input_index %= AUDIO_BUFFER_SIZE;
173 memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
174 s->input_index += len - amount;
175 }
176 release_sem_etc(s->output_sem, len, 0);
177 //printf("release_sem(output, %d)\n", len);
178 buf += len;
179 bufferSize -= len;
180 }
181 }
182 #endif
183
142 static int audio_open(AudioData *s, int is_output) 184 static int audio_open(AudioData *s, int is_output)
143 { 185 {
144 int p[2]; 186 int p[2];
145 int ret; 187 int ret;
146 media_raw_audio_format format; 188 media_raw_audio_format format;
147 189 media_multi_audio_format iformat;
190
191 #ifndef HAVE_BSOUNDRECORDER
148 if (!is_output) 192 if (!is_output)
149 return -EIO; /* not for now */ 193 return -EIO; /* not for now */
194 #endif
150 s->input_sem = create_sem(AUDIO_BUFFER_SIZE, "ffmpeg_ringbuffer_input"); 195 s->input_sem = create_sem(AUDIO_BUFFER_SIZE, "ffmpeg_ringbuffer_input");
151 // s->input_sem = create_sem(AUDIO_BLOCK_SIZE, "ffmpeg_ringbuffer_input"); 196 // s->input_sem = create_sem(AUDIO_BLOCK_SIZE, "ffmpeg_ringbuffer_input");
152 if (s->input_sem < B_OK) 197 if (s->input_sem < B_OK)
153 return -EIO; 198 return -EIO;
154 s->output_sem = create_sem(0, "ffmpeg_ringbuffer_output"); 199 s->output_sem = create_sem(0, "ffmpeg_ringbuffer_output");
159 s->input_index = 0; 204 s->input_index = 0;
160 s->output_index = 0; 205 s->output_index = 0;
161 s->queued = 0; 206 s->queued = 0;
162 create_bapp_if_needed(); 207 create_bapp_if_needed();
163 s->frame_size = AUDIO_BLOCK_SIZE; 208 s->frame_size = AUDIO_BLOCK_SIZE;
209 /* bump up the priority (avoid realtime though) */
210 set_thread_priority(find_thread(NULL), B_DISPLAY_PRIORITY+1);
211 #ifdef HAVE_BSOUNDRECORDER
212 if (!is_output) {
213 s->recorder = new BSoundRecorder(&iformat, false, "ffmpeg input", audiorecord_callback);
214 if (s->recorder->InitCheck() != B_OK || iformat.format != media_raw_audio_format::B_AUDIO_SHORT) {
215 delete s->recorder;
216 s->recorder = NULL;
217 if (s->input_sem)
218 delete_sem(s->input_sem);
219 if (s->output_sem)
220 delete_sem(s->output_sem);
221 return -EIO;
222 }
223 s->codec_id = (iformat.byte_order == B_MEDIA_LITTLE_ENDIAN)?CODEC_ID_PCM_S16LE:CODEC_ID_PCM_S16BE;
224 s->channels = iformat.channel_count;
225 s->sample_rate = (int)iformat.frame_rate;
226 s->frame_size = iformat.buffer_size;
227 s->recorder->SetCookie(s);
228 s->recorder->SetVolume(1.0);
229 s->recorder->Start();
230 return 0;
231 }
232 #endif
164 format = media_raw_audio_format::wildcard; 233 format = media_raw_audio_format::wildcard;
165 format.format = media_raw_audio_format::B_AUDIO_SHORT; 234 format.format = media_raw_audio_format::B_AUDIO_SHORT;
166 format.byte_order = B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN; 235 format.byte_order = B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN;
167 format.channel_count = s->channels; 236 format.channel_count = s->channels;
168 format.buffer_size = s->frame_size; 237 format.buffer_size = s->frame_size;
169 format.frame_rate = s->sample_rate; 238 format.frame_rate = s->sample_rate;
170 s->player = new BSoundPlayer(&format, "ffmpeg output", audioplay_callback); 239 s->player = new BSoundPlayer(&format, "ffmpeg output", audioplay_callback);
171 if (s->player->InitCheck() != B_OK) { 240 if (s->player->InitCheck() != B_OK) {
172 delete s->player; 241 delete s->player;
173 s->player = NULL; 242 s->player = NULL;
174 if (s->input_sem) 243 if (s->input_sem)
175 delete_sem(s->input_sem); 244 delete_sem(s->input_sem);
176 if (s->output_sem) 245 if (s->output_sem)
177 delete_sem(s->output_sem); 246 delete_sem(s->output_sem);
178 return -EIO; 247 return -EIO;
179 } 248 }
180 s->player->SetCookie(s); 249 s->player->SetCookie(s);
181 s->player->SetVolume(1.0); 250 s->player->SetVolume(1.0);
182 s->player->Start(); 251 s->player->Start();
183 s->player->SetHasData(true); 252 s->player->SetHasData(true);
184 /* bump up the priority (avoid realtime though) */
185 set_thread_priority(find_thread(NULL), B_DISPLAY_PRIORITY+1);
186 return 0; 253 return 0;
187 } 254 }
188 255
189 static int audio_close(AudioData *s) 256 static int audio_close(AudioData *s)
190 { 257 {
196 if (s->player) { 263 if (s->player) {
197 s->player->Stop(); 264 s->player->Stop();
198 } 265 }
199 if (s->player) 266 if (s->player)
200 delete s->player; 267 delete s->player;
268 #ifdef HAVE_BSOUNDRECORDER
269 if (s->recorder)
270 delete s->recorder;
271 #endif
201 destroy_bapp_if_needed(); 272 destroy_bapp_if_needed();
202 return 0; 273 return 0;
203 } 274 }
204 275
205 /* sound output support */ 276 /* sound output support */
276 347
277 ret = audio_open(s, 0); 348 ret = audio_open(s, 0);
278 if (ret < 0) { 349 if (ret < 0) {
279 av_free(st); 350 av_free(st);
280 return -EIO; 351 return -EIO;
281 } else { 352 }
282 /* take real parameters */ 353 /* take real parameters */
283 st->codec.codec_type = CODEC_TYPE_AUDIO; 354 st->codec.codec_type = CODEC_TYPE_AUDIO;
284 st->codec.codec_id = s->codec_id; 355 st->codec.codec_id = s->codec_id;
285 st->codec.sample_rate = s->sample_rate; 356 st->codec.sample_rate = s->sample_rate;
286 st->codec.channels = s->channels; 357 st->codec.channels = s->channels;
287 return 0; 358 return 0;
288 } 359 av_set_pts_info(s1, 48, 1, 1000000); /* 48 bits pts in us */
289 } 360 }
290 361
291 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) 362 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
292 { 363 {
293 AudioData *s = (AudioData *)s1->priv_data; 364 AudioData *s = (AudioData *)s1->priv_data;
294 int ret; 365 int size;
366 size_t len, amount;
367 unsigned char *buf;
368 status_t err;
295 369
296 if (av_new_packet(pkt, s->frame_size) < 0) 370 if (av_new_packet(pkt, s->frame_size) < 0)
297 return -EIO; 371 return -EIO;
298 for(;;) { 372 buf = (unsigned char *)pkt->data;
299 ret = read(s->fd, pkt->data, pkt->size); 373 size = pkt->size;
300 if (ret > 0) 374 while (size > 0) {
301 break; 375 len = MIN(AUDIO_BLOCK_SIZE, size);
302 if (ret == -1 && (errno == EAGAIN || errno == EINTR)) { 376 //printf("acquire_sem(output, %d)\n", len);
303 av_free_packet(pkt); 377 while ((err=acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL)) == B_INTERRUPTED);
304 pkt->size = 0; 378 if (err < B_OK) {
305 return 0;
306 }
307 if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
308 av_free_packet(pkt); 379 av_free_packet(pkt);
309 return -EIO; 380 return -EIO;
310 } 381 }
311 } 382 amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
312 pkt->size = ret; 383 memcpy(buf, &s->buffer[s->output_index], amount);
384 s->output_index += amount;
385 if (s->output_index >= AUDIO_BUFFER_SIZE) {
386 s->output_index %= AUDIO_BUFFER_SIZE;
387 memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
388 s->output_index += len-amount;
389 s->output_index %= AUDIO_BUFFER_SIZE;
390 }
391 release_sem_etc(s->input_sem, len, 0);
392 //printf("release_sem(input, %d)\n", len);
393 buf += len;
394 size -= len;
395 }
396 //XXX: add pts info
313 return 0; 397 return 0;
314 } 398 }
315 399
316 static int audio_read_close(AVFormatContext *s1) 400 static int audio_read_close(AVFormatContext *s1)
317 { 401 {
319 403
320 audio_close(s); 404 audio_close(s);
321 return 0; 405 return 0;
322 } 406 }
323 407
324 AVInputFormat audio_in_format = { 408 static AVInputFormat audio_in_format = {
325 "audio_device", 409 "audio_device",
326 "audio grab and output", 410 "audio grab and output",
327 sizeof(AudioData), 411 sizeof(AudioData),
328 NULL, 412 NULL,
329 audio_read_header, 413 audio_read_header,