source: mediastreamer2/src/android-display.c @ 1193:58278fd087fd

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

rework msandroiddisplay filter to be included statically

File size: 6.2 KB
Line 
1/*
2mediastreamer2 android video display filter
3Copyright (C) 2010 Belledonne Communications SARL (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#include "ffmpeg-priv.h"
21
22#include "mediastreamer2/msfilter.h"
23#include "mediastreamer2/msvideo.h"
24#include "layouts.h"
25#include <android/bitmap.h>
26#include <jni.h>
27#include <dlfcn.h>
28
29/*defined in msandroid.cpp*/
30extern JavaVM *ms_andsnd_jvm;
31
32typedef struct AndroidDisplay{
33        JavaVM *jvm;
34        JNIEnv *jenv;
35        jobject android_video_window;
36        jobject jbitmap;
37        jmethodID get_bitmap_id;
38        jmethodID update_id;
39        AndroidBitmapInfo bmpinfo;
40        struct ms_SwsContext *sws;
41        MSVideoSize vsize;
42}AndroidDisplay;
43
44
45static int (*sym_AndroidBitmap_getInfo)(JNIEnv *env,jobject bitmap, AndroidBitmapInfo *bmpinfo)=NULL;
46static int (*sym_AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **pixels)=NULL;
47static int (*sym_AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap)=NULL;
48
49static void android_display_init(MSFilter *f){
50        AndroidDisplay *ad=(AndroidDisplay*)ms_new0(AndroidDisplay,1);
51        JNIEnv *jenv=NULL;
52        jclass wc;
53
54        ad->jvm=ms_andsnd_jvm;
55
56        if ((*(ad->jvm))->AttachCurrentThread(ad->jvm,&jenv,NULL)!=0){
57                ms_error("Could not get JNIEnv");
58                return ;
59        }
60        wc=(*jenv)->FindClass(jenv,"org/linphone/core/AndroidVideoWindowImpl");
61        if (wc==0){
62                ms_fatal("Could not find org.linphone.core.AndroidVideoWindowImpl class !");
63        }
64        ad->get_bitmap_id=(*jenv)->GetMethodID(jenv,wc,"getBitmap", "()Landroid/graphics/Bitmap;");
65        ad->update_id=(*jenv)->GetMethodID(jenv,wc,"update","()V");
66
67        MS_VIDEO_SIZE_ASSIGN(ad->vsize,CIF);
68        f->data=ad;
69}
70
71static void android_display_uninit(MSFilter *f){
72        AndroidDisplay *ad=(AndroidDisplay*)f->data;
73        if (ad->sws){
74                ms_sws_freeContext (ad->sws);
75                ad->sws=NULL;
76        }
77        ms_free(ad);
78}
79
80static void android_display_preprocess(MSFilter *f){
81       
82}
83
84static void android_display_process(MSFilter *f){
85        AndroidDisplay *ad=(AndroidDisplay*)f->data;
86        MSPicture pic;
87        mblk_t *m;
88
89        if (ad->jenv==NULL){
90                jint result = (*(ad->jvm))->AttachCurrentThread(ad->jvm,&ad->jenv,NULL);
91                if (result != 0) {
92                        ms_error("android_display_process(): cannot attach VM");
93                        goto end;
94                }
95        }
96
97        ms_filter_lock(f);
98        if (ad->jbitmap!=0){
99                if ((m=ms_queue_peek_last(f->inputs[0]))!=NULL){
100                        if (ms_yuv_buf_init_from_mblk (&pic,m)==0){
101                                MSVideoSize wsize={ad->bmpinfo.width,ad->bmpinfo.height};
102                                MSVideoSize vsize={pic.w, pic.h};
103                                MSRect vrect;
104                                MSPicture dest={0};
105                                void *pixels=NULL;
106
107                                if (!ms_video_size_equal(vsize,ad->vsize)){
108                                        ad->vsize=vsize;
109                                        if (ad->sws){
110                                                ms_sws_freeContext (ad->sws);
111                                                ad->sws=NULL;
112                                        }
113                                }
114                               
115                                ms_layout_compute(wsize,vsize,vsize,-1,0,&vrect, NULL);
116
117                                if (ad->sws==NULL){
118                                        ad->sws=ms_sws_getContext (vsize.width,vsize.height,PIX_FMT_YUV420P,
119                                                                   vrect.w,vrect.h,PIX_FMT_RGB565,SWS_BILINEAR,NULL,NULL,NULL);
120                                        if (ad->sws==NULL){
121                                                ms_fatal("Could not obtain sws context !");
122                                        }
123                                }
124                                if (sym_AndroidBitmap_lockPixels(ad->jenv,ad->jbitmap,&pixels)==0){
125                                        dest.planes[0]=(uint8_t*)pixels+(vrect.y*ad->bmpinfo.stride)+(vrect.x*2);
126                                        dest.strides[0]=ad->bmpinfo.stride;
127                                        ms_sws_scale (ad->sws,pic.planes,pic.strides,0,pic.h,dest.planes,dest.strides);
128                                        sym_AndroidBitmap_unlockPixels(ad->jenv,ad->jbitmap);
129                                }else{
130                                        ms_error("AndroidBitmap_lockPixels() failed !");
131                                }
132                                ms_message("Ask draw of bitmap");
133                                (*ad->jenv)->CallVoidMethod(ad->jenv,ad->android_video_window,ad->update_id);
134                        }
135                }
136        }
137        ms_filter_unlock(f);
138       
139end:
140        ms_queue_flush(f->inputs[0]);
141        ms_queue_flush(f->inputs[1]);
142}
143
144static int android_display_set_window(MSFilter *f, void *arg){
145        AndroidDisplay *ad=(AndroidDisplay*)f->data;
146        unsigned long id=*(unsigned long*)arg;
147        int err;
148        JNIEnv *jenv=NULL;
149        jobject window=(jobject)id;
150       
151        if ((*(ad->jvm))->AttachCurrentThread(ad->jvm,&jenv,NULL)!=0){
152                ms_error("Could not get JNIEnv");
153                return -1;
154        }
155       
156        ms_filter_lock(f);
157        ad->jbitmap=(*jenv)->CallObjectMethod(jenv,window,ad->get_bitmap_id);
158        ad->android_video_window=window;
159        err=sym_AndroidBitmap_getInfo(jenv,ad->jbitmap,&ad->bmpinfo);
160        if (err!=0){
161                ms_error("AndroidBitmap_getInfo() failed.");
162                ad->jbitmap=0;
163                ms_filter_unlock(f);
164                return -1;
165        }
166        ms_filter_unlock(f);
167        ms_message("New java bitmap given with w=%i,h=%i,stride=%i,format=%i",
168                   ad->bmpinfo.width,ad->bmpinfo.height,ad->bmpinfo.stride,ad->bmpinfo.format);
169}
170
171static MSFilterMethod methods[]={
172        {       MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID , android_display_set_window },
173        {       0, NULL}
174};
175
176MSFilterDesc ms_android_display_desc={
177        .id=MS_ANDROID_DISPLAY_ID,
178        .name="MSAndroidDisplay",
179        .text="Video display filter for Android.",
180        .category=MS_FILTER_OTHER,
181        .ninputs=2, /*number of inputs*/
182        .noutputs=0, /*number of outputs*/
183        .init=android_display_init,
184        .preprocess=android_display_preprocess,
185        .process=android_display_process,
186        .uninit=android_display_uninit
187};
188
189void libmsandroiddisplay_init(void){
190        /*See if we can use AndroidBitmap_* symbols (only since android 2.2 normally)*/
191        void *handle=dlopen("libjnigraphics.so",RTLD_LAZY);
192        if (handle!=NULL){
193                sym_AndroidBitmap_getInfo=dlsym(handle,"AndroidBitmap_getInfo");
194                sym_AndroidBitmap_lockPixels=dlsym(handle,"AndroidBitmap_lockPixels");
195                sym_AndroidBitmap_unlockPixels=dlsym(handle,"AndroidBitmap_unlockPixels");
196
197                if (sym_AndroidBitmap_getInfo==NULL || sym_AndroidBitmap_lockPixels==NULL
198                        || sym_AndroidBitmap_unlockPixels==NULL){
199                        ms_warning("AndroidBitmap not available.");
200                }else{
201                        ms_filter_register(&ms_android_display_desc);
202                        ms_message("MSAndroidDisplay registered.");
203                }
204        }else ms_warning("libjnigraphics.so cannot be loaded.");
205}
206
207
Note: See TracBrowser for help on using the repository browser.