pull code of origin
This commit is contained in:
160
app/src/main/java/com/mogo/cloud/BaseLiveActivity.java
Normal file
160
app/src/main/java/com/mogo/cloud/BaseLiveActivity.java
Normal file
@@ -0,0 +1,160 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
|
||||
import com.mogo.cloud.util.YuvToolUtils;
|
||||
import com.zhidao.manager.camera.FrameBufferCallBack;
|
||||
import com.zhidao.manager.camera.ZDCameraManager;
|
||||
import com.zhidao.manager.camera.ZDCameraParams;
|
||||
|
||||
|
||||
public abstract class BaseLiveActivity extends AppCompatActivity {
|
||||
private String TAG = "TestCarRecorderLiveActivity";
|
||||
|
||||
private String yuvSavePath = "/sdcard/Movies/TestYuvNV12.yuv";
|
||||
|
||||
public static int cameraId = 0; // 要打开的摄像头的ID
|
||||
|
||||
public int videoWidth = 1280;
|
||||
public int videoHeight = 720;
|
||||
|
||||
// 开始直播
|
||||
protected ToggleButton btnLive;
|
||||
// 保存文件到本地
|
||||
protected ToggleButton btnSaveFile;
|
||||
// 设置摄像头与状态
|
||||
protected ToggleButton btnChangeCameraState;
|
||||
// 当前直播的状态
|
||||
protected ToggleButton tbLiveStatus;
|
||||
// 相机数据预览
|
||||
protected SurfaceView surfaceView;
|
||||
|
||||
private ZDCameraManager zdCameraManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_live_push);
|
||||
|
||||
surfaceView = findViewById(R.id.surfaceView);
|
||||
btnLive = findViewById(R.id.btnLive);
|
||||
btnLive.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
Toast.makeText(getApplicationContext(), buttonView.getText(), Toast.LENGTH_SHORT).show();
|
||||
toggleLive(isChecked);
|
||||
});
|
||||
|
||||
btnSaveFile = findViewById(R.id.btnSaveFile);
|
||||
btnSaveFile.setOnCheckedChangeListener((btnSaveFile, isChecked) -> {
|
||||
Toast.makeText(getApplicationContext(), btnSaveFile.getText(), Toast.LENGTH_SHORT).show();
|
||||
YuvToolUtils.isSaveFile = isChecked;
|
||||
if (isChecked) {
|
||||
YuvToolUtils.connectYUVFile(yuvSavePath);
|
||||
}
|
||||
});
|
||||
|
||||
btnChangeCameraState = findViewById(R.id.btnChangeCameraState);
|
||||
btnChangeCameraState.setOnCheckedChangeListener((btnSaveFile, isChecked) -> {
|
||||
Toast.makeText(getApplicationContext(), btnSaveFile.getText(), Toast.LENGTH_SHORT).show();
|
||||
toggleCameraState(isChecked);
|
||||
});
|
||||
|
||||
tbLiveStatus = findViewById(R.id.tbLiveStatus);
|
||||
|
||||
initCamer();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化相机
|
||||
*/
|
||||
private void initCamer() {
|
||||
zdCameraManager = ZDCameraManager.getInstance();
|
||||
zdCameraManager.init(getApplicationContext());
|
||||
ZDCameraParams camParam = zdCameraManager.getCameraParam();
|
||||
camParam.setStoragePath("/sdcard/DCIM/");
|
||||
camParam.setVideoWidth(0, videoWidth);
|
||||
camParam.setVideoHeight(0, videoHeight);
|
||||
zdCameraManager.setCameraParam(camParam);
|
||||
|
||||
// 这里是获取 YUV-NV12 格式的视频流
|
||||
ZDCameraManager.getInstance().setFrontBufferCallBack(new FrameBufferCallBack() {
|
||||
@Override
|
||||
public void onFrame(byte[] bytes, int i) {
|
||||
//Log.d(TAG, "duanmu OnFrame ,bytes:" + bytes + " i:" + i);
|
||||
// 回碉给业务侧进行处理
|
||||
// 这里对所有传入的YUV数据进行对应类型的转码,为I420
|
||||
byte[] yuv420p = YuvToolUtils.convertData(bytes, videoWidth, videoHeight, 4);
|
||||
|
||||
onVideoFrame(yuv420p, i);
|
||||
|
||||
// 保存yuv文件
|
||||
if (YuvToolUtils.isSaveFile) {
|
||||
try {
|
||||
// 往队列里面添加数据
|
||||
YuvToolUtils.queueYUV.put(yuv420p);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 这里是纯预览
|
||||
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "addSurfaceCallBack id");
|
||||
zdCameraManager.startPreview(holder, cameraId, videoWidth, videoHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
zdCameraManager.stopPreview(cameraId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (zdCameraManager != null) {
|
||||
zdCameraManager.stopPreview(cameraId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* F 车机从相机获取的视频数据回调
|
||||
* <p>
|
||||
* TODO 一般在这里调用直播SDK的接口进行直播操作,一定要先卸载 ADAS com.zhidao.autopilot
|
||||
*
|
||||
* @param yuv420p YUV数据 I420
|
||||
* @param bytesLength 数据长度
|
||||
*/
|
||||
public abstract void onVideoFrame(byte[] yuv420p, int bytesLength);
|
||||
|
||||
|
||||
/**
|
||||
* 开关直播状态
|
||||
*
|
||||
* @param isLive true-开启直播,false-关闭直播
|
||||
*/
|
||||
public abstract void toggleLive(boolean isLive);
|
||||
|
||||
/**
|
||||
* 摄像头状态
|
||||
*
|
||||
* @param isLive true-可以直播,false-不可以直播
|
||||
*/
|
||||
public abstract void toggleCameraState(boolean isLive);
|
||||
|
||||
}
|
||||
26
app/src/main/java/com/mogo/cloud/ConfigInfoActivity.java
Normal file
26
app/src/main/java/com/mogo/cloud/ConfigInfoActivity.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.utils.GsonUtil;
|
||||
|
||||
/**
|
||||
* 查看配置信息
|
||||
*/
|
||||
public class ConfigInfoActivity extends AppCompatActivity {
|
||||
|
||||
private TextView tvConfigInfo;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.actitity_config_info);
|
||||
tvConfigInfo = findViewById(R.id.tvConfigInfo);
|
||||
tvConfigInfo.setText(GsonUtil.jsonFromObject(MoGoAiCloudClientConfig.getInstance()));
|
||||
}
|
||||
}
|
||||
63
app/src/main/java/com/mogo/cloud/LivePlayActivity.java
Normal file
63
app/src/main/java/com/mogo/cloud/LivePlayActivity.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
|
||||
import com.mogo.cloud.trafficlive.api.ITrafficLiveCallBack;
|
||||
import com.mogo.cloud.trafficlive.api.MoGoAiCloudTrafficLive;
|
||||
|
||||
|
||||
public class LivePlayActivity extends AppCompatActivity implements ITrafficLiveCallBack {
|
||||
private String TAG = "LiveActivity";
|
||||
|
||||
private SurfaceView surfaceView;
|
||||
private ToggleButton liveToggleBtn;
|
||||
private EditText etLookRoomId;
|
||||
private String liveSn;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_live_play);
|
||||
surfaceView = findViewById(R.id.surfaceView);
|
||||
etLookRoomId = findViewById(R.id.etLookRoomId);
|
||||
liveToggleBtn = findViewById(R.id.liveToggleBtn);
|
||||
liveToggleBtn.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
Toast.makeText(getApplicationContext(), buttonView.getText(), Toast.LENGTH_SHORT).show();
|
||||
if (isChecked) {
|
||||
liveSn = etLookRoomId.getText().toString().trim();
|
||||
MoGoAiCloudTrafficLive.viewVehicleHeadLive(this.getApplication(), liveSn, surfaceView, this);
|
||||
} else {
|
||||
MoGoAiCloudTrafficLive.stopLive(liveSn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
MoGoAiCloudTrafficLive.stopLive(liveSn);
|
||||
MoGoAiCloudTrafficLive.destroyLive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLive() {
|
||||
Log.d(TAG, "开始直播 onLive");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisConnect() {
|
||||
Log.d(TAG, "失去连接 onDisConnect");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String errorMsg) {
|
||||
Log.d(TAG, "发生错误 onError msg: " + errorMsg);
|
||||
}
|
||||
}
|
||||
80
app/src/main/java/com/mogo/cloud/LivePushActivity.java
Normal file
80
app/src/main/java/com/mogo/cloud/LivePushActivity.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.mogo.cloud.live.listener.ILiveStatusListener;
|
||||
import com.mogo.cloud.live.manager.ILiveStreamManager;
|
||||
import com.mogo.cloud.live.manager.LiveStreamManagerImpl;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
|
||||
|
||||
/**
|
||||
* 推流页面
|
||||
*/
|
||||
public class LivePushActivity extends BaseLiveActivity {
|
||||
public static final String TAG = "PushActivity";
|
||||
|
||||
ILiveStreamManager liveStreamManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// 初始化直播流管理
|
||||
liveStreamManager = LiveStreamManagerImpl.getInstance(this,
|
||||
MoGoAiCloudClientConfig.getInstance().getThirdPartyDeviceId());
|
||||
liveStreamManager.setLiveStatusChangeCallback(new ILiveStatusListener() {
|
||||
@Override
|
||||
public void onChange(String camId, int status) {
|
||||
tbLiveStatus.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (status == 0) {
|
||||
tbLiveStatus.setTextColor(getResources().getColor(R.color.colorStartLive));
|
||||
tbLiveStatus.setChecked(true);
|
||||
} else {
|
||||
tbLiveStatus.setTextColor(getResources().getColor(R.color.colorStopLive));
|
||||
tbLiveStatus.setChecked(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoFrame(byte[] bytes, int bytesLength) {
|
||||
//Log.i(TAG, "onVideoFrame byte length: " + bytesLength);
|
||||
if (liveStreamManager != null) {
|
||||
// 将摄像头采集的YUV数据推送到ZEGO
|
||||
liveStreamManager.notifyYUVData(bytes, 1280, 720, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleLive(boolean isLive) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleCameraState(boolean isLive) {
|
||||
Log.i(TAG, "toggleCameraState isLive: " + isLive);
|
||||
if (isLive) {
|
||||
// 上报摄像头状态,1-可用,2-不可用
|
||||
liveStreamManager.uploadCamStatus(1, 1);
|
||||
} else {
|
||||
liveStreamManager.uploadCamStatus(2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (liveStreamManager != null) {
|
||||
// 停止
|
||||
liveStreamManager.stopLiveStream();
|
||||
// 释放资源
|
||||
liveStreamManager.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@ package com.mogo.cloud;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.mogo.cloud.network.NetworkActivity;
|
||||
import com.mogo.cloud.passport.IMoGoTokenCallback;
|
||||
@@ -15,9 +15,12 @@ import com.mogo.cloud.passport.MoGoAiCloudClient;
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private Button btnJumpPassPort;
|
||||
private Button btnJumpConfigInfo;
|
||||
private Button btnJumpNetWorkPort;
|
||||
private Button btnJumpRealTime;
|
||||
private Button btnJumpRoadCondition;
|
||||
private Button btnJumpLivePush;
|
||||
private Button btnJumpLivePlay;
|
||||
|
||||
private TextView tvSn;
|
||||
private TextView tvToken;
|
||||
@@ -57,6 +60,24 @@ public class MainActivity extends AppCompatActivity {
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnJumpConfigInfo = findViewById(R.id.btnJumpConfigInfo);
|
||||
btnJumpConfigInfo.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(MainActivity.this, ConfigInfoActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnJumpLivePush = findViewById(R.id.btnJumpLivePush);
|
||||
btnJumpLivePush.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(MainActivity.this, LivePushActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnJumpLivePlay = findViewById(R.id.btnJumpLivePlay);
|
||||
btnJumpLivePlay.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(MainActivity.this, LivePlayActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
MoGoAiCloudClient.getInstance().addTokenCallbacks(new IMoGoTokenCallback() {
|
||||
@Override
|
||||
public void onTokenGot(String token, String sn) {
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import androidx.multidex.MultiDexApplication;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.multidex.MultiDexApplication;
|
||||
|
||||
import com.mogo.cloud.httpdns.MogoHttpDnsConfig;
|
||||
import com.mogo.cloud.httpdns.bean.HttpDnsSimpleLocation;
|
||||
import com.mogo.cloud.httpdns.listener.IHttpDnsCurrentLocation;
|
||||
import com.mogo.cloud.passport.IMoGoTokenCallback;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClient;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.cloud.util.Devices;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -35,17 +36,19 @@ public class MoGoApplication extends MultiDexApplication {
|
||||
* BYD:bydauto
|
||||
*/
|
||||
// 配置云服务API
|
||||
MoGoAiCloudClientConfig clientConfig = new MoGoAiCloudClientConfig();
|
||||
MoGoAiCloudClientConfig clientConfig = MoGoAiCloudClientConfig.getInstance();
|
||||
// 设置网络环境:HTTP_DNS_ENV_QA、HTTP_DNS_ENV_RELEASE、HTTP_DNS_ENV_DEV
|
||||
clientConfig.setNetMode(MogoHttpDnsConfig.HTTP_DNS_ENV_QA);
|
||||
// 设置是否是第三APP登录
|
||||
clientConfig.setThirdLogin(true);
|
||||
clientConfig.setThirdLogin(false);
|
||||
// 设置是否输出日志
|
||||
clientConfig.setShowDebugLog(true);
|
||||
// 设置从蘑菇AI开放平台获取的APPKey
|
||||
clientConfig.setThirdPartyAppKey("bydauto");
|
||||
clientConfig.setThirdPartyAppKey("wbvpzgar");
|
||||
// 设置AI云平台分配给三方应用的签名密钥,需要从AI云平台申请
|
||||
clientConfig.setThirdPartySignSecret("y5VajBH+sTHonJP2a5Uh6uDZcK0fxNB5ORHmbg9B3V0=");
|
||||
// 设置车机设备的唯一标识(这些表识必须是通过后台录入的设备)
|
||||
clientConfig.setThirdPartyDeviceId("bydauto");
|
||||
clientConfig.setThirdPartyDeviceId(Devices.getSn());
|
||||
// 设置循环检测间隔时间
|
||||
clientConfig.setLoopCheckDelay(15 * 1000);
|
||||
|
||||
@@ -59,8 +62,7 @@ public class MoGoApplication extends MultiDexApplication {
|
||||
});
|
||||
|
||||
// 初始化SDK,可以设置状态回调来监听
|
||||
MoGoAiCloudClient.getInstance().init(
|
||||
this, clientConfig);
|
||||
MoGoAiCloudClient.getInstance().init(this, clientConfig);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClient;
|
||||
<<<<<<< HEAD
|
||||
import com.mogo.realtime.Interface.IRealTimeProvider;
|
||||
import com.mogo.realtime.Interface.MoGoAiCloudRealTime;
|
||||
=======
|
||||
import com.mogo.realtime.api.MoGoAiCloudRealTime;
|
||||
>>>>>>> 17b3ed341e822ad073ace72a78b08f26214c0059
|
||||
import com.mogo.realtime.entity.MogoSnapshotSetData;
|
||||
import com.mogo.realtime.socket.IMogoCloudOnMsgListener;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mogo.cloud.network.BaseData;
|
||||
import com.mogo.cloud.network.NetworkActivity;
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClient;
|
||||
import com.mogo.cloud.tanlu.MogoRoadSearchManager;
|
||||
import com.mogo.cloud.tanlu.MogoUploadManager;
|
||||
import com.mogo.cloud.tanlu.api.MogoRoadSearchManager;
|
||||
import com.mogo.cloud.tanlu.api.MogoUploadManager;
|
||||
import com.mogo.cloud.tanlu.api.IRoadInfoSearchCallback;
|
||||
import com.mogo.cloud.tanlu.api.ITanluUploadCallback;
|
||||
import com.mogo.cloud.tanlu.bean.RoadInfoRequest;
|
||||
@@ -21,9 +17,6 @@ import com.mogo.cloud.tanlu.bean.RoadInfos;
|
||||
import com.mogo.cloud.tanlu.bean.UploadInfo;
|
||||
import com.mogo.cloud.tanlu.bean.UploadResult;
|
||||
import com.mogo.cloud.tanlu.bean.location.Location;
|
||||
import com.mogo.realtime.Interface.MoGoAiCloudRealTime;
|
||||
import com.mogo.realtime.entity.MogoSnapshotSetData;
|
||||
import com.mogo.realtime.socket.IMogoCloudOnMsgListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.mogo.cloud;
|
||||
|
||||
import com.elegant.spi.annotations.Service;
|
||||
import com.mogo.realtime.Interface.IRealTimeProvider;
|
||||
import com.mogo.realtime.api.IRealTimeProvider;
|
||||
import com.mogo.realtime.entity.ADASRecognizedResult;
|
||||
import com.mogo.realtime.entity.CloudLocationInfo;
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.mogo.cloud.network;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mogo.cloud.R;
|
||||
|
||||
|
||||
33
app/src/main/java/com/mogo/cloud/util/Devices.java
Normal file
33
app/src/main/java/com/mogo/cloud/util/Devices.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.mogo.cloud.util;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Devices {
|
||||
|
||||
private static final String PROPERTIES = "android.os.SystemProperties";
|
||||
private static final String GSM_SERIAL = "gsm.serial";
|
||||
private static final String GET = "get";
|
||||
|
||||
public static String getSn(){
|
||||
return getSystemProperties(GSM_SERIAL);
|
||||
}
|
||||
|
||||
public static String getSystemProperties(String name ) {
|
||||
String value = "";
|
||||
try {
|
||||
Class< ? > c = Class.forName( PROPERTIES );
|
||||
Method get = c.getMethod( GET, String.class );
|
||||
value = (String) get.invoke( c, name );
|
||||
} catch ( ClassNotFoundException var3 ) {
|
||||
var3.printStackTrace();
|
||||
} catch ( NoSuchMethodException var4 ) {
|
||||
var4.printStackTrace();
|
||||
} catch ( InvocationTargetException var5 ) {
|
||||
var5.printStackTrace();
|
||||
} catch ( IllegalAccessException var6 ) {
|
||||
var6.printStackTrace();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
197
app/src/main/java/com/mogo/cloud/util/YuvToolUtils.java
Normal file
197
app/src/main/java/com/mogo/cloud/util/YuvToolUtils.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package com.mogo.cloud.util;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.zhidao.libyuv.Key;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* YUV与RGB转换工具类
|
||||
*/
|
||||
public class YuvToolUtils {
|
||||
private static final String TAG = "YuvToolUtils";
|
||||
|
||||
private static final int DST_WIDTH = 1280;
|
||||
private static final int DST_HEIGHT = 720;
|
||||
|
||||
private static byte[] dst = null;
|
||||
private static byte[] tmp = null;
|
||||
|
||||
/**
|
||||
* @param data origin yuv data
|
||||
* @param width data width
|
||||
* @param height data height
|
||||
* @param type 1:YV12 2:NV21 3:I420 4 nv12
|
||||
*/
|
||||
public static byte[] convertData(byte[] data, int width, int height, int type) {
|
||||
if (dst == null) {
|
||||
dst = new byte[DST_WIDTH * DST_HEIGHT * 3 / 2];
|
||||
}
|
||||
|
||||
if (tmp == null) {
|
||||
tmp = new byte[848 * 480 * 3 / 2];
|
||||
}
|
||||
|
||||
if (type == 4) {
|
||||
if (DST_WIDTH == width && DST_HEIGHT == height) {
|
||||
com.zhidao.libyuv.YuvUtils.NV12ToI420(data, dst, width, height);
|
||||
return dst;
|
||||
} else {
|
||||
com.zhidao.libyuv.YuvUtils.NV12ToI420(data, tmp, width, height);
|
||||
com.zhidao.libyuv.YuvUtils.I420Scale(tmp, width, height, dst, DST_WIDTH, DST_HEIGHT, Key.SCALE_MODE_NONE, false);
|
||||
return dst;
|
||||
}
|
||||
} else if (type == 3) {
|
||||
if (DST_WIDTH == width && DST_HEIGHT == height) {
|
||||
return data;
|
||||
} else {
|
||||
com.zhidao.libyuv.YuvUtils.I420Scale(data, width, height, dst, DST_WIDTH, DST_HEIGHT, Key.SCALE_MODE_NONE, false);
|
||||
return dst;
|
||||
}
|
||||
} else if (type == 2) {
|
||||
if (DST_WIDTH == width && DST_HEIGHT == height) {
|
||||
com.zhidao.libyuv.YuvUtils.NV21ToI420(data, dst, width, height, false);
|
||||
return dst;
|
||||
} else {
|
||||
com.zhidao.libyuv.YuvUtils.NV21ToI420(data, tmp, width, height, false);
|
||||
com.zhidao.libyuv.YuvUtils.I420Scale(tmp, width, height, dst, DST_WIDTH, DST_HEIGHT, Key.SCALE_MODE_NONE, false);
|
||||
return dst;
|
||||
}
|
||||
} else if (type == 1) {
|
||||
if (DST_WIDTH == width && DST_HEIGHT == height) {
|
||||
swapYV12toI420(data, dst, width, height);
|
||||
return dst;
|
||||
} else {
|
||||
swapYV12toI420(data, tmp, width, height);
|
||||
com.zhidao.libyuv.YuvUtils.I420Scale(tmp, width, height, dst, DST_WIDTH, DST_HEIGHT, Key.SCALE_MODE_NONE, false);
|
||||
return dst;
|
||||
}
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
public static synchronized void release() {
|
||||
dst = null;
|
||||
tmp = null;
|
||||
Log.d(TAG, "release 释放临时帧");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 YV12 格式转换为 I420
|
||||
*
|
||||
* @param yv12bytes 原始格式数据
|
||||
* @param i420bytes 转出格式数据
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
*/
|
||||
public static void swapYV12toI420(byte[] yv12bytes, byte[] i420bytes, int width, int height) {
|
||||
System.arraycopy(yv12bytes, 0, i420bytes, 0, width * height);
|
||||
int srcPos = width * height + width * height / 4;
|
||||
// 这里利用的是 YV12 和 I420 存储特性 ,将 U 和 V 数据进行调换
|
||||
System.arraycopy(yv12bytes, srcPos, i420bytes, width * height, width * height / 4);
|
||||
System.arraycopy(yv12bytes, width * height, i420bytes, srcPos, width * height / 4);
|
||||
}
|
||||
|
||||
|
||||
public static ArrayList<byte[]> splitYUVI420(byte[] i420bytes, int width, int height) {
|
||||
|
||||
ArrayList<byte[]> yuvList = new ArrayList<>();
|
||||
|
||||
byte[] yData = new byte[width * height];
|
||||
byte[] uData = new byte[width * height / 4];
|
||||
byte[] vData = new byte[width * height / 4];
|
||||
|
||||
System.arraycopy(i420bytes, 0, yData, 0, width * height);
|
||||
System.arraycopy(i420bytes, width * height, uData, 0, width * height / 4);
|
||||
System.arraycopy(i420bytes, width * height + width * height / 4, vData, 0, width * height / 4);
|
||||
|
||||
yuvList.add(yData);
|
||||
yuvList.add(uData);
|
||||
yuvList.add(vData);
|
||||
|
||||
return yuvList;
|
||||
}
|
||||
|
||||
|
||||
public static LinkedBlockingQueue<byte[]> queueYUV = new LinkedBlockingQueue<>();
|
||||
public static boolean isSaveFile = true;
|
||||
|
||||
public static void connectYUVFile(String filePath) {
|
||||
Thread writeThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
boolean isOk = file.createNewFile();
|
||||
if (isOk) {
|
||||
Log.d(TAG, filePath + " 文件创建成功");
|
||||
} else {
|
||||
Log.w(TAG, filePath + " 文件已经存在");
|
||||
}
|
||||
}
|
||||
FileOutputStream out = new FileOutputStream(filePath);
|
||||
// 子线程中死循环
|
||||
while (isSaveFile) {
|
||||
// 拿数据
|
||||
byte[] data = queueYUV.take();
|
||||
// 往本地文件写入
|
||||
out.write(data);
|
||||
// 刷新
|
||||
out.flush();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
writeThread.start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 写入文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param data YUV 数据
|
||||
* @return 是否写入成功
|
||||
*/
|
||||
public static boolean writeFile(String path, byte[] data) {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
File file = new File(path);
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists())
|
||||
parent.mkdirs();
|
||||
if (!file.exists()) {
|
||||
boolean isOk = file.createNewFile();
|
||||
if (isOk) {
|
||||
out = new FileOutputStream(path);
|
||||
out.write(data);
|
||||
FileDescriptor fd = out.getFD();
|
||||
fd.sync();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
Log.d(TAG, path + " 文件已经存在");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (out != null)
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user