source: mediastreamer2/src/msandroid.cpp @ 1029:975201674719

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

android tuning

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                qinit(&rq);
158                ms_mutex_init(&mutex,NULL);
159        };
160~msandroid_sound_read_data() {
161                ms_mutex_lock(&mutex);
162                flushq(&rq,0);
163                ms_mutex_unlock(&mutex);
164                ms_mutex_destroy(&mutex);
165        }
166        jobject                 audio_record;
167        jclass                  audio_record_class;
168        jbyteArray              read_buff;
169        ms_mutex_t              mutex;
170        queue_t                 rq;
171        int                             read_chunk_size;
172        unsigned long   ticker_count;
173
174
175
176};
177
178void* msandroid_read_cb(msandroid_sound_read_data* d) {
179        mblk_t *m;
180        int nread;
181        JNIEnv *jni_env = 0;
182        jmethodID read_id=0;
183        jmethodID record_id=0;
184
185
186        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
187        if (result != 0) {
188                ms_error("cannot attach VM\n");
189                goto end;
190        }
191        record_id = jni_env->GetMethodID(d->audio_record_class,"startRecording", "()V");
192        if(record_id==0) {
193                ms_error("cannot find AudioRecord.startRecording() method");
194                goto end;
195        }
196        //start recording
197        jni_env->CallVoidMethod(d->audio_record,record_id);
198
199        // int read (byte[] audioData, int offsetInBytes, int sizeInBytes)
200        read_id = jni_env->GetMethodID(d->audio_record_class,"read", "([BII)I");
201        if(read_id==0) {
202                ms_error("cannot find AudioRecord.read() method");
203                goto end;
204        }
205
206        while (d->started && (nread=jni_env->CallIntMethod(d->audio_record,read_id,d->read_buff,0, d->read_chunk_size))>0) {
207                m = allocb(nread,0);
208                jni_env->GetByteArrayRegion(d->read_buff, 0,nread, (jbyte*)m->b_wptr);
209                //ms_error("%i octets read",nread);
210                m->b_wptr += nread;
211                ms_mutex_lock(&d->mutex);
212                putq(&d->rq,m);
213                ms_mutex_unlock(&d->mutex);
214        };
215        goto end;
216        end: {
217                d->jvm->DetachCurrentThread();
218                return 0;
219        }
220}
221
222void msandroid_sound_read_preprocess(MSFilter *f){
223        ms_debug("andsnd_read_preprocess");
224        msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
225        JNIEnv *jni_env = 0;
226        jmethodID constructor_id=0;
227        jmethodID min_buff_size_id;
228        //jmethodID set_notification_period;
229        int rc;
230
231        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
232        if (result != 0) {
233                ms_error("cannot attach VM\n");
234                goto end;
235        }
236        d->audio_record_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/media/AudioRecord"));
237        if (d->audio_record_class == 0) {
238                ms_error("cannot find  android/media/AudioRecord\n");
239                goto end;
240        }
241
242        constructor_id = jni_env->GetMethodID(d->audio_record_class,"<init>", "(IIIII)V");
243        if (constructor_id == 0) {
244                ms_error("cannot find  AudioRecord (int audioSource, int sampleRateInHz, \
245                int channelConfig, int audioFormat, int bufferSizeInBytes)");
246                goto end;
247        }
248        min_buff_size_id = jni_env->GetStaticMethodID(d->audio_record_class,"getMinBufferSize", "(III)I");
249        if (min_buff_size_id == 0) {
250                ms_error("cannot find  AudioRecord.getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)");
251                goto end;
252        }
253        d->buff_size = jni_env->CallStaticIntMethod(d->audio_record_class,min_buff_size_id,d->rate,2/*CHANNEL_CONFIGURATION_MONO*/,2/*  ENCODING_PCM_16BIT */);
254        d->read_chunk_size = (d->rate*(d->bits/8)*d->nchannels)*0.02;
255
256        if (d->buff_size > 0) {
257                ms_message("Configuring recorder with [%i] bits  rate [%i] nchanels [%i] buff size [%i], chunk size [%i]"
258                                ,d->bits
259                                ,d->rate
260                                ,d->nchannels
261                                ,d->buff_size
262                                ,d->read_chunk_size);
263        } else {
264                ms_message("Cannot configure recorder with [%i] bits  rate [%i] nchanels [%i] buff size [%i] chunk size [%i]"
265                                ,d->bits
266                                ,d->rate
267                                ,d->nchannels
268                                ,d->buff_size
269                                ,d->read_chunk_size);
270                goto end;
271        }
272
273        d->read_buff = jni_env->NewByteArray(d->buff_size);
274        d->read_buff = (jbyteArray)jni_env->NewGlobalRef(d->read_buff);
275        if (d->read_buff == 0) {
276                ms_error("cannot instanciate read buff");
277                goto end;
278        }
279
280        d->audio_record =  jni_env->NewObject(d->audio_record_class
281                        ,constructor_id
282                        ,1/*MIC*/
283                        ,d->rate
284                        ,2/*CHANNEL_CONFIGURATION_MONO*/
285                        ,2/*  ENCODING_PCM_16BIT */
286                        ,d->buff_size);
287
288
289        d->audio_record = jni_env->NewGlobalRef(d->audio_record);
290        if (d->audio_record == 0) {
291                ms_error("cannot instanciate AudioRecord");
292                goto end;
293        }
294
295        d->started=true;
296        // start reader thread
297        rc = ms_thread_create(&d->thread_id, 0, (void*(*)(void*))msandroid_read_cb, d);
298        if (rc){
299                ms_error("cannot create read thread return code  is [%i]", rc);
300                d->started=false;
301                goto end;
302
303        }
304
305        goto end;
306        end: {
307                //d->jvm->DetachCurrentThread();
308                return;
309        }
310}
311
312void msandroid_sound_read_postprocess(MSFilter *f){
313        msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
314        JNIEnv *jni_env = 0;
315        jmethodID flush_id=0;
316        jmethodID stop_id=0;
317        jmethodID release_id=0;
318        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
319        if (result != 0) {
320                ms_error("cannot attach VM\n");
321                goto end;
322        }
323
324        //stop recording
325        stop_id = jni_env->GetMethodID(d->audio_record_class,"stop", "()V");
326        if(stop_id==0) {
327                ms_error("cannot find AudioRecord.stop() method");
328                goto end;
329        }
330
331        d->started = false;
332        if (d->thread_id !=0) ms_thread_join(d->thread_id,0);
333
334        if (d->audio_record) {
335                jni_env->CallVoidMethod(d->audio_record,stop_id);
336
337                //release recorder
338                release_id = jni_env->GetMethodID(d->audio_record_class,"release", "()V");
339                if(release_id==0) {
340                        ms_error("cannot find AudioRecord.release() method");
341                        goto end;
342                }
343                jni_env->CallVoidMethod(d->audio_record,release_id);
344        }
345        goto end;
346        end: {
347                if (d->audio_record) jni_env->DeleteGlobalRef(d->audio_record);
348                jni_env->DeleteGlobalRef(d->audio_record_class);
349                if (d->read_buff) jni_env->DeleteGlobalRef(d->read_buff);
350
351                //d->jvm->DetachCurrentThread();
352                return;
353        }
354}
355
356void msandroid_sound_read_process(MSFilter *f){
357        msandroid_sound_read_data *d=(msandroid_sound_read_data*)f->data;
358        mblk_t *m;
359       
360        ms_mutex_lock(&d->mutex);
361        m=peekq(&d->rq);
362       
363        if (d->ticker_count!=0 || m!=NULL){
364                //start incrementing the first time we have a packet
365                d->ticker_count++;
366        }
367        // get buffer only every 2 ticks + alpha
368        if (m != NULL && ((d->ticker_count % 2)==1 ||   (d->ticker_count % 50)==0 ) ) {
369                m=getq(&d->rq);
370                ms_queue_put(f->outputs[0],m);
371        }
372        ms_mutex_unlock(&d->mutex);
373
374}
375
376
377static MSFilterDesc msandroid_sound_read_desc={
378/*.id=*/MS_FILTER_PLUGIN_ID,
379/*.name=*/"MSAndSoundRead",
380/*.text=*/N_("Sound capture filter for Android"),
381/*.category=*/MS_FILTER_OTHER,
382/*.enc_fmt*/NULL,
383/*.ninputs=*/0,
384/*.noutputs=*/1,
385/*.init*/NULL,
386/*.preprocess=*/msandroid_sound_read_preprocess,
387/*.process=*/msandroid_sound_read_process,
388/*.postprocess=*/msandroid_sound_read_postprocess,
389/*.uninit*/NULL,
390/*.methods=*/msandroid_sound_read_methods
391};
392
393MSFilter *msandroid_sound_read_new(MSSndCard *card){
394        ms_debug("msandroid_sound_read_new");
395        MSFilter *f=ms_filter_new_from_desc(&msandroid_sound_read_desc);
396        f->data=new msandroid_sound_read_data();
397        return f;
398}
399
400MS_FILTER_DESC_EXPORT(msandroid_sound_read_desc)
401
402/***********************************write filter********************/
403int set_write_rate(MSFilter *f, void *arg){
404        int proposed_rate = *((int*)arg);
405        ms_debug("set_rate %d",proposed_rate);
406        msandroid_sound_data *d=(msandroid_sound_data*)f->data;
407        d->rate=proposed_rate;
408        return 0;
409        /*d->rate=44100; //to improve latency on msn 7k
410        if (proposed_rate == d->rate) {
411        return 0;
412        } else {
413                return d->rate;
414        }
415         */
416}
417
418MSFilterMethod msandroid_sound_write_methods[]={
419        {       MS_FILTER_SET_SAMPLE_RATE       , set_write_rate        },
420        {       MS_FILTER_GET_SAMPLE_RATE       , get_rate      },
421        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
422        {       0                               , NULL          }
423};
424
425
426class msandroid_sound_write_data : public msandroid_sound_data{
427public:
428        msandroid_sound_write_data() :audio_track_class(0),audio_track(0),write_chunk_size(0),writtenBytes(0){
429                bufferizer = ms_bufferizer_new();
430                ms_cond_init(&cond,0);
431        };
432        ~msandroid_sound_write_data() {
433                ms_mutex_lock(&mutex);
434                ms_bufferizer_flush(bufferizer);
435                ms_mutex_unlock(&mutex);
436                ms_bufferizer_destroy(bufferizer);
437                ms_cond_destroy(&cond);
438        }
439        jclass                  audio_track_class;
440        jobject                 audio_track;
441        MSBufferizer    *bufferizer;
442        ms_cond_t               cond;
443        int                     write_chunk_size;
444        unsigned int    writtenBytes;
445        unsigned int getWriteBuffSize() {
446                return buff_size;
447        }
448        int getWrittenFrames() {
449                return writtenBytes/(nchannels*(bits/8));
450        }
451};
452
453void* msandroid_write_cb(msandroid_sound_write_data* d) {
454        JNIEnv                  *jni_env = 0;
455        jbyteArray              write_buff;
456        jmethodID               write_id=0;
457        jmethodID play_id=0;
458
459        jint result;
460        int buff_size = d->getWriteBuffSize();
461        result = d->jvm->AttachCurrentThread(&jni_env,NULL);
462        if (result != 0) {
463                ms_error("cannot attach VM\n");
464                goto end;
465        }
466
467        // int write  (byte[] audioData, int offsetInBytes, int sizeInBytes)
468        write_id = jni_env->GetMethodID(d->audio_track_class,"write", "([BII)I");
469        if(write_id==0) {
470                ms_error("cannot find AudioTrack.write() method");
471                goto end;
472        }
473        play_id = jni_env->GetMethodID(d->audio_track_class,"play", "()V");
474        if(play_id==0) {
475                ms_error("cannot find AudioTrack.play() method");
476                goto end;
477        }
478        write_buff = jni_env->NewByteArray(buff_size);
479        uint8_t tmpBuff[buff_size];
480
481        //start playing
482        jni_env->CallVoidMethod(d->audio_track,play_id);
483
484        ms_bufferizer_flush(d->bufferizer);
485        while(d->started) {
486                mblk_t *m;
487                ms_mutex_lock(&d->mutex);
488                int bufferizer_size;
489                while((bufferizer_size = ms_bufferizer_get_avail(d->bufferizer)) >= d->write_chunk_size) {
490                        if (bufferizer_size > (d->rate*(d->bits/8)*d->nchannels)*.250) { //250 ms
491                                ms_warning("we are late [%i] bytes, flushing",bufferizer_size);
492                                ms_bufferizer_flush(d->bufferizer);
493
494                        } else {
495                                ms_bufferizer_read(d->bufferizer, tmpBuff, d->write_chunk_size);
496                                ms_mutex_unlock(&d->mutex);
497                                jni_env->SetByteArrayRegion(write_buff,0,d->write_chunk_size,(jbyte*)tmpBuff);
498                                int result = jni_env->CallIntMethod(d->audio_track,write_id,write_buff,0,d->write_chunk_size);
499                                d->writtenBytes+=result;
500                                if (result <= 0) {
501                                        ms_error("write operation has failed [%i]",result);
502                                }
503                                ms_mutex_lock(&d->mutex);
504                        }
505                }
506                if (d->started) ms_cond_wait(&d->cond,&d->mutex);
507                ms_mutex_unlock(&d->mutex);
508        }
509
510        goto end;
511        end: {
512                d->jvm->DetachCurrentThread();
513                return 0;
514        }
515
516}
517void msandroid_sound_write_preprocess(MSFilter *f){
518        ms_debug("andsnd_write_preprocess");
519        msandroid_sound_write_data *d=(msandroid_sound_write_data*)f->data;
520        JNIEnv *jni_env = 0;
521        jmethodID constructor_id=0;
522
523        int rc;
524        jmethodID min_buff_size_id;
525
526        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
527        if (result != 0) {
528                ms_error("cannot attach VM\n");
529                goto end;
530        }
531        d->audio_track_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/media/AudioTrack"));
532        if (d->audio_track_class == 0) {
533                ms_error("cannot find  android/media/AudioTrack\n");
534                goto end;
535        }
536
537        constructor_id = jni_env->GetMethodID(d->audio_track_class,"<init>", "(IIIIII)V");
538        if (constructor_id == 0) {
539                ms_error("cannot find  AudioTrack(int streamType, int sampleRateInHz, \
540                int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)");
541                goto end;
542        }
543
544        min_buff_size_id = jni_env->GetStaticMethodID(d->audio_track_class,"getMinBufferSize", "(III)I");
545        if (min_buff_size_id == 0) {
546                ms_error("cannot find  AudioTrack.getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)");
547                goto end;
548        }
549        d->buff_size = jni_env->CallStaticIntMethod(d->audio_track_class,min_buff_size_id,d->rate,2/*CHANNEL_CONFIGURATION_MONO*/,2/*  ENCODING_PCM_16BIT */);
550        d->write_chunk_size= (d->rate*(d->bits/8)*d->nchannels)*0.02;
551
552        if (d->buff_size > 0) {
553                ms_message("Configuring 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        } else {
560                ms_message("Cannot configure player with [%i] bits  rate [%i] nchanels [%i] buff size [%i] chunk size [%i]"
561                                ,d->bits
562                                ,d->rate
563                                ,d->nchannels
564                                ,d->buff_size
565                                ,d->write_chunk_size);
566                goto end;
567        }
568        d->audio_track =  jni_env->NewObject(d->audio_track_class
569                        ,constructor_id
570                        ,0/*STREAM_VOICE_CALL*/
571                        ,d->rate
572                        ,2/*CHANNEL_CONFIGURATION_MONO*/
573                        ,2/*  ENCODING_PCM_16BIT */
574                        ,d->buff_size
575                        ,1/*MODE_STREAM */);
576        d->audio_track = jni_env->NewGlobalRef(d->audio_track);
577        if (d->audio_track == 0) {
578                ms_error("cannot instanciate AudioTrack");
579                goto end;
580        }
581
582
583        // start reader thread
584        d->started = true;
585        rc = ms_thread_create(&d->thread_id, 0, (void*(*)(void*))msandroid_write_cb, d);
586        if (rc){
587                ms_error("cannot create write thread return code  is [%i]", rc);
588                d->started = false;
589                goto end;
590        }
591
592        goto end;
593        end: {
594                //d->jvm->DetachCurrentThread();
595                return;
596        }
597
598}
599
600void msandroid_sound_write_postprocess(MSFilter *f){
601        msandroid_sound_write_data *d=(msandroid_sound_write_data*)f->data;
602        JNIEnv *jni_env = 0;
603        jmethodID flush_id=0;
604        jmethodID stop_id=0;
605        jmethodID release_id=0;
606        jint result = d->jvm->AttachCurrentThread(&jni_env,NULL);
607        if (result != 0) {
608                ms_error("cannot attach VM\n");
609                goto end;
610        }
611
612        d->started=false;
613        ms_mutex_lock(&d->mutex);
614        ms_cond_signal(&d->cond);
615        ms_mutex_unlock(&d->mutex);
616        ms_thread_join(d->thread_id,0);
617        // flush
618        flush_id = jni_env->GetMethodID(d->audio_track_class,"flush", "()V");
619        if(flush_id==0) {
620                ms_error("cannot find AudioTrack.flush() method");
621                goto end;
622        }
623        if (d->audio_track) {
624
625                jni_env->CallVoidMethod(d->audio_track,flush_id);
626
627                //stop playing
628                stop_id = jni_env->GetMethodID(d->audio_track_class,"stop", "()V");
629                if(stop_id==0) {
630                        ms_error("cannot find AudioTrack.stop() method");
631                        goto end;
632                }
633                jni_env->CallVoidMethod(d->audio_track,stop_id);
634
635                //release playing
636                release_id = jni_env->GetMethodID(d->audio_track_class,"release", "()V");
637                if(release_id==0) {
638                        ms_error("cannot find AudioTrack.release() method");
639                        goto end;
640                }
641                jni_env->CallVoidMethod(d->audio_track,release_id);
642        }
643
644        goto end;
645end: {
646        if (d->audio_track) jni_env->DeleteGlobalRef(d->audio_track);
647        jni_env->DeleteGlobalRef(d->audio_track_class);
648        //d->jvm->DetachCurrentThread();
649        return;
650}
651
652}
653
654
655
656void msandroid_sound_write_process(MSFilter *f){
657        msandroid_sound_write_data *d=(msandroid_sound_write_data*)f->data;
658        if (d->started == false) return;
659        mblk_t *m;
660        while((m=ms_queue_get(f->inputs[0]))!=NULL){
661                ms_mutex_lock(&d->mutex);
662                ms_bufferizer_put(d->bufferizer,m);
663                ms_cond_signal(&d->cond);
664                ms_mutex_unlock(&d->mutex);
665        }
666}
667
668
669static MSFilterDesc msandroid_sound_write_desc={
670/*.id=*/MS_FILTER_PLUGIN_ID,
671/*.name=*/"MSAndSoundWrite",
672/*.text=*/N_("Sound playback filter for Android"),
673/*.category=*/MS_FILTER_OTHER,
674/*.enc_fmt*/NULL,
675/*.ninputs=*/1,
676/*.noutputs=*/0,
677/*.init*/NULL,
678/*.preprocess=*/msandroid_sound_write_preprocess,
679/*.process=*/msandroid_sound_write_process,
680/*.postprocess=*/msandroid_sound_write_postprocess,
681/*.uninit*/NULL,
682/*.methods=*/msandroid_sound_write_methods
683};
684
685
686MSFilter *msandroid_sound_write_new(MSSndCard *card){
687        ms_debug("msandroid_sound_write_new");
688        MSFilter *f=ms_filter_new_from_desc(&msandroid_sound_write_desc);
689        f->data=new msandroid_sound_write_data();
690        return f;
691}
692
693
694MS_FILTER_DESC_EXPORT(msandroid_sound_write_desc)
695
696extern "C" void ms_andsnd_register_card(JavaVM *jvm) {
697
698        ms_andsnd_jvm=jvm;
699        /**
700         * register audio unit plugin should be move to linphone code
701         */
702
703        ms_snd_card_manager_register_desc(ms_snd_card_manager_get(),&msandroid_sound_card_desc);
704}       
Note: See TracBrowser for help on using the repository browser.