~ubuntu-branches/ubuntu/intrepid/blender/intrepid-updates

« back to all changes in this revision

Viewing changes to extern/ffmpeg/libavformat/beosaudio.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-08-08 02:45:40 UTC
  • mfrom: (12.1.14 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080808024540-kkjp7ekfivzhuw3l
Tags: 2.46+dfsg-4
* Fix python syntax warning in import_dxf.py, which led to nasty output
  in installation/upgrade logs during byte-compilation, using a patch
  provided by the script author (Closes: #492280):
   - debian/patches/45_fix_python_syntax_warning

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * BeOS audio play interface
3
 
 * Copyright (c) 2000, 2001 Fabrice Bellard.
4
 
 *
5
 
 * This library is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU Lesser General Public
7
 
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
9
 
 *
10
 
 * This library is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
 * Lesser General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU Lesser General Public
16
 
 * License along with this library; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 */
19
 
 
20
 
#include <signal.h>
21
 
#include <stdlib.h>
22
 
#include <stdio.h>
23
 
#include <string.h>
24
 
#include <unistd.h>
25
 
#include <sys/time.h>
26
 
 
27
 
#include <Application.h>
28
 
#include <SoundPlayer.h>
29
 
 
30
 
extern "C" {
31
 
#include "avformat.h"
32
 
}
33
 
 
34
 
#ifdef HAVE_BSOUNDRECORDER
35
 
#include <SoundRecorder.h>
36
 
using namespace BPrivate::Media::Experimental;
37
 
#endif
38
 
 
39
 
/* enable performance checks */
40
 
//#define PERF_CHECK
41
 
 
42
 
/* enable Media Kit latency checks */
43
 
//#define LATENCY_CHECK
44
 
 
45
 
#define AUDIO_BLOCK_SIZE 4096
46
 
#define AUDIO_BLOCK_COUNT 8
47
 
 
48
 
#define AUDIO_BUFFER_SIZE (AUDIO_BLOCK_SIZE*AUDIO_BLOCK_COUNT)
49
 
 
50
 
typedef struct {
51
 
    int fd; // UNUSED
52
 
    int sample_rate;
53
 
    int channels;
54
 
    int frame_size; /* in bytes ! */
55
 
    CodecID codec_id;
56
 
    uint8_t buffer[AUDIO_BUFFER_SIZE];
57
 
    int buffer_ptr;
58
 
    /* ring buffer */
59
 
    sem_id input_sem;
60
 
    int input_index;
61
 
    sem_id output_sem;
62
 
    int output_index;
63
 
    BSoundPlayer *player;
64
 
#ifdef HAVE_BSOUNDRECORDER
65
 
    BSoundRecorder *recorder;
66
 
#endif
67
 
    int has_quit; /* signal callbacks not to wait */
68
 
    volatile bigtime_t starve_time;
69
 
} AudioData;
70
 
 
71
 
static thread_id main_thid;
72
 
static thread_id bapp_thid;
73
 
static int own_BApp_created = 0;
74
 
static int refcount = 0;
75
 
 
76
 
/* create the BApplication and Run() it */
77
 
static int32 bapp_thread(void *arg)
78
 
{
79
 
    new BApplication("application/x-vnd.ffmpeg");
80
 
    own_BApp_created = 1;
81
 
    be_app->Run();
82
 
    /* kill the process group */
83
 
//    kill(0, SIGINT);
84
 
//    kill(main_thid, SIGHUP);
85
 
    return B_OK;
86
 
}
87
 
 
88
 
/* create the BApplication only if needed */
89
 
static void create_bapp_if_needed(void)
90
 
{
91
 
    if (refcount++ == 0) {
92
 
        /* needed by libmedia */
93
 
        if (be_app == NULL) {
94
 
            bapp_thid = spawn_thread(bapp_thread, "ffmpeg BApplication", B_NORMAL_PRIORITY, NULL);
95
 
            resume_thread(bapp_thid);
96
 
            while (!own_BApp_created)
97
 
                snooze(50000);
98
 
        }
99
 
    }
100
 
}
101
 
 
102
 
static void destroy_bapp_if_needed(void)
103
 
{
104
 
    if (--refcount == 0 && own_BApp_created) {
105
 
        be_app->Lock();
106
 
        be_app->Quit();
107
 
        be_app = NULL;
108
 
    }
109
 
}
110
 
 
111
 
/* called back by BSoundPlayer */
112
 
static void audioplay_callback(void *cookie, void *buffer, size_t bufferSize, const media_raw_audio_format &format)
113
 
{
114
 
    AudioData *s;
115
 
    size_t len, amount;
116
 
    unsigned char *buf = (unsigned char *)buffer;
117
 
 
118
 
    s = (AudioData *)cookie;
119
 
    if (s->has_quit)
120
 
        return;
121
 
    while (bufferSize > 0) {
122
 
#ifdef PERF_CHECK
123
 
        bigtime_t t;
124
 
        t = system_time();
125
 
#endif
126
 
        len = MIN(AUDIO_BLOCK_SIZE, bufferSize);
127
 
        if (acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
128
 
            s->has_quit = 1;
129
 
            s->player->SetHasData(false);
130
 
            return;
131
 
        }
132
 
        amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
133
 
        memcpy(buf, &s->buffer[s->output_index], amount);
134
 
        s->output_index += amount;
135
 
        if (s->output_index >= AUDIO_BUFFER_SIZE) {
136
 
            s->output_index %= AUDIO_BUFFER_SIZE;
137
 
            memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
138
 
            s->output_index += len-amount;
139
 
            s->output_index %= AUDIO_BUFFER_SIZE;
140
 
        }
141
 
        release_sem_etc(s->input_sem, len, 0);
142
 
#ifdef PERF_CHECK
143
 
        t = system_time() - t;
144
 
        s->starve_time = MAX(s->starve_time, t);
145
 
#endif
146
 
        buf += len;
147
 
        bufferSize -= len;
148
 
    }
149
 
}
150
 
 
151
 
#ifdef HAVE_BSOUNDRECORDER
152
 
/* called back by BSoundRecorder */
153
 
static void audiorecord_callback(void *cookie, bigtime_t timestamp, void *buffer, size_t bufferSize, const media_multi_audio_format &format)
154
 
{
155
 
    AudioData *s;
156
 
    size_t len, amount;
157
 
    unsigned char *buf = (unsigned char *)buffer;
158
 
 
159
 
    s = (AudioData *)cookie;
160
 
    if (s->has_quit)
161
 
        return;
162
 
 
163
 
    while (bufferSize > 0) {
164
 
        len = MIN(bufferSize, AUDIO_BLOCK_SIZE);
165
 
        //printf("acquire_sem(input, %d)\n", len);
166
 
        if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
167
 
            s->has_quit = 1;
168
 
            return;
169
 
        }
170
 
        amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
171
 
        memcpy(&s->buffer[s->input_index], buf, amount);
172
 
        s->input_index += amount;
173
 
        if (s->input_index >= AUDIO_BUFFER_SIZE) {
174
 
            s->input_index %= AUDIO_BUFFER_SIZE;
175
 
            memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
176
 
            s->input_index += len - amount;
177
 
        }
178
 
        release_sem_etc(s->output_sem, len, 0);
179
 
        //printf("release_sem(output, %d)\n", len);
180
 
        buf += len;
181
 
        bufferSize -= len;
182
 
    }
183
 
}
184
 
#endif
185
 
 
186
 
static int audio_open(AudioData *s, int is_output, const char *audio_device)
187
 
{
188
 
    int p[2];
189
 
    int ret;
190
 
    media_raw_audio_format format;
191
 
    media_multi_audio_format iformat;
192
 
 
193
 
#ifndef HAVE_BSOUNDRECORDER
194
 
    if (!is_output)
195
 
        return -EIO; /* not for now */
196
 
#endif
197
 
    s->input_sem = create_sem(AUDIO_BUFFER_SIZE, "ffmpeg_ringbuffer_input");
198
 
    if (s->input_sem < B_OK)
199
 
        return -EIO;
200
 
    s->output_sem = create_sem(0, "ffmpeg_ringbuffer_output");
201
 
    if (s->output_sem < B_OK) {
202
 
        delete_sem(s->input_sem);
203
 
        return -EIO;
204
 
    }
205
 
    s->input_index = 0;
206
 
    s->output_index = 0;
207
 
    create_bapp_if_needed();
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
 
        bool wait_for_input = false;
214
 
        if (audio_device && !strcmp(audio_device, "wait:"))
215
 
            wait_for_input = true;
216
 
        s->recorder = new BSoundRecorder(&iformat, wait_for_input, "ffmpeg input", audiorecord_callback);
217
 
        if (wait_for_input && (s->recorder->InitCheck() == B_OK)) {
218
 
            s->recorder->WaitForIncomingConnection(&iformat);
219
 
        }
220
 
        if (s->recorder->InitCheck() != B_OK || iformat.format != media_raw_audio_format::B_AUDIO_SHORT) {
221
 
            delete s->recorder;
222
 
            s->recorder = NULL;
223
 
            if (s->input_sem)
224
 
                delete_sem(s->input_sem);
225
 
            if (s->output_sem)
226
 
                delete_sem(s->output_sem);
227
 
            return -EIO;
228
 
        }
229
 
        s->codec_id = (iformat.byte_order == B_MEDIA_LITTLE_ENDIAN)?CODEC_ID_PCM_S16LE:CODEC_ID_PCM_S16BE;
230
 
        s->channels = iformat.channel_count;
231
 
        s->sample_rate = (int)iformat.frame_rate;
232
 
        s->frame_size = iformat.buffer_size;
233
 
        s->recorder->SetCookie(s);
234
 
        s->recorder->SetVolume(1.0);
235
 
        s->recorder->Start();
236
 
        return 0;
237
 
    }
238
 
#endif
239
 
    format = media_raw_audio_format::wildcard;
240
 
    format.format = media_raw_audio_format::B_AUDIO_SHORT;
241
 
    format.byte_order = B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN;
242
 
    format.channel_count = s->channels;
243
 
    format.buffer_size = s->frame_size;
244
 
    format.frame_rate = s->sample_rate;
245
 
    s->player = new BSoundPlayer(&format, "ffmpeg output", audioplay_callback);
246
 
    if (s->player->InitCheck() != B_OK) {
247
 
        delete s->player;
248
 
        s->player = NULL;
249
 
        if (s->input_sem)
250
 
            delete_sem(s->input_sem);
251
 
        if (s->output_sem)
252
 
            delete_sem(s->output_sem);
253
 
        return -EIO;
254
 
    }
255
 
    s->player->SetCookie(s);
256
 
    s->player->SetVolume(1.0);
257
 
    s->player->Start();
258
 
    s->player->SetHasData(true);
259
 
    return 0;
260
 
}
261
 
 
262
 
