2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.example.nativemedia;
19 import android.app.Activity;
20 import android.graphics.SurfaceTexture;
21 import android.media.MediaPlayer;
22 import android.os.Bundle;
23 import android.util.Log;
24 import android.view.Surface;
25 import android.view.SurfaceHolder;
26 import android.view.SurfaceView;
27 import android.view.View;
28 import android.widget.AdapterView;
29 import android.widget.ArrayAdapter;
30 import android.widget.Button;
31 import android.widget.Spinner;
32 import java.io.IOException;
34 import android.content.Context;
36 import android.graphics.SurfaceTexture;
38 import android.media.MediaPlayer.OnPreparedListener;
39 import android.media.MediaPlayer;
41 public class NativeMedia extends Activity {
42 static final String TAG = "NativeMedia";
44 String mSourceString = null;
45 String mSinkString = null;
47 // member variables for Java media player
48 MediaPlayer mMediaPlayer;
49 boolean mMediaPlayerIsPrepared = false;
50 SurfaceView mSurfaceView1;
51 SurfaceHolder mSurfaceHolder1;
53 // member variables for native media player
54 boolean mIsPlayingStreaming = false;
55 SurfaceView mSurfaceView2;
56 SurfaceHolder mSurfaceHolder2;
58 VideoSink mSelectedVideoSink;
59 VideoSink mJavaMediaPlayerVideoSink;
60 VideoSink mNativeMediaPlayerVideoSink;
62 SurfaceHolderVideoSink mSurfaceHolder1VideoSink, mSurfaceHolder2VideoSink;
63 GLViewVideoSink mGLView1VideoSink, mGLView2VideoSink;
65 /** Called when the activity is first created. */
67 public void onCreate(Bundle icicle) {
68 super.onCreate(icicle);
69 setContentView(R.layout.main);
71 mGLView1 = (MyGLSurfaceView) findViewById(R.id.glsurfaceview1);
72 mGLView2 = (MyGLSurfaceView) findViewById(R.id.glsurfaceview2);
74 //setContentView(mGLView);
75 //setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
77 // initialize native media system
80 // set up the Surface 1 video sink
81 mSurfaceView1 = (SurfaceView) findViewById(R.id.surfaceview1);
82 mSurfaceHolder1 = mSurfaceView1.getHolder();
84 mSurfaceHolder1.addCallback(new SurfaceHolder.Callback() {
86 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
87 Log.v(TAG, "surfaceChanged format=" + format + ", width=" + width + ", height=" + height);
90 public void surfaceCreated(SurfaceHolder holder) {
91 Log.v(TAG, "surfaceCreated");
92 setSurface(holder.getSurface());
95 public void surfaceDestroyed(SurfaceHolder holder) {
96 Log.v(TAG, "surfaceDestroyed");
101 // set up the Surface 2 video sink
102 mSurfaceView2 = (SurfaceView) findViewById(R.id.surfaceview2);
103 mSurfaceHolder2 = mSurfaceView2.getHolder();
105 mSurfaceHolder2.addCallback(new SurfaceHolder.Callback() {
107 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
108 Log.v(TAG, "surfaceChanged format=" + format + ", width=" + width + ", height=" + height);
111 public void surfaceCreated(SurfaceHolder holder) {
112 Log.v(TAG, "surfaceCreated");
113 setSurface(holder.getSurface());
116 public void surfaceDestroyed(SurfaceHolder holder) {
117 Log.v(TAG, "surfaceDestroyed");
122 // create Java media player
123 mMediaPlayer = new MediaPlayer();
125 // set up Java media player listeners
126 mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
128 public void onPrepared(MediaPlayer mediaPlayer) {
129 int width = mediaPlayer.getVideoWidth();
130 int height = mediaPlayer.getVideoHeight();
131 Log.v(TAG, "onPrepared width=" + width + ", height=" + height);
132 if (width != 0 && height != 0 && mJavaMediaPlayerVideoSink != null) {
133 mJavaMediaPlayerVideoSink.setFixedSize(width, height);
135 mMediaPlayerIsPrepared = true;
141 mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
143 public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
144 Log.v(TAG, "onVideoSizeChanged width=" + width + ", height=" + height);
145 if (width != 0 && height != 0 && mJavaMediaPlayerVideoSink != null) {
146 mJavaMediaPlayerVideoSink.setFixedSize(width, height);
152 // initialize content source spinner
153 Spinner sourceSpinner = (Spinner) findViewById(R.id.source_spinner);
154 ArrayAdapter<CharSequence> sourceAdapter = ArrayAdapter.createFromResource(
155 this, R.array.source_array, android.R.layout.simple_spinner_item);
156 sourceAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
157 sourceSpinner.setAdapter(sourceAdapter);
158 sourceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
160 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
161 mSourceString = parent.getItemAtPosition(pos).toString();
162 Log.v(TAG, "onItemSelected " + mSourceString);
165 public void onNothingSelected(AdapterView parent) {
166 Log.v(TAG, "onNothingSelected");
167 mSourceString = null;
172 // initialize video sink spinner
173 Spinner sinkSpinner = (Spinner) findViewById(R.id.sink_spinner);
174 ArrayAdapter<CharSequence> sinkAdapter = ArrayAdapter.createFromResource(
175 this, R.array.sink_array, android.R.layout.simple_spinner_item);
176 sinkAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
177 sinkSpinner.setAdapter(sinkAdapter);
178 sinkSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
180 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
181 mSinkString = parent.getItemAtPosition(pos).toString();
182 Log.v(TAG, "onItemSelected " + mSinkString);
183 if ("Surface 1".equals(mSinkString)) {
184 if (mSurfaceHolder1VideoSink == null) {
185 mSurfaceHolder1VideoSink = new SurfaceHolderVideoSink(mSurfaceHolder1);
187 mSelectedVideoSink = mSurfaceHolder1VideoSink;
188 } else if ("Surface 2".equals(mSinkString)) {
189 if (mSurfaceHolder2VideoSink == null) {
190 mSurfaceHolder2VideoSink = new SurfaceHolderVideoSink(mSurfaceHolder2);
192 mSelectedVideoSink = mSurfaceHolder2VideoSink;
193 } else if ("SurfaceTexture 1".equals(mSinkString)) {
194 if (mGLView1VideoSink == null) {
195 mGLView1VideoSink = new GLViewVideoSink(mGLView1);
197 mSelectedVideoSink = mGLView1VideoSink;
198 } else if ("SurfaceTexture 2".equals(mSinkString)) {
199 if (mGLView2VideoSink == null) {
200 mGLView2VideoSink = new GLViewVideoSink(mGLView2);
202 mSelectedVideoSink = mGLView2VideoSink;
206 public void onNothingSelected(AdapterView parent) {
207 Log.v(TAG, "onNothingSelected");
209 mSelectedVideoSink = null;
214 // initialize button click handlers
216 // Java MediaPlayer start/pause
218 ((Button) findViewById(R.id.start_java)).setOnClickListener(new View.OnClickListener() {
220 public void onClick(View view) {
221 if (mJavaMediaPlayerVideoSink == null) {
222 if (mSelectedVideoSink == null) {
225 mSelectedVideoSink.useAsSinkForJava(mMediaPlayer);
226 mJavaMediaPlayerVideoSink = mSelectedVideoSink;
228 if (!mMediaPlayerIsPrepared) {
229 if (mSourceString != null) {
231 mMediaPlayer.setDataSource(mSourceString);
232 } catch (IOException e) {
233 Log.e(TAG, "IOException " + e);
235 mMediaPlayer.prepareAsync();
237 } else if (mMediaPlayer.isPlaying()) {
238 mMediaPlayer.pause();
240 mMediaPlayer.start();
246 // native MediaPlayer start/pause
248 ((Button) findViewById(R.id.start_native)).setOnClickListener(new View.OnClickListener() {
250 boolean created = false;
251 public void onClick(View view) {
253 if (mNativeMediaPlayerVideoSink == null) {
254 if (mSelectedVideoSink == null) {
257 mSelectedVideoSink.useAsSinkForNative();
258 mNativeMediaPlayerVideoSink = mSelectedVideoSink;
260 if (mSourceString != null) {
261 created = createStreamingMediaPlayer(mSourceString);
265 mIsPlayingStreaming = !mIsPlayingStreaming;
266 setPlayingStreamingMediaPlayer(mIsPlayingStreaming);
274 /** Called when the activity is about to be paused. */
276 protected void onPause()
278 mIsPlayingStreaming = false;
279 setPlayingStreamingMediaPlayer(false);
286 protected void onResume() {
292 /** Called when the activity is about to be destroyed. */
294 protected void onDestroy()
300 private MyGLSurfaceView mGLView1, mGLView2;
302 /** Native methods, implemented in jni folder */
303 public static native void createEngine();
304 public static native boolean createStreamingMediaPlayer(String filename);
305 public static native void setPlayingStreamingMediaPlayer(boolean isPlaying);
306 public static native void shutdown();
307 public static native void setSurface(Surface surface);
308 public static native void setSurfaceTexture(SurfaceTexture surfaceTexture);
310 /** Load jni .so on initialization */
312 System.loadLibrary("native-media-jni");
315 // VideoSink abstracts out the difference between Surface and SurfaceTexture
316 // aka SurfaceHolder and GLSurfaceView
317 static abstract class VideoSink {
319 abstract void setFixedSize(int width, int height);
320 abstract void useAsSinkForJava(MediaPlayer mediaPlayer);
321 abstract void useAsSinkForNative();
325 static class SurfaceHolderVideoSink extends VideoSink {
327 private final SurfaceHolder mSurfaceHolder;
329 SurfaceHolderVideoSink(SurfaceHolder surfaceHolder) {
330 mSurfaceHolder = surfaceHolder;
333 void setFixedSize(int width, int height) {
334 mSurfaceHolder.setFixedSize(width, height);
337 void useAsSinkForJava(MediaPlayer mediaPlayer) {
338 mediaPlayer.setDisplay(mSurfaceHolder);
341 void useAsSinkForNative() {
342 setSurface(mSurfaceHolder.getSurface());
347 static class GLViewVideoSink extends VideoSink {
349 private final MyGLSurfaceView mMyGLSurfaceView;
351 GLViewVideoSink(MyGLSurfaceView myGLSurfaceView) {
352 mMyGLSurfaceView = myGLSurfaceView;
355 void setFixedSize(int width, int height) {
358 void useAsSinkForJava(MediaPlayer mediaPlayer) {
359 // This API is @hide currently, so use reflection instead:
360 // mMediaPlayer.setTexture(surfaceTexture);
361 Class clazz = MediaPlayer.class;
362 Class[] types = new Class[] { SurfaceTexture.class };
363 Object[] arglist = new Object[] { mMyGLSurfaceView.getSurfaceTexture() };
365 clazz.getMethod("setTexture", types).invoke(mediaPlayer, arglist);
366 } catch (NoSuchMethodException e) {
367 } catch (IllegalAccessException e) {
368 } catch (java.lang.reflect.InvocationTargetException e) {
372 void useAsSinkForNative() {
373 setSurfaceTexture(mMyGLSurfaceView.getSurfaceTexture());