/* * * MultiThread.java * * Created by Wuwang on 2016/11/16 * Copyright © 2016年 深圳哎吖科技. All rights reserved. */ package com.aiyaapp.camera.sdk; import java.io.File; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import android.content.Context; import android.os.Handler; import android.os.HandlerThread; import android.telephony.TelephonyManager; import com.aiyaapp.camera.sdk.base.Assets; import com.aiyaapp.camera.sdk.base.ISdkManager; import com.aiyaapp.camera.sdk.base.Log; import com.aiyaapp.camera.sdk.base.Parameter; import com.aiyaapp.camera.sdk.base.ProcessCallback; import com.aiyaapp.camera.sdk.base.Rotation; import com.aiyaapp.camera.sdk.base.Event; import com.aiyaapp.camera.sdk.base.ActionObservable; import com.aiyaapp.camera.sdk.base.ActionObserver; import com.aiyaapp.camera.sdk.base.TrackCallback; /** * Sdk的核心接口,将工作线程、GL线程、人脸追踪线程分开, * 提高SDK对视频流的处理速度。 */ public class AiyaEffects implements ISdkManager { // #define TRACK_STAT_OFF 0 // #define TRACK_STAT_OK 1 // #define TRACK_STAT_RECOVERING 2 // #define TRACK_STAT_INIT 3 private static AiyaEffects instance; private ActionObservable mObservable; private AiyaCameraJni mAiyaCameraJni; private HandlerThread mWorkThread; private Handler mWorkHandler; private Parameter input,output; private String nextEffect,currentEffect; private ProcessCallback mProcessCallback; private TrackCallback mTrackCallback; private ExecutorService mTrackExecutor; private int mInWidth=720; private int mInHeight=1280; private int mOutWidth=720; private int mOutHeight=1280; private int mTrackWidth=180; private int mTrackHeight=320; private boolean isSetParam=false; private int mMode=0; private boolean isResourceReady=false; private Semaphore mSemaphore; private Object assetManager; private Event mProcessEvent=new Event(Event.PROCESS_END,Event.PROCESS_PLAY,"",null); private AiyaEffects(){ mObservable=new ActionObservable(); } public static AiyaEffects getInstance(){ if(instance==null){ synchronized (AiyaEffects.class){ if(instance==null){ instance=new AiyaEffects(); } } } return instance; } @Override public void registerObserver(ActionObserver observer){ mObservable.registerObserver(observer); } @Override public void unRegisterObserver(ActionObserver observer){ mObservable.unRegisterObserver(observer); } private void cInit(){ mSemaphore=new Semaphore(1,true); mAiyaCameraJni=new AiyaCameraJni(); mWorkThread=new HandlerThread("Sdk Work Thread"); mWorkThread.start(); mWorkHandler=new Handler(mWorkThread.getLooper()); mTrackExecutor= Executors.newFixedThreadPool(1); } private boolean prepareResource(Context context,String licensePath){ Log.d("prepare Resource"); Assets assets=new Assets(context,licensePath); return assets.doCopy(); } @Override public void init(final Context context,final String licensePath,final String appKey) { Log.e("sdk init"); assetManager=context.getAssets(); cInit(); mWorkHandler.post(new Runnable() { @Override public void run() { Log.e("start prepare resource"); boolean pb; final String path=licensePath.substring(0,licensePath.lastIndexOf (File.separator)+1); Log.e("path -- >"+path); if(new File(licensePath).exists()){ pb=true; }else{ pb=prepareResource(context,path); } Log.e("prepare resource success:"+pb); if(pb){ mObservable.notifyState(new Event(Event.RESOURCE_READY,Event.RESOURCE_READY,"资源准备完成",null)); isResourceReady=true; TelephonyManager tm = (TelephonyManager)context.getSystemService(Context .TELEPHONY_SERVICE); String DEVICE_ID = tm.getDeviceId(); if(DEVICE_ID==null)DEVICE_ID=android.os.Build.SERIAL; Log.e("sticker jni init"); int state=mAiyaCameraJni.init(context,path, licensePath,context.getPackageName(),DEVICE_ID,appKey); Log.e("state="+state); if(state==0){ mObservable.notifyState(new Event(Event.INIT_SUCCESS,Event.INIT_SUCCESS,"初始化成功",null)); }else{ mObservable.notifyState(new Event(Event.INIT_FAILED,state,"初始化失败",null)); } }else{ mObservable.notifyState(new Event(Event.RESOURCE_FAILED,Event.INIT_FAILED,"资源准备失败",null)); isResourceReady=false; } } }); } @Deprecated @Override public void setParameters(Parameter inputConfig, Parameter outputConfig) { refreshParams(); if(inputConfig!=null){ this.input=inputConfig; } if(outputConfig!=null){ this.output=outputConfig; } Log.e("CameraJni.setParameters"); mAiyaCameraJni.setParameters(input.width,input.height,input.format,input .rotation.asInt(),input.flip?1:0,output.width,output.height,output.format, output.rotation.asInt(),output.flip?1:0); set(SET_ASSETS_MANAGER,assetManager); currentEffect=null; setEffect(nextEffect); isSetParam=true; } @Override public void setEffect(String effectPath) { if(effectPath==null){ currentEffect=null; set(SET_EFFECT_ON,0); }else{ set(SET_EFFECT_ON,1); } this.nextEffect=effectPath; } private void refreshParams(){ if(input==null){ input=new Parameter(); } input.width=mInWidth; input.height=mInHeight; input.rotation= Rotation.NORMAL; input.format=Parameter.FORMAT_RGBA; if(output==null){ output=new Parameter(); } output.width=mOutWidth; output.height=mOutHeight; output.rotation=Rotation.NORMAL; output.format=Parameter.FORMAT_RGBA; } @Override public void set(String key, int value) { switch (key){ case SET_IN_WIDTH: mInWidth=value; isSetParam=false; break; case SET_IN_HEIGHT: mInHeight=value; isSetParam=false; break; case SET_OUT_WIDTH: mOutWidth=value; isSetParam=false; break; case SET_OUT_HEIGHT: mOutHeight=value; isSetParam=false; break; case SET_TRACK_WIDTH: mTrackWidth=value; break; case SET_TRACK_HEIGHT: mTrackHeight=value; break; case SET_MODE: this.mMode=value; break; case SET_ACTION: switch (value){ case ACTION_REFRESH_PARAMS_NOW: setParameters(input,output); break; } break; default: mAiyaCameraJni.set(key, value); break; } } @Override public void set(String key, Object obj) { if(key.equals(SET_ASSETS_MANAGER)){ mAiyaCameraJni.set(key,obj); } } @Override public void track(final byte[] trackData, final float[] info, final int trackIndex) { if(isResourceReady){ mTrackExecutor.execute(new Runnable() { @Override public void run() { long start=System.currentTimeMillis(); int trackCode=mAiyaCameraJni.track(trackData,mTrackWidth,mTrackHeight,info, trackIndex); Log.e("track------------------------>"+(System.currentTimeMillis()-start)); if(mTrackCallback!=null){ mTrackCallback.onTrack(trackCode,info); } mSemaphore.release(); } }); } } @Override public void process(int textureId, int trackIndex) { if(isResourceReady){ try { mSemaphore.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } if(!isSetParam){ setParameters(input,output); } if(nextEffect!=null&&!nextEffect.equals(currentEffect)){ mAiyaCameraJni.setEffect(nextEffect); currentEffect=nextEffect; } int ret= mAiyaCameraJni.processFrame(textureId,input.width,input.height,trackIndex); if(mProcessCallback!=null){ mProcessCallback.onFinished(); } if(mMode==MODE_GIFT&&ret==STATE_EFFECT_END){ setEffect(null); } if(ret==STATE_EFFECT_END){ mProcessEvent.strTag=currentEffect; mObservable.notifyState(mProcessEvent); } } } @Override public void setProcessCallback(ProcessCallback callback) { this.mProcessCallback=callback; } @Override public void setTrackCallback(TrackCallback callback) { this.mTrackCallback=callback; } @Override public void stopEffect() { setEffect(null); } @Override public int get(String key) { switch (key){ case SET_IN_WIDTH: return mInWidth; case SET_IN_HEIGHT: return mInHeight; case SET_OUT_WIDTH: return mOutWidth; case SET_OUT_HEIGHT: return mOutHeight; case SET_TRACK_WIDTH: return mTrackWidth; case SET_TRACK_HEIGHT: return mTrackHeight; case SET_MODE: return mMode; default: return -1; } } @Override public void release() { mObservable.unRegisterAll(); if(mAiyaCameraJni!=null){ mAiyaCameraJni.release(); } } }