static int audio_close(AudioData *s)
263
 
{
264
 
    if (s->input_sem)
265
 
        delete_sem(s->input_sem);
266
 
    if (s->output_sem)
267
 
        delete_sem(s->output_sem);
268
 
    s->has_quit = 1;
269
 
    if (s->player) {
270
 
        s->player->Stop();
271
 
    }
272
 
    if (s->player)
273
 
        delete s->player;
274
 
#ifdef HAVE_BSOUNDRECORDER
275
 
    if (s->recorder)
276
 
        delete s->recorder;
277
 
#endif
278
 
    destroy_bapp_if_needed();
279
 
    return 0;
280
 
}
281
 
 
282
 
/* sound output support */
283
 
static int audio_write_header(AVFormatContext *s1)
284
 
{
285
 
    AudioData *s = (AudioData *)s1->priv_data;
286
 
    AVStream *st;
287
 
    int ret;
288
 
 
289
 
    st = s1->streams[0];
290
 
    s->sample_rate = st->codec->sample_rate;
291
 
    s->channels = st->codec->channels;
292
 
    ret = audio_open(s, 1, NULL);
293
 
    if (ret < 0)
294
 
        return -EIO;
295
 
    return 0;
296
 
}
297
 
 
298
 
static int audio_write_packet(AVFormatContext *s1, int stream_index,
299
 
                              const uint8_t *buf, int size, int64_t force_pts)
