source: mediastreamer2/src/msandroid.cpp @ 1031:6b63434d94e0

Last change on this file since 1031:6b63434d94e0 was 1031:6b63434d94e0, checked in by Simon Morlat <simon.morlat@…>, 3 years ago

bypass reference signal when no echo signal is yet received.
msandroid improvements in progress

File size: 18.7 KB
Line 
1/*
2 * msandroid.cpp -Android Media plugin for Linphone-
3 *
4 *
5 * Copyright (C) 2009  Belledonne Communications, Grenoble, France
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License as published by
9 *  the Free Software Foundation; either version 2 of the License, or
10 *  (at your option) any later version.
11 *
12 *  This program is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *  GNU Library General Public License for more details.
16 *
17 *  You should have received a copy of the GNU General Public License
18 *  along with this program; if not, write to the Free Software
19 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "mediastreamer2/mssndcard.h"
23#include "mediastreamer2/msfilter.h"
24#include <jni.h>
25
26static JavaVM *ms_andsnd_jvm;
27
28
29
30/*
31 mediastreamer2 sound card functions
32 */
33
34void msandroid_sound_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent)
35{
36}
37
38int msandroid_sound_get_level(MSSndCard *card, MSSndCardMixerElem e)
39{
40        return 0;
41}
42
43void msandroid_sound_set_source(MSSndCard *card, MSSndCardCapture source)
44{
45}
46
47void msandroid_sound_init(MSSndCard *card){
48}
49
50void msandroid_sound_uninit(MSSndCard *card){
51}
52
53void msandroid_sound_detect(MSSndCardManager *m);
54MSSndCard *msandroid_sound_duplicate(MSSndCard *obj);
55
56MSFilter *msandroid_sound_read_new(MSSndCard *card);
57MSFilter *msandroid_sound_write_new(MSSndCard *card);
58
59MSSndCardDesc msandroid_sound_card_desc = {
60/*.driver_type=*/"ANDROID SND",
61/*.detect=*/ msandroid_sound_detect,
62/*.init=*/msandroid_sound_init,
63/*.set_level=*/msandroid_sound_set_level,
64/*.get_level=*/msandroid_sound_get_level,
65/*.set_capture=*/msandroid_sound_set_source,
66/*.set_control=*/NULL,
67/*.get_control=*/NULL,
68/*.create_reader=*/msandroid_sound_read_new,
69/*.create_writer=*/msandroid_sound_write_new,
70/*.uninit=*/msandroid_sound_uninit,
71/*.duplicate=*/msandroid_sound_duplicate
72};
73
74MSSndCard *msandroid_sound_duplicate(MSSndCard *obj){
75        MSSndCard *card=card=ms_snd_card_new(&msandroid_sound_card_desc);
76        card->name=ms_strdup(obj->name);
77        return card;
78}
79
80MSSndCard *msandroid_sound_card_new(){
81        MSSndCard *card=ms_snd_card_new(&msandroid_sound_card_desc);
82        card->name=ms_strdup("Android Sound card");
83        return card;
84}
85
86void msandroid_sound_detect(MSSndCardManager *m){
87        ms_debug("msandroid_sound_detect");
88        MSSndCard *card=msandroid_sound_card_new();
89        ms_snd_card_manager_add_card(m,card);
90}
91
92
93/*************filter commun functions*********/
94class msandroid_sound_data {
95public:
96        msandroid_sound_data() : jvm(ms_andsnd_jvm),bits(16),rate(8000),nchannels(1),started(false),thread_id(0){
97                ms_mutex_init(&mutex,NULL);
98        };
99        ~msandroid_sound_data() {
100                ms_mutex_destroy(&mutex);
101        }
102        JavaVM                  *jvm;
103        unsigned int    rate;
104        unsigned int    bits;
105        unsigned int    nchannels;
106        bool                    started;
107        ms_mutex_t              mutex;
108        queue_t                 rq;
109        ms_thread_t     thread_id;
110        int     buff_size; /*buffer size in bytes*/
111};
112
113
114int get_rate(MSFilter *f, void *data){
115        msandroid_sound_data *d=(msandroid_sound_data*)f->data;
116        *(int*)data=d->rate;
117        return 0;
118}
119
120
121int set_nchannels(MSFilter *f, void *arg){
122        ms_debug("set_nchannels %d", *((int*)arg));
123        msandroid_sound_data *d=(msandroid_sound_data*)f->data;
124        d->nchannels=*(int*)arg;
125        return 0;
126}
127
128
129
130
131/***********************************read filter********************/
132int set_read_rate(MSFilter *f, void *arg){
133        int proposed_rate = *((int*)arg);
134        ms_debug("set_rate %d",proposed_rate);
135        msandroid_sound_data *d=(msandroid_sound_data*)f->data;
136        d->rate=proposed_rate;
137        return 0;
138        /*d->rate=44100; //to improve latency on msn 7k
139        if (proposed_rate == d->rate) {
140        return 0;
141        } else {
142                return d->rate;
143        }*/
144}
145
146MSFilterMethod msandroid_sound_read_methods[]={
147        {       MS_FILTER_SET_SAMPLE_RATE       , set_read_rate },
148        {       MS_FILTER_GET_SAMPLE_RATE       , get_rate      },
149        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
150        {       0                               , NULL          }
151};
152
153
154class msandroid_sound_read_data : public msandroid_sound_data{
155public:
156        msandroid_sound_read_data() : audio_record(0),audio_record_class(0),read_buff(0),read_chunk_size(0),ticker_count(0) {
157                ms_bufferizer_init(&rb);
158                ms_mutex_init(&mutex,NULL);
159        }
160        ~msandroid_sound_read_data() {
161                        ms_bufferizer_uninit (&rb);
162                        ms_mutex_destroy(&mutex);
163                }
164                jobject                 audio_record;
165                jclass                  audio_record_class;
166                jbyteArray              read_buff;
167                MSBufferizer rb;
168                int                             read_chunk_size;
169        }
170};
171
172void* msandroid_read_cb(msandroid_sound_read_data* d) {
173        mblk_t *m;
174        int nread;
175        JNIEnv *jni_env = 0;
176        jmethodID read_id=0;
177        jmethodID record_id=0;
178
179
180        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
181        if (result != 0) {
182                ms_error("cannot attach VM\n");
183                goto end;
184        }
185        record_id = jni_env->GetMethodID(d->audio_record_class,"startRecording", "()V");
186        if(record_id==0) {
187                ms_error("cannot find AudioRecord.startRecording() method");
188                goto end;
189        }
190        //start recording
191        jni_env->CallVoidMethod(d->audio_record,record_id);
192
193        // int read (byte[] audioData, int offsetInBytes, int sizeInBytes)
194        read_id = jni_env->GetMethodID(d->audio_record_class,"read", "([BII)I");
195        if(read_id==0) {
196                ms_error("cannot find AudioRecord.read() method");
197                goto end;
198        }
199
200        while (d->started && (nread=jni_env->CallIntMethod(d->audio_record,read_id,d->read_buff,0, d->read_chunk_size))>0) {
201                m = allocb(nread,0);
202                jni_env->GetByteArrayRegion(d->read_buff, 0,nread, (jbyte*)m->b_wptr);
203                //ms_error("%i octets read",nread);
204                m->b_wptr += nread;
205                ms_mutex_lock(&d->mutex);
206                ms_bufferizer_put (&d->rb,m);
207                ms_mutex_unlock(&d->mutex);
208        };
209        goto end;
210        end: {
211                d->jvm->DetachCurrentThread();
212                return 0;
213        }
214}
215
216void msandroid_sound_read_preprocess(MSFilter *f){
217        ms_debug("andsnd_read_preprocess");
218        msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
219        JNIEnv *jni_env = 0;
220        jmethodID constructor_id=0;
221        jmethodID min_buff_size_id;
222        //jmethodID set_notification_period;
223        int rc;
224
225        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
226        if (result != 0) {
227                ms_error("cannot attach VM\n");
228                goto end;
229        }
230        d->audio_record_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/media/AudioRecord"));
231        if (d->audio_record_class == 0) {
232                ms_error("cannot find  android/media/AudioRecord\n");
233                goto end;
234        }
235
236        constructor_id = jni_env->GetMethodID(d->audio_record_class,"<init>", "(IIIII)V");
237        if (constructor_id == 0) {
238                ms_error("cannot find  AudioRecord (int audioSource, int sampleRateInHz, \
239                int channelConfig, int audioFormat, int bufferSizeInBytes)");
240                goto end;
241        }
242        min_buff_size_id = jni_env->GetStaticMethodID(d->audio_record_class,"getMinBufferSize", "(III)I");
243        if (min_buff_size_id == 0) {
244                ms_error("cannot find  AudioRecord.getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)");
245                goto end;
246        }
247        d->buff_size = jni_env->CallStaticIntMethod(d->audio_record_class,min_buff_size_id,d->rate,2/*CHANNEL_CONFIGURATION_MONO*/,2/*  ENCODING_PCM_16BIT */);
248        d->read_chunk_size = d->buff_size;
249
250        if (d->buff_size > 0) {
251                ms_message("Configuring recorder with [%i] bits  rate [%i] nchanels [%i] buff size [%i], chunk size [%i]"
252                                ,d->bits
253                                ,d->rate
254                                ,d->nchannels
255                                ,d->buff_size
256                                ,d->read_chunk_size);
257        } else {
258                ms_message("Cannot configure recorder with [%i] bits  rate [%i] nchanels [%i] buff size [%i] chunk size [%i]"
259                                ,d->bits
260                                ,d->rate
261                                ,d->nchannels
262                                ,d->buff_size
263                                ,d->read_chunk_size);
264                goto end;
265        }
266
267        d->read_buff = jni_env->NewByteArray(d->buff_size);
268        d->read_buff = (jbyteArray)jni_env->NewGlobalRef(d->read_buff);
269        if (d->read_buff == 0) {
270                ms_error("cannot instanciate read buff");
271                goto end;
272        }
273
274        d->audio_record =  jni_env->NewObject(d->audio_record_class
275                        ,constructor_id
276                        ,1/*MIC*/
277                        ,d->rate
278                        ,2/*CHANNEL_CONFIGURATION_MONO*/
279                        ,2/*  ENCODING_PCM_16BIT */
280                        ,d->buff_size);
281
282
283        d->audio_record = jni_env->NewGlobalRef(d->audio_record);
284        if (d->audio_record == 0) {
285                ms_error("cannot instanciate AudioRecord");
286                goto end;
287        }
288
289        d->started=true;
290        // start reader thread
291        rc = ms_thread_create(&d->thread_id, 0, (void*(*)(void*))msandroid_read_cb, d);
292        if (rc){
293                ms_error("cannot create read thread return code  is [%i]", rc);
294                d->started=false;
295                goto end;
296
297        }
298
299        goto end;
300        end: {
301                //d->jvm->DetachCurrentThread();
302                return;
303        }
304}
305
306void msandroid_sound_read_postprocess(MSFilter *f){
307        msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
308        JNIEnv *jni_env = 0;
309        jmethodID flush_id=0;
310        jmethodID stop_id=0;
311        jmethodID release_id=0;
312        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
313        if (result != 0) {
314                ms_error("cannot attach VM\n");
315                goto end;
316        }
317
318        //stop recording
319        stop_id = jni_env->GetMethodID(d->audio_record_class,"stop", "()V");
320        if(stop_id==0) {
321                ms_error("cannot find AudioRecord.stop() method");
322                goto end;
323        }
324
325        d->started = false;
326        if (d->thread_id !=0) ms_thread_join(d->thread_id,0);
327
328        if (d->audio_record) {
329                jni_env->CallVoidMethod(d->audio_record,stop_id);
330
331                //release recorder
332                release_id = jni_env->GetMethodID(d->audio_record_class,"release", "()V");
333                if(release_id==0) {
334                        ms_error("cannot find AudioRecord.release() method");
335                        goto end;
336                }
337                jni_env->CallVoidMethod(d->audio_record,release_id);
338        }
339        goto end;
340        end: {
341                if (d->audio_record) jni_env->DeleteGlobalRef(d->audio_record);
342                jni_env->DeleteGlobalRef(d->audio_record_class);
343                if (d->read_buff) jni_env->DeleteGlobalRef(d->read_buff);
344
345                //d->jvm->DetachCurrentThread();
346                return;
347        }
348}
349
350void msandroid_sound_read_process(MSFilter *f){
351        msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
352        mblk_t *m;
353        int nbytes=0.02*(float)d->rate*2.0*(float)d->nchannels;
354
355        // output a buffer only every 2 ticks + alpha
356        if ((f->ticker->time % 20)==0 || (f->ticker->time % 510)==0){
357                mblk_t *om=allocb(nbytes,0);
358                int err;
359                ms_mutex_lock(&d->mutex);
360                err=ms_bufferizer_read(&d->rb,om->b_wptr,nbytes);
361                if (err==nbytes){
362                        ms_mutex_unlock(&d->mutex);
363                        om->b_wptr+=nbytes;
364                        ms_queue_put(f->outputs[0],om);
365                }else freemsg(om);
366        }
367}
368
369
370static MSFilterDesc msandroid_sound_read_desc={
371/*.id=*/MS_FILTER_PLUGIN_ID,
372/*.name=*/"MSAndSoundRead",
373/*.text=*/N_("Sound capture filter for Android"),
374/*.category=*/MS_FILTER_OTHER,
375/*.enc_fmt*/NULL,
376/*.ninputs=*/0,
377/*.noutputs=*/1,
378/*.init*/NULL,
379/*.preprocess=*/msandroid_sound_read_preprocess,
380/*.process=*/msandroid_sound_read_process,
381/*.postprocess=*/msandroid_sound_read_postprocess,
382/*.uninit*/NULL,
383/*.methods=*/msandroid_sound_read_methods
384};
385
386MSFilter *msandroid_sound_read_new(MSSndCard *card){
387        ms_debug("msandroid_sound_read_new");
388        MSFilter *f=ms_filter_new_from_desc(&msandroid_sound_read_desc);
389        f->data=new msandroid_sound_read_data();
390        return f;
391}
392
393MS_FILTER_DESC_EXPORT(msandroid_sound_read_desc)
394
395/***********************************write filter********************/
396int set_write_rate(MSFilter *f, void *arg){
397        int proposed_rate = *((int*)arg);
398        ms_debug("set_rate %d",proposed_rate);
399        msandroid_sound_data *d=(msandroid_sound_data*)f->data;
400        d->rate=proposed_rate;
401        return 0;
402        /*d->rate=44100; //to improve latency on msn 7k
403        if (proposed_rate == d->rate) {
404        return 0;
405        } else {
406                return d->rate;
407        }
408         */
409}
410
411MSFilterMethod msandroid_sound_write_methods[]={
412        {       MS_FILTER_SET_SAMPLE_RATE       , set_write_rate        },
413        {       MS_FILTER_GET_SAMPLE_RATE       , get_rate      },
414        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
415        {       0                               , NULL          }
416};
417
418
419class msandroid_sound_write_data : public msandroid_sound_data{
420public:
421        msandroid_sound_write_data() :audio_track_class(0),audio_track(0),write_chunk_size(0),writtenBytes(0){
422                bufferizer = ms_bufferizer_new();
423                ms_cond_init(&cond,0);
424        };
425        ~msandroid_sound_write_data() {
426                ms_mutex_lock(&mutex);
427                ms_bufferizer_flush(bufferizer);
428                ms_mutex_unlock(&mutex);
429                ms_bufferizer_destroy(bufferizer);
430                ms_cond_destroy(&cond);
431        }
432        jclass                  audio_track_class;
433        jobject                 audio_track;
434        MSBufferizer    *bufferizer;
435        ms_cond_t               cond;
436        int                     write_chunk_size;
437        unsigned int    writtenBytes;
438        unsigned int getWriteBuffSize() {
439                return buff_size;
440        }
441        int getWrittenFrames() {
442                return writtenBytes/(nchannels*(bits/8));
443        }
444};
445
446void* msandroid_write_cb(msandroid_sound_write_data* d) {
447        JNIEnv                  *jni_env = 0;
448        jbyteArray              write_buff;
449        jmethodID               write_id=0;
450        jmethodID play_id=0;
451
452        jint result;
453        int buff_size = d->getWriteBuffSize();
454        result = d->jvm->AttachCurrentThread(&jni_env,NULL);
455        if (result != 0) {
456                ms_error("cannot attach VM\n");
457                goto end;
458        }
459
460        // int write  (byte[] audioData, int offsetInBytes, int sizeInBytes)
461        write_id = jni_env->GetMethodID(d->audio_track_class,"write", "([BII)I");
462        if(write_id==0) {
463                ms_error("cannot find AudioTrack.write() method");
464                goto end;
465        }
466        play_id = jni_env->GetMethodID(d->audio_track_class,"play", "()V");
467        if(play_id==0) {
468                ms_error("cannot find AudioTrack.play() method");
469                goto end;
470        }
471        write_buff = jni_env->NewByteArray(buff_size);
472        uint8_t tmpBuff[buff_size];
473
474        //start playing
475        jni_env->CallVoidMethod(d->audio_track,play_id);
476
477        ms_bufferizer_flush(d->bufferizer);
478        while(d->started) {
479                mblk_t *m;
480                ms_mutex_lock(&d->mutex);
481                int bufferizer_size;
482                while((bufferizer_size = ms_bufferizer_get_avail(d->bufferizer)) >= d->write_chunk_size) {
483                        if (bufferizer_size > (d->rate*(d->bits/8)*d->nchannels)*.250) { //250 ms
484                                ms_warning("we are late [%i] bytes, flushing",bufferizer_size);
485                                ms_bufferizer_flush(d->bufferizer);
486
487                        } else {
488                                ms_bufferizer_read(d->bufferizer, tmpBuff, d->write_chunk_size);
489                                ms_mutex_unlock(&d->mutex);
490                                jni_env->SetByteArrayRegion(write_buff,0,d->write_chunk_size,(jbyte*)tmpBuff);
491                                int result = jni_env->CallIntMethod(d->audio_track,write_id,write_buff,0,d->write_chunk_size);
492                                d->writtenBytes+=result;
493                                if (result <= 0) {
494                                        ms_error("write operation has failed [%i]",result);
495                                }
496                                ms_mutex_lock(&d->mutex);
497                        }
498                }
499                if (d->started) ms_cond_wait(&d->cond,&d->mutex);
500                ms_mutex_unlock(&d->mutex);
501        }
502
503        goto end;
504        end: {
505                d->jvm->DetachCurrentThread();
506                return 0;
507        }
508
509}
510void msandroid_sound_write_preprocess(MSFilter *f){
511        ms_debug("andsnd_write_preprocess");
512        msandroid_sound_write_data *d=(msandroid_sound_write_data*)f->data;
513        JNIEnv *jni_env = 0;
514        jmethodID constructor_id=0;
515
516        int rc;
517        jmethodID min_buff_size_id;
518
519        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
520        if (result != 0) {
521                ms_error("cannot attach VM\n");
522                goto end;
523        }
524        d->audio_track_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/media/AudioTrack"));
525        if (d->audio_track_class == 0) {
526                ms_error("cannot find  android/media/AudioTrack\n");
527                goto end;
528        }
529
530        constructor_id = jni_env->GetMethodID(d->audio_track_class,"<init>", "(IIIIII)V");
531        if (constructor_id == 0) {
532                ms_error("cannot find  AudioTrack(int streamType, int sampleRateInHz, \
533                int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)");
534                goto end;
535        }
536
537        min_buff_size_id = jni_env->GetStaticMethodID(d->audio_track_class,"getMinBufferSize", "(III)I");
538        if (min_buff_size_id == 0) {
539                ms_error("cannot find  AudioTrack.getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)");
540                goto end;
541        }
542        d->buff_size = jni_env->CallStaticIntMethod(d->audio_track_class,min_buff_size_id,d->rate,2/*CHANNEL_CONFIGURATION_MONO*/,2/*  ENCODING_PCM_16BIT */);
543        d->write_chunk_size= (d->rate*(d->bits/8)*d->nchannels)*0.02;
544
545        if (d->buff_size > 0) {
546                ms_message("Configuring player with [%i] bits  rate [%i] nchanels [%i] buff size [%i] chunk size [%i]"
547                                ,d->bits
548                                ,d->rate
549                                ,d->nchannels
550                                ,d->buff_size
551                                ,d->write_chunk_size);
552        } else {
553                ms_message("Cannot configure player with [%i] bits  rate [%i] nchanels [%i] buff size [%i] chunk size [%i]"
554                                ,d->bits
555                                ,d->rate
556                                ,d->nchannels
557                                ,d->buff_size
558                                ,d->write_chunk_size);
559                goto end;
560        }
561        d->audio_track =  jni_env->NewObject(d->audio_track_class
562                        ,constructor_id
563                        ,0/*STREAM_VOICE_CALL*/
564                        ,d->rate
565                        ,2/*CHANNEL_CONFIGURATION_MONO*/
566                        ,2/*  ENCODING_PCM_16BIT */
567                        ,d->buff_size
568                        ,1/*MODE_STREAM */);
569        d->audio_track = jni_env->NewGlobalRef(d->audio_track);
570        if (d->audio_track == 0) {
571                ms_error("cannot instanciate AudioTrack");
572                goto end;
573        }
574
575
576        // start reader thread
577        d->started = true;
578        rc = ms_thread_create(&d->thread_id, 0, (void*(*)(void*))msandroid_write_cb, d);
579        if (rc){
580                ms_error("cannot create write thread return code  is [%i]", rc);
581                d->started = false;
582                goto end;
583        }
584
585        goto end;
586        end: {
587                //d->jvm->DetachCurrentThread();
588                return;
589        }
590
591}
592
593void msandroid_sound_write_postprocess(MSFilter *f){
594        msandroid_sound_write_data *d=(msandroid_sound_write_data*)f->data;
595        JNIEnv *jni_env = 0;
596        jmethodID flush_id=0;
597        jmethodID stop_id=0;
598        jmethodID release_id=0;
599        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
600        if (result != 0) {
601                ms_error("cannot attach VM\n");
602                goto end;
603        }
604
605        d->started=false;
606        ms_mutex_lock(&d->mutex);
607        ms_cond_signal(&d->cond);
608        ms_mutex_unlock(&d->mutex);
609        ms_thread_join(d->thread_id,0);
610        // flush
611        flush_id = jni_env->GetMethodID(d->audio_track_class,"flush", "()V");
612        if(flush_id==0) {
613                ms_error("cannot find AudioTrack.flush() method");
614                goto end;
615        }
616        if (d->audio_track) {
617
618                jni_env->CallVoidMethod(d->audio_track,flush_id);
619
620                //stop playing
621                stop_id = jni_env->GetMethodID(d->audio_track_class,"stop", "()V");
622                if(stop_id==0) {
623                        ms_error("cannot find AudioTrack.stop() method");
624                        goto end;
625                }
626                jni_env->CallVoidMethod(d->audio_track,stop_id);
627
628                //release playing
629                release_id = jni_env->GetMethodID(d->audio_track_class,"release", "()V");
630                if(release_id==0) {
631                        ms_error("cannot find AudioTrack.release() method");
632                        goto end;
633                }
634                jni_env->CallVoidMethod(d->audio_track,release_id);
635        }
636
637        goto end;
638end: {
639        if (d->audio_track) jni_env->DeleteGlobalRef(d->audio_track);
640        jni_env->DeleteGlobalRef(d->audio_track_class);
641        //d->jvm->DetachCurrentThread();
642        return;
643}
644
645}
646
647
648
649void msandroid_sound_write_process(MSFilter *f){
650        msandroid_sound_write_data *d=(msandroid_sound_write_data*)f->data;
651       
652        mblk_t *m;
653        while((m=ms_queue_get(f->inputs[0]))!=NULL){
654                if (d->started){
655                        ms_mutex_lock(&d->mutex);
656                        ms_bufferizer_put(d->bufferizer,m);
657                        ms_cond_signal(&d->cond);
658                        ms_mutex_unlock(&d->mutex);
659                }else freemsg(m);
660        }
661}
662
663
664static MSFilterDesc msandroid_sound_write_desc={
665/*.id=*/MS_FILTER_PLUGIN_ID,
666/*.name=*/"MSAndSoundWrite",
667/*.text=*/N_("Sound playback filter for Android"),
668/*.category=*/MS_FILTER_OTHER,
669/*.enc_fmt*/NULL,
670/*.ninputs=*/1,
671/*.noutputs=*/0,
672/*.init*/NULL,
673/*.preprocess=*/msandroid_sound_write_preprocess,
674/*.process=*/msandroid_sound_write_process,
675/*.postprocess=*/msandroid_sound_write_postprocess,
676/*.uninit*/NULL,
677/*.methods=*/msandroid_sound_write_methods
678};
679
680
681MSFilter *msandroid_sound_write_new(MSSndCard *card){
682        ms_debug("msandroid_sound_write_new");
683        MSFilter *f=ms_filter_new_from_desc(&msandroid_sound_write_desc);
684        f->data=new msandroid_sound_write_data();
685        return f;
686}
687
688
689MS_FILTER_DESC_EXPORT(msandroid_sound_write_desc)
690
691extern "C" void ms_andsnd_register_card(JavaVM *jvm) {
692
693        ms_andsnd_jvm=jvm;
694        /**
695         * register audio unit plugin should be move to linphone code
696         */
697
698        ms_snd_card_manager_register_desc(ms_snd_card_manager_get(),&msandroid_sound_card_desc);
699}       
Note: See TracBrowser for help on using the repository browser.