Mercurial > libavformat.hg
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, |