300
 
{
301
 
    AudioData *s = (AudioData *)s1->priv_data;
302
 
    int len, ret;
303
 
#ifdef LATENCY_CHECK
304
 
bigtime_t lat1, lat2;
305
 
lat1 = s->player->Latency();
306
 
#endif
307
 
#ifdef PERF_CHECK
308
 
    bigtime_t t = s->starve_time;
309
 
    s->starve_time = 0;
310
 
    printf("starve_time: %lld    \n", t);
311
 
#endif
312
 
    while (size > 0) {
313
 
        int amount;
314
 
        len = MIN(size, AUDIO_BLOCK_SIZE);
315
 
        if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK)
316
 
            return -EIO;
317
 
        amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
318
 
        memcpy(&s->buffer[s->input_index], buf, amount);
319
 
        s->input_index += amount;
320
 
        if (s->input_index >= AUDIO_BUFFER_SIZE) {
321
 
            s->input_index %= AUDIO_BUFFER_SIZE;
322
 
            memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
323
 
            s->input_index += len - amount;
324
 
        }
325
 
        release_sem_etc(s->output_sem, len, 0);
326
 
        buf += len;
327
 
        size -= len;
328
 
    }
329
 
#ifdef LATENCY_CHECK
330
 
lat2 = s->player->Latency();
331
 
printf("#### BSoundPlayer::Latency(): before= %lld, after= %lld\n", lat1, lat2);
332
 
#endif
333
 
    return 0;
334
 
}
335
 
 
336
 
