/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.nativemedia; import android.app.Activity; import android.graphics.SurfaceTexture; import android.media.MediaPlayer; import android.os.Bundle; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; import java.io.IOException; import android.content.Context; import android.graphics.SurfaceTexture; import android.media.MediaPlayer.OnPreparedListener; import android.media.MediaPlayer; public class NativeMedia extends Activity { static final String TAG = "NativeMedia"; String mSourceString = null; String mSinkString = null; // member variables for Java media player MediaPlayer mMediaPlayer; boolean mMediaPlayerIsPrepared = false; SurfaceView mSurfaceView1; SurfaceHolder mSurfaceHolder1; // member variables for native media player boolean mIsPlayingStreaming = false; SurfaceView mSurfaceView2; SurfaceHolder mSurfaceHolder2; VideoSink mSelectedVideoSink; VideoSink mJavaMediaPlayerVideoSink; VideoSink mNativeMediaPlayerVideoSink; SurfaceHolderVideoSink mSurfaceHolder1VideoSink, mSurfaceHolder2VideoSink; GLViewVideoSink mGLView1VideoSink, mGLView2VideoSink; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); mGLView1 = (MyGLSurfaceView) findViewById(R.id.glsurfaceview1); mGLView2 = (MyGLSurfaceView) findViewById(R.id.glsurfaceview2); //setContentView(mGLView); //setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // initialize native media system createEngine(); // set up the Surface 1 video sink mSurfaceView1 = (SurfaceView) findViewById(R.id.surfaceview1); mSurfaceHolder1 = mSurfaceView1.getHolder(); mSurfaceHolder1.addCallback(new SurfaceHolder.Callback() { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v(TAG, "surfaceChanged format=" + format + ", width=" + width + ", height=" + height); } public void surfaceCreated(SurfaceHolder holder) { Log.v(TAG, "surfaceCreated"); setSurface(holder.getSurface()); } public void surfaceDestroyed(SurfaceHolder holder) { Log.v(TAG, "surfaceDestroyed"); } }); // set up the Surface 2 video sink mSurfaceView2 = (SurfaceView) findViewById(R.id.surfaceview2); mSurfaceHolder2 = mSurfaceView2.getHolder(); mSurfaceHolder2.addCallback(new SurfaceHolder.Callback() { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v(TAG, "surfaceChanged format=" + format + ", width=" + width + ", height=" + height); } public void surfaceCreated(SurfaceHolder holder) { Log.v(TAG, "surfaceCreated"); setSurface(holder.getSurface()); } public void surfaceDestroyed(SurfaceHolder holder) { Log.v(TAG, "surfaceDestroyed"); } }); // create Java media player mMediaPlayer = new MediaPlayer(); // set up Java media player listeners mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mediaPlayer) { int width = mediaPlayer.getVideoWidth(); int height = mediaPlayer.getVideoHeight(); Log.v(TAG, "onPrepared width=" + width + ", height=" + height); if (width != 0 && height != 0 && mJavaMediaPlayerVideoSink != null) { mJavaMediaPlayerVideoSink.setFixedSize(width, height); } mMediaPlayerIsPrepared = true; mediaPlayer.start(); } }); mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() { public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) { Log.v(TAG, "onVideoSizeChanged width=" + width + ", height=" + height); if (width != 0 && height != 0 && mJavaMediaPlayerVideoSink != null) { mJavaMediaPlayerVideoSink.setFixedSize(width, height); } } }); // initialize content source spinner Spinner sourceSpinner = (Spinner) findViewById(R.id.source_spinner); ArrayAdapter sourceAdapter = ArrayAdapter.createFromResource( this, R.array.source_array, android.R.layout.simple_spinner_item); sourceAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sourceSpinner.setAdapter(sourceAdapter); sourceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int pos, long id) { mSourceString = parent.getItemAtPosition(pos).toString(); Log.v(TAG, "onItemSelected " + mSourceString); } public void onNothingSelected(AdapterView parent) { Log.v(TAG, "onNothingSelected"); mSourceString = null; } }); // initialize video sink spinner Spinner sinkSpinner = (Spinner) findViewById(R.id.sink_spinner); ArrayAdapter sinkAdapter = ArrayAdapter.createFromResource( this, R.array.sink_array, android.R.layout.simple_spinner_item); sinkAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sinkSpinner.setAdapter(sinkAdapter); sinkSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int pos, long id) { mSinkString = parent.getItemAtPosition(pos).toString(); Log.v(TAG, "onItemSelected " + mSinkString); if ("Surface 1".equals(mSinkString)) { if (mSurfaceHolder1VideoSink == null) { mSurfaceHolder1VideoSink = new SurfaceHolderVideoSink(mSurfaceHolder1); } mSelectedVideoSink = mSurfaceHolder1VideoSink; } else if ("Surface 2".equals(mSinkString)) { if (mSurfaceHolder2VideoSink == null) { mSurfaceHolder2VideoSink = new SurfaceHolderVideoSink(mSurfaceHolder2); } mSelectedVideoSink = mSurfaceHolder2VideoSink; } else if ("SurfaceTexture 1".equals(mSinkString)) { if (mGLView1VideoSink == null) { mGLView1VideoSink = new GLViewVideoSink(mGLView1); } mSelectedVideoSink = mGLView1VideoSink; } else if ("SurfaceTexture 2".equals(mSinkString)) { if (mGLView2VideoSink == null) { mGLView2VideoSink = new GLViewVideoSink(mGLView2); } mSelectedVideoSink = mGLView2VideoSink; } } public void onNothingSelected(AdapterView parent) { Log.v(TAG, "onNothingSelected"); mSinkString = null; mSelectedVideoSink = null; } }); // initialize button click handlers // Java MediaPlayer start/pause ((Button) findViewById(R.id.start_java)).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (mJavaMediaPlayerVideoSink == null) { if (mSelectedVideoSink == null) { return; } mSelectedVideoSink.useAsSinkForJava(mMediaPlayer); mJavaMediaPlayerVideoSink = mSelectedVideoSink; } if (!mMediaPlayerIsPrepared) { if (mSourceString != null) { try { mMediaPlayer.setDataSource(mSourceString); } catch (IOException e) { Log.e(TAG, "IOException " + e); } mMediaPlayer.prepareAsync(); } } else if (mMediaPlayer.isPlaying()) { mMediaPlayer.pause(); } else { mMediaPlayer.start(); } } }); // native MediaPlayer start/pause ((Button) findViewById(R.id.start_native)).setOnClickListener(new View.OnClickListener() { boolean created = false; public void onClick(View view) { if (!created) { if (mNativeMediaPlayerVideoSink == null) { if (mSelectedVideoSink == null) { return; } mSelectedVideoSink.useAsSinkForNative(); mNativeMediaPlayerVideoSink = mSelectedVideoSink; } if (mSourceString != null) { created = createStreamingMediaPlayer(mSourceString); } } if (created) { mIsPlayingStreaming = !mIsPlayingStreaming; setPlayingStreamingMediaPlayer(mIsPlayingStreaming); } } }); // Java MediaPlayer rewind ((Button) findViewById(R.id.rewind_java)).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (mMediaPlayerIsPrepared) { mMediaPlayer.seekTo(0); } } }); // native MediaPlayer rewind ((Button) findViewById(R.id.rewind_native)).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (mNativeMediaPlayerVideoSink != null) { rewindStreamingMediaPlayer(); } } }); } /** Called when the activity is about to be paused. */ @Override protected void onPause() { mIsPlayingStreaming = false; setPlayingStreamingMediaPlayer(false); mGLView1.onPause(); mGLView2.onPause(); super.onPause(); } @Override protected void onResume() { super.onResume(); mGLView1.onResume(); mGLView2.onResume(); } /** Called when the activity is about to be destroyed. */ @Override protected void onDestroy() { shutdown(); super.onDestroy(); } private MyGLSurfaceView mGLView1, mGLView2; /** Native methods, implemented in jni folder */ public static native void createEngine(); public static native boolean createStreamingMediaPlayer(String filename); public static native void setPlayingStreamingMediaPlayer(boolean isPlaying); public static native void shutdown(); public static native void setSurface(Surface surface); public static native void rewindStreamingMediaPlayer(); /** Load jni .so on initialization */ static { System.loadLibrary("native-media-jni"); } // VideoSink abstracts out the difference between Surface and SurfaceTexture // aka SurfaceHolder and GLSurfaceView static abstract class VideoSink { abstract void setFixedSize(int width, int height); abstract void useAsSinkForJava(MediaPlayer mediaPlayer); abstract void useAsSinkForNative(); } static class SurfaceHolderVideoSink extends VideoSink { private final SurfaceHolder mSurfaceHolder; SurfaceHolderVideoSink(SurfaceHolder surfaceHolder) { mSurfaceHolder = surfaceHolder; } void setFixedSize(int width, int height) { mSurfaceHolder.setFixedSize(width, height); } void useAsSinkForJava(MediaPlayer mediaPlayer) { mediaPlayer.setDisplay(mSurfaceHolder); } void useAsSinkForNative() { setSurface(mSurfaceHolder.getSurface()); } } static class GLViewVideoSink extends VideoSink { private final MyGLSurfaceView mMyGLSurfaceView; GLViewVideoSink(MyGLSurfaceView myGLSurfaceView) { mMyGLSurfaceView = myGLSurfaceView; } void setFixedSize(int width, int height) { } void useAsSinkForJava(MediaPlayer mediaPlayer) { SurfaceTexture st = mMyGLSurfaceView.getSurfaceTexture(); Surface s = new Surface(st); mediaPlayer.setSurface(s); s.release(); } void useAsSinkForNative() { Surface surface = new Surface(mMyGLSurfaceView.getSurfaceTexture()); setSurface(surface); surface.release(); } } }