source: mediastreamer2/src/android-display.c @ 1192:29ad880561b5

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

android display in progress

File size: 5.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
28/*defined in msandroid.cpp*/
29extern JavaVM *ms_andsnd_jvm;
30
31typedef struct AndroidDisplay{
32        JavaVM *jvm;
33        JNIEnv *jenv;
34        jobject android_video_window;
35        jobject jbitmap;
36        jmethodID get_bitmap_id;
37        jmethodID update_id;
38        AndroidBitmapInfo bmpinfo;
39        struct ms_SwsContext *sws;
40        MSVideoSize vsize;
41}AndroidDisplay;
42
43static void android_display_init(MSFilter *f){
44        AndroidDisplay *ad=(AndroidDisplay*)ms_new0(AndroidDisplay,1);
45        JNIEnv *jenv=NULL;
46        jclass wc;
47
48        ad->jvm=ms_andsnd_jvm;
49
50        if ((*(ad->jvm))->AttachCurrentThread(ad->jvm,&jenv,NULL)!=0){
51                ms_error("Could not get JNIEnv");
52                return ;
53        }
54        wc=(*jenv)->FindClass(jenv,"org/linphone/core/AndroidVideoWindowImpl");
55        if (wc==0){
56                ms_fatal("Could not find org.linphone.core.AndroidVideoWindowImpl class !");
57        }
58        ad->get_bitmap_id=(*jenv)->GetMethodID(jenv,wc,"getBitmap", "()Landroid/graphics/Bitmap;");
59        ad->update_id=(*jenv)->GetMethodID(jenv,wc,"update","()V");
60
61        MS_VIDEO_SIZE_ASSIGN(ad->vsize,CIF);
62        f->data=ad;
63}
64
65static void android_display_uninit(MSFilter *f){
66        AndroidDisplay *ad=(AndroidDisplay*)f->data;
67        if (ad->sws){
68                ms_sws_freeContext (ad->sws);
69                ad->sws=NULL;
70        }
71        ms_free(ad);
72}
73
74static void android_display_preprocess(MSFilter *f){
75       
76}
77
78static void android_display_process(MSFilter *f){
79        AndroidDisplay *ad=(AndroidDisplay*)f->data;
80        MSPicture pic;
81        mblk_t *m;
82
83        if (ad->jenv==NULL){
84                jint result = (*(ad->jvm))->AttachCurrentThread(ad->jvm,&ad->jenv,NULL);
85                if (result != 0) {
86                        ms_error("android_display_process(): cannot attach VM");
87                        goto end;
88                }
89        }
90
91        ms_filter_lock(f);
92        if (ad->jbitmap!=0){
93                if ((m=ms_queue_peek_last(f->inputs[0]))!=NULL){
94                        if (ms_yuv_buf_init_from_mblk (&pic,m)==0){
95                                MSVideoSize wsize={ad->bmpinfo.width,ad->bmpinfo.height};
96                                MSVideoSize vsize={pic.w, pic.h};
97                                MSRect vrect;
98                                MSPicture dest={0};
99                                void *pixels=NULL;
100
101                                if (!ms_video_size_equal(vsize,ad->vsize)){
102                                        ad->vsize=vsize;
103                                        if (ad->sws){
104                                                ms_sws_freeContext (ad->sws);
105                                                ad->sws=NULL;
106                                        }
107                                }
108                               
109                                ms_layout_compute(wsize,vsize,vsize,-1,0,&vrect, NULL);
110
111                                if (ad->sws==NULL){
112                                        ad->sws=ms_sws_getContext (vsize.width,vsize.height,PIX_FMT_YUV420P,
113                                                                   vrect.w,vrect.h,PIX_FMT_RGB565,SWS_BILINEAR,NULL,NULL,NULL);
114                                        if (ad->sws==NULL){
115                                                ms_fatal("Could not obtain sws context !");
116                                        }
117                                }
118                                if (AndroidBitmap_lockPixels(ad->jenv,ad->jbitmap,&pixels)==0){
119                                        dest.planes[0]=(uint8_t*)pixels+(vrect.y*ad->bmpinfo.stride)+(vrect.x*2);
120                                        dest.strides[0]=ad->bmpinfo.stride;
121                                        ms_sws_scale (ad->sws,pic.planes,pic.strides,0,pic.h,dest.planes,dest.strides);
122                                        AndroidBitmap_unlockPixels(ad->jenv,ad->jbitmap);
123                                }else{
124                                        ms_error("AndroidBitmap_lockPixels() failed !");
125                                }
126                                ms_message("Ask draw of bitmap");
127                                (*ad->jenv)->CallVoidMethod(ad->jenv,ad->android_video_window,ad->update_id);
128                        }
129                }
130        }
131        ms_filter_unlock(f);
132       
133end:
134        ms_queue_flush(f->inputs[0]);
135        ms_queue_flush(f->inputs[1]);
136}
137
138static int android_display_set_window(MSFilter *f, void *arg){
139        AndroidDisplay *ad=(AndroidDisplay*)f->data;
140        unsigned long id=*(unsigned long*)arg;
141        int err;
142        JNIEnv *jenv=NULL;
143        jobject window=(jobject)id;
144       
145        if ((*(ad->jvm))->AttachCurrentThread(ad->jvm,&jenv,NULL)!=0){
146                ms_error("Could not get JNIEnv");
147                return -1;
148        }
149       
150        ms_filter_lock(f);
151        ad->jbitmap=(*jenv)->CallObjectMethod(jenv,window,ad->get_bitmap_id);
152        ad->android_video_window=window;
153        err=AndroidBitmap_getInfo(jenv,ad->jbitmap,&ad->bmpinfo);
154        if (err!=0){
155                ms_error("AndroidBitmap_getInfo() failed.");
156                ad->jbitmap=0;
157                ms_filter_unlock(f);
158                return -1;
159        }
160        ms_filter_unlock(f);
161        ms_message("New java bitmap given with w=%i,h=%i,stride=%i,format=%i",
162                   ad->bmpinfo.width,ad->bmpinfo.height,ad->bmpinfo.stride,ad->bmpinfo.format);
163}
164
165static MSFilterMethod methods[]={
166        {       MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID , android_display_set_window },
167        {       0, NULL}
168};
169
170MSFilterDesc ms_android_display_desc={
171        .id=MS_ANDROID_DISPLAY_ID,
172        .name="MSAndroidDisplay",
173        .text="Video display filter for Android.",
174        .category=MS_FILTER_OTHER,
175        .ninputs=2, /*number of inputs*/
176        .noutputs=0, /*number of outputs*/
177        .init=android_display_init,
178        .preprocess=android_display_preprocess,
179        .process=android_display_process,
180        .uninit=android_display_uninit
181};
182
183void libmsandroiddisplay_init(void){
184        ms_filter_register(&ms_android_display_desc);
185}
186
187
Note: See TracBrowser for help on using the repository browser.