static int audio_write_trailer(AVFormatContext *s1)
337
 
{
338
 
    AudioData *s = (AudioData *)s1->priv_data;
339
 
 
340
 
    audio_close(s);
341
 
    return 0;
342
 
}
343
 
 
344
 
/* grab support */
345
 
 
346
 
static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
347
 
{
348
 
    AudioData *s = (AudioData *)s1->priv_data;
349
 
    AVStream *st;
350
 
    int ret;
351
 
 
352
 
    if (!ap || ap->sample_rate <= 0 || ap->channels <= 0)
353
 
        return -1;
354
 
 
355
 
    st = av_new_stream(s1, 0);
356
 
    if (!st) {
357
 
        return -ENOMEM;
358
 
    }
359
 
    s->sample_rate = ap->sample_rate;
360
 
    s->channels = ap->channels;
361
 
 
362
 
    ret = audio_open(s, 0, ap->device);
363
 
    if (ret < 0) {
364
 
        av_free(st);
365
 
        return -EIO;
366
 
    }
367
 
    /* take real parameters */
368
 
    st->codec->codec_type = CODEC_TYPE_AUDIO;
369
 
    st->codec->codec_id = s->codec_id;
370
 
    st->codec->sample_rate = s->sample_rate;
371
 
    st->codec->channels = s->channels;
372
 
    return 0;
373
 
    av_set_pts_info(s1, 48, 1, 1000000);  /* 48 bits pts in us */
374
 
}
375
 
 
376
 
static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
377
 
{
378
 
    AudioData *s = (AudioData *)s1->priv_data;
379
 
    int size;
380
 
    size_t len, amount;
381
 
    unsigned char *buf;
382
 
    status_t err;
383
 
 
384
 
    if (av_new_packet(pkt, s->frame_size) < 0)
385
 
        return -EIO;
386
 
    buf = (unsigned char *)pkt->data;
387
 
    size = pkt->size;
388
 
    while (size > 0) {
389
 
        len = MIN(AUDIO_BLOCK_SIZE, size);
390
 
        //printf("acquire_sem(output, %d)\n", len);
391
 
        while ((err=acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL)) == B_INTERRUPTED);
392
 
        if (err < B_OK) {
393
 
            av_free_packet(pkt);
394
 
            return -EIO;
395
 
        }
396
 
        amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
397
 
        memcpy(buf, &s->buffer[s->output_index], amount);
398
 
        s->output_index += amount;
399
 
        if (s->output_index >= AUDIO_BUFFER_SIZE) {
400
 
            s->output_index %= AUDIO_BUFFER_SIZE;
401
 
            memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
402
 
            s->output_index += len-amount;
403
 
            s->output_index %= AUDIO_BUFFER_SIZE;
404
 
        }
405
 
        release_sem_etc(s->input_sem, len, 0);
406
 
        //printf("release_sem(input, %d)\n", len);
407
 
        buf += len;
408
 
        size -= len;
409
 
    }
410
 
    //XXX: add pts info
411
 
    return 0;
412
 
}
413
 
 
414
 
static int audio_read_close(AVFormatContext *s1)
415
 
{
416
 
    AudioData *s = (AudioData *)s1->priv_data;
417
 
 
418
 
    audio_close(s);
419
 
    return 0;
420
 
}
421
 
 
422
 
static AVInputFormat audio_in_format = {
423
 
    "audio_device",
424
 
    "audio grab and output",
425
 
    sizeof(AudioData),
426
 
    NULL,
427
 
    audio_read_header,
428
 
    audio_read_packet,
429
 
    audio_read_close,
430
 
    NULL,
431
 
    AVFMT_NOFILE,
432
 
};
433
 
 
434
 
AVOutputFormat audio_out_format = {
435
 
    "audio_device",
436
 
    "audio grab and output",
437
 
    "",
438
 
    "",
439
 
    sizeof(AudioData),
440
 
#ifdef WORDS_BIGENDIAN
441
 
    CODEC_ID_PCM_S16BE,
442
 
#else
443
 
    CODEC_ID_PCM_S16LE,
444
 
#endif
445
 
    CODEC_ID_NONE,
446
 
    audio_write_header,
447
 
    audio_write_packet,
448
 
    audio_write_trailer,
449
 
    AVFMT_NOFILE,
450
 
};
451
 
 
452
 
extern "C" {
453
 
 
454
 
int audio_init(void)
455
 
{
456
 
    main_thid = find_thread(NULL);
457
 
    av_register_input_format(&audio_in_format);
458
 
    av_register_output_format(&audio_out_format);
459
 
    return 0;
460
 
}
461
 
 
462
 
} // "C"
463