New file |
| | |
| | | /* |
| | | * Copyright (C) 2014 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.nativecodec; |
| | | |
| | | import android.app.Activity; |
| | | import android.graphics.PixelFormat; |
| | | import android.graphics.SurfaceTexture; |
| | | import android.graphics.drawable.Drawable; |
| | | 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.CompoundButton; |
| | | import android.widget.CompoundButton.OnCheckedChangeListener; |
| | | import android.widget.ImageButton; |
| | | import android.widget.ImageView; |
| | | import android.widget.RadioButton; |
| | | import android.widget.Spinner; |
| | | import android.content.Context; |
| | | import android.graphics.Bitmap; |
| | | import android.graphics.BitmapFactory; |
| | | import android.graphics.Canvas; |
| | | import android.util.AttributeSet; |
| | | import android.widget.Button; |
| | | import android.widget.TextView; |
| | | |
| | | import java.nio.ByteBuffer; |
| | | |
| | | import cn.com.basic.face.util.NativeImg; |
| | | import cn.com.basic.face.util.RtspFaceNative; |
| | | |
| | | public class NativeCodec extends Activity { |
| | | static final String TAG = "NativeCodec"; |
| | | |
| | | String mSourceString = null; |
| | | |
| | | SurfaceView mSurfaceView1; |
| | | SurfaceHolder mSurfaceHolder1; |
| | | |
| | | VideoSink mSelectedVideoSink; |
| | | VideoSink mNativeCodecPlayerVideoSink; |
| | | |
| | | SurfaceHolderVideoSink mSurfaceHolder1VideoSink; |
| | | GLViewVideoSink mGLView1VideoSink; |
| | | |
| | | boolean mCreated = false; |
| | | boolean mIsPlaying = false; |
| | | |
| | | public static NativeImg faceImg = null; |
| | | |
| | | /** Called when the activity is first created. */ |
| | | @Override |
| | | public void onCreate(Bundle icicle) { |
| | | super.onCreate(icicle); |
| | | setContentView(R.layout.main); |
| | | |
| | | ThisActivity = this; |
| | | |
| | | RtspFaceNative.init(); |
| | | RtspFaceNative.setLocalIP("192.168.1.10"); |
| | | |
| | | mGLView1 = (MyGLSurfaceView) findViewById(R.id.glsurfaceview1); |
| | | |
| | | // set up the Surface 1 video sink |
| | | mSurfaceView1 = (SurfaceView) findViewById(R.id.surfaceview1); |
| | | mSurfaceHolder1 = mSurfaceView1.getHolder(); |
| | | |
| | | |
| | | |
| | | mSurfaceHolder1.addCallback(new SurfaceHolder.Callback() { |
| | | |
| | | @Override |
| | | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { |
| | | Log.v(TAG, "surfaceChanged format=" + format + ", width=" + width + ", height=" |
| | | + height); |
| | | } |
| | | |
| | | @Override |
| | | public void surfaceCreated(SurfaceHolder holder) { |
| | | Log.v(TAG, "surfaceCreated"); |
| | | if (mRadio1.isChecked()) { |
| | | //setSurface(1, holder.getSurface()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void surfaceDestroyed(SurfaceHolder holder) { |
| | | Log.v(TAG, "surfaceDestroyed"); |
| | | } |
| | | |
| | | }); |
| | | |
| | | // initialize content source spinner |
| | | Spinner sourceSpinner = (Spinner) findViewById(R.id.source_spinner); |
| | | ArrayAdapter<CharSequence> 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() { |
| | | |
| | | @Override |
| | | public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { |
| | | mSourceString = parent.getItemAtPosition(pos).toString(); |
| | | Log.v(TAG, "onItemSelected " + mSourceString); |
| | | } |
| | | |
| | | @Override |
| | | public void onNothingSelected(AdapterView parent) { |
| | | Log.v(TAG, "onNothingSelected"); |
| | | mSourceString = null; |
| | | } |
| | | |
| | | }); |
| | | |
| | | mRadio1 = (RadioButton) findViewById(R.id.radio1); |
| | | mRadio2 = (RadioButton) findViewById(R.id.radio2); |
| | | |
| | | OnCheckedChangeListener checklistener = new CompoundButton.OnCheckedChangeListener() { |
| | | |
| | | @Override |
| | | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
| | | Log.i("@@@@", "oncheckedchanged"); |
| | | if (buttonView == mRadio1 && isChecked) { |
| | | mRadio2.setChecked(false); |
| | | } |
| | | if (buttonView == mRadio2 && isChecked) { |
| | | mRadio1.setChecked(false); |
| | | } |
| | | |
| | | |
| | | if (isChecked) { |
| | | if (mRadio1.isChecked()) { |
| | | if (mSurfaceHolder1VideoSink == null) { |
| | | mSurfaceHolder1VideoSink = new SurfaceHolderVideoSink(mSurfaceHolder1); |
| | | //mSurfaceHolder1VideoSink.useAsSinkForNative(); |
| | | } |
| | | mSelectedVideoSink = mSurfaceHolder1VideoSink; |
| | | mGLView1.onPause(); |
| | | Log.i("@@@@", "glview pause"); |
| | | } else { |
| | | mGLView1.onResume(); |
| | | if (mGLView1VideoSink == null) { |
| | | mGLView1VideoSink = new GLViewVideoSink(mGLView1); |
| | | //mGLView1VideoSink.useAsSinkForNative(); |
| | | } |
| | | mSelectedVideoSink = mGLView1VideoSink; |
| | | } |
| | | switchSurface(); |
| | | } |
| | | } |
| | | }; |
| | | mRadio1.setOnCheckedChangeListener(checklistener); |
| | | mRadio2.setOnCheckedChangeListener(checklistener); |
| | | mRadio2.toggle(); |
| | | |
| | | // the surfaces themselves are easier targets than the radio buttons |
| | | mSurfaceView1.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | mRadio1.toggle(); |
| | | } |
| | | }); |
| | | mGLView1.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | mRadio2.toggle(); |
| | | } |
| | | }); |
| | | |
| | | // initialize button click handlers |
| | | |
| | | // native MediaPlayer start/pause |
| | | ((Button) findViewById(R.id.start_native)).setOnClickListener(new View.OnClickListener() { |
| | | |
| | | @Override |
| | | public void onClick(View view) { |
| | | if (!mCreated) { |
| | | if (mNativeCodecPlayerVideoSink == null) { |
| | | if (mSelectedVideoSink == null) { |
| | | return; |
| | | } |
| | | //mSelectedVideoSink.useAsSinkForNative(); |
| | | mNativeCodecPlayerVideoSink = mSelectedVideoSink; |
| | | } |
| | | if (mSourceString != null) { |
| | | |
| | | RtspFaceNative.setSurface(1, mSurfaceHolder1.getSurface()); |
| | | mGLView1VideoSink.useAsSinkForNative(); |
| | | |
| | | //mCreated = createStreamingMediaPlayer(getResources().getAssets(), mSourceString); |
| | | //#todo ok |
| | | mCreated = RtspFaceNative.createPlayer(1, "rtsp://admin:admin12345@192.168.1.70:554/h264/ch1/sub/av_stream"); |
| | | //mCreated = RtspFaceNative.createPlayer(2, "rtsp://admin:admin12345@192.168.1.70:554/h264/ch1/sub/av_stream"); |
| | | //mCreated = createPlayer(1, "rtsp://192.168.1.56:8554"); |
| | | |
| | | RtspFaceNative.setFaceCallback(1, "cn/com/basic/face/util/RtspFaceNative", "faceCallBack"); |
| | | //RtspFaceNative.setFaceCallback(2, "cn/com/basic/face/util/RtspFaceNative", "faceCallBack"); |
| | | |
| | | //byte[] arr = new byte[5]; |
| | | //arr[0] = 3; arr[1] = 4; arr[2] = 5; |
| | | //RtspFaceNative.getFaceList(1, arr); |
| | | |
| | | } |
| | | } |
| | | if (mCreated) { |
| | | mIsPlaying = !mIsPlaying; |
| | | //setPlayingStreamingMediaPlayer(mIsPlaying); |
| | | } |
| | | } |
| | | |
| | | }); |
| | | |
| | | |
| | | // native MediaPlayer rewind |
| | | ((Button) findViewById(R.id.rewind_native)).setOnClickListener(new View.OnClickListener() { |
| | | |
| | | @Override |
| | | public void onClick(View view) { |
| | | if (mNativeCodecPlayerVideoSink != null) { |
| | | //rewindStreamingMediaPlayer(); |
| | | } |
| | | } |
| | | |
| | | }); |
| | | |
| | | ((Button) findViewById(R.id.addface_native)).setOnClickListener(new View.OnClickListener() { |
| | | |
| | | @Override |
| | | public void onClick(View view) { |
| | | Log.i("@@@", "addface_native onClick"); |
| | | |
| | | } |
| | | |
| | | }); |
| | | |
| | | ((ImageView) findViewById(R.id.addface_image)).setOnClickListener(new View.OnClickListener() { |
| | | |
| | | @Override |
| | | public void onClick(View view) { |
| | | Log.i("@@@", "addface_image onClick"); |
| | | //ImageView image = (ImageView)ThisActivity.findViewById(R.id.addface_image); |
| | | //image.setImageBitmap(faceBitmap); |
| | | } |
| | | |
| | | }); |
| | | |
| | | ((Button) findViewById(R.id.addface_native)).setOnClickListener(new View.OnClickListener() { |
| | | |
| | | @Override |
| | | public void onClick(View view) { |
| | | Log.i("@@@", "addface_image onClick"); |
| | | RtspFaceNative.dbgFaceAdd(ThisActivity.faceImg); |
| | | } |
| | | |
| | | }); |
| | | |
| | | } |
| | | |
| | | static NativeCodec ThisActivity; |
| | | |
| | | public static void setFaceDrawable(NativeImg img) |
| | | { |
| | | //ImageView image = (ImageView)ThisActivity.findViewById(R.id.addface_image); |
| | | //return image; |
| | | |
| | | ThisActivity.faceImg = img; |
| | | |
| | | //ImageView image = (ImageView)ThisActivity.findViewById(R.id.addface_image); |
| | | //image.callOnClick(); |
| | | |
| | | new Thread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | ThisActivity.runOnUiThread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | Bitmap bitmap = Bitmap.createBitmap(faceImg.width, faceImg.height, Bitmap.Config.ARGB_8888); |
| | | ByteBuffer byteBuffer = ByteBuffer.wrap(faceImg.image, 0, faceImg.size); |
| | | bitmap.copyPixelsFromBuffer(byteBuffer); |
| | | |
| | | ImageView image = (ImageView)ThisActivity.findViewById(R.id.addface_image); |
| | | image.setImageBitmap(bitmap); |
| | | |
| | | TextView textView1 = (TextView)ThisActivity.findViewById(R.id.textView1); |
| | | textView1.setText(RtspFaceNative.dbgGetLog()); |
| | | } |
| | | }); |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | void switchSurface() { |
| | | |
| | | //mGLView1VideoSink.useAsSinkForNative(); |
| | | //mSurfaceHolder1VideoSink.useAsSinkForNative(); |
| | | |
| | | if (mCreated && mNativeCodecPlayerVideoSink != mSelectedVideoSink) { |
| | | // shutdown and recreate on other surface |
| | | Log.i("@@@", "shutting down player"); |
| | | //shutdown(1); |
| | | //shutdown(2); |
| | | mCreated = false; |
| | | //mSelectedVideoSink.useAsSinkForNative(); |
| | | |
| | | |
| | | |
| | | mNativeCodecPlayerVideoSink = mSelectedVideoSink; |
| | | if (mSourceString != null) { |
| | | Log.i("@@@", "recreating player"); |
| | | //mCreated = createStreamingMediaPlayer(getResources().getAssets(),mSourceString); |
| | | //mCreated = createPlayer(1, "rtsp://admin:admin12345@192.168.1.70:554/h264/ch1/main/av_stream"); |
| | | //mCreated = createPlayer(2, "rtsp://admin:admin12345@192.168.1.70:554/h264/ch1/main/av_stream"); |
| | | //mCreated = createPlayer(1, "rtsp://192.168.1.56:8554"); |
| | | mIsPlaying = false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** Called when the activity is about to be paused. */ |
| | | @Override |
| | | protected void onPause() |
| | | { |
| | | mIsPlaying = false; |
| | | //setPlayingStreamingMediaPlayer(false); |
| | | mGLView1.onPause(); |
| | | super.onPause(); |
| | | } |
| | | |
| | | @Override |
| | | protected void onResume() { |
| | | super.onResume(); |
| | | if (mRadio2.isChecked()) { |
| | | mGLView1.onResume(); |
| | | } |
| | | } |
| | | |
| | | /** Called when the activity is about to be destroyed. */ |
| | | @Override |
| | | protected void onDestroy() |
| | | { |
| | | RtspFaceNative.shutdown(1); |
| | | RtspFaceNative.shutdown(2); |
| | | mCreated = false; |
| | | super.onDestroy(); |
| | | } |
| | | |
| | | private MyGLSurfaceView mGLView1; |
| | | |
| | | private RadioButton mRadio1; |
| | | |
| | | private RadioButton mRadio2; |
| | | |
| | | /** Native methods, implemented in jni folder */ |
| | | //public static native void createEngine(); |
| | | //public static native boolean createStreamingMediaPlayer(AssetManager assetMgr, 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(); |
| | | |
| | | //public static native void init(); |
| | | //public static native void setSurface(int cameraIdx, Surface surface); |
| | | //public static native boolean createPlayer(int cameraIdx, String uri); |
| | | //public static native void shutdown(int cameraIdx); |
| | | //// typedef void (* Java_com_example_nativecodec_NativeCodec_FaceCallback_func)(int cameraIdx, int count); |
| | | //public static native boolean setFaceCallback(int cameraIdx, String func); |
| | | //public static native void lockFace(int cameraIdx); |
| | | //public static native void releaseFace(int cameraIdx); |
| | | //public static native boolean getFaceList(int cameraIdx, byte[] faceListPb); |
| | | //public static native boolean getFaceImages(int cameraIdx, byte[] faceImagesIdx, byte[] faceImages); |
| | | |
| | | /** Load jni .so on initialization */ |
| | | static { |
| | | System.loadLibrary("rtspface"); |
| | | System.loadLibrary("opencv_java3"); |
| | | } |
| | | |
| | | // 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 useAsSinkForNative(); |
| | | |
| | | } |
| | | |
| | | static class SurfaceHolderVideoSink extends VideoSink { |
| | | |
| | | private final SurfaceHolder mSurfaceHolder; |
| | | |
| | | SurfaceHolderVideoSink(SurfaceHolder surfaceHolder) { |
| | | mSurfaceHolder = surfaceHolder; |
| | | } |
| | | |
| | | @Override |
| | | void setFixedSize(int width, int height) { |
| | | mSurfaceHolder.setFixedSize(width, height); |
| | | } |
| | | |
| | | @Override |
| | | void useAsSinkForNative() { |
| | | Surface s = mSurfaceHolder.getSurface(); |
| | | Log.i("@@@", "setting surface " + s); |
| | | //mSurfaceHolder1.setFormat(PixelFormat.RGBA_8888); |
| | | RtspFaceNative.setSurface(1, s); |
| | | } |
| | | |
| | | } |
| | | |
| | | static class GLViewVideoSink extends VideoSink { |
| | | |
| | | private final MyGLSurfaceView mMyGLSurfaceView; |
| | | |
| | | GLViewVideoSink(MyGLSurfaceView myGLSurfaceView) { |
| | | mMyGLSurfaceView = myGLSurfaceView; |
| | | } |
| | | |
| | | @Override |
| | | void setFixedSize(int width, int height) { |
| | | } |
| | | |
| | | @Override |
| | | void useAsSinkForNative() { |
| | | SurfaceTexture st = mMyGLSurfaceView.getSurfaceTexture(); |
| | | Surface s = new Surface(st); |
| | | //setEGLConfigChooser(8, 8, 8, 8, 0, 0); |
| | | RtspFaceNative.setSurface(2, s); |
| | | s.release(); |
| | | } |
| | | |
| | | } |
| | | |
| | | } |