|
|
|
@ -17,7 +17,13 @@ import android.graphics.Color;
|
|
|
|
|
import android.graphics.Paint;
|
|
|
|
|
import android.graphics.Path;
|
|
|
|
|
import android.graphics.RectF;
|
|
|
|
|
import android.media.MediaCodec;
|
|
|
|
|
import android.media.MediaCodecInfo;
|
|
|
|
|
import android.media.MediaCodecList;
|
|
|
|
|
import android.media.MediaFormat;
|
|
|
|
|
import android.media.MediaScannerConnection;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.os.Environment;
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.Message;
|
|
|
|
|
import android.provider.ContactsContract;
|
|
|
|
@ -25,6 +31,7 @@ import android.util.AttributeSet;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.MotionEvent;
|
|
|
|
|
import android.view.Surface;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
import android.view.animation.AlphaAnimation;
|
|
|
|
@ -38,13 +45,18 @@ import android.widget.Toast;
|
|
|
|
|
|
|
|
|
|
import org.json.JSONException;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedOutputStream;
|
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.net.DatagramPacket;
|
|
|
|
|
import java.net.DatagramSocket;
|
|
|
|
|
import java.net.InetAddress;
|
|
|
|
|
import java.net.*;
|
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
@ -78,6 +90,7 @@ public class VideoActivity extends AppCompatActivity {
|
|
|
|
|
private ImageButton Setting_btn;
|
|
|
|
|
private ImageButton TakeOff_btn;
|
|
|
|
|
private ImageButton Landing_btn;
|
|
|
|
|
private ImageButton Record_btn;
|
|
|
|
|
private ToggleButton Mode_btn;
|
|
|
|
|
private ImageButton selfHome_btn;
|
|
|
|
|
private String mangle;
|
|
|
|
@ -110,6 +123,7 @@ public class VideoActivity extends AppCompatActivity {
|
|
|
|
|
TurnRight_btn = findViewById(R.id.rotate_right_button);
|
|
|
|
|
TakeOff_btn = findViewById(R.id.takeoff_button);
|
|
|
|
|
Mode_btn = findViewById(R.id.toggleButton2);
|
|
|
|
|
Record_btn = findViewById(R.id.start_record_button);
|
|
|
|
|
Setting_btn = findViewById(R.id.setting_button);
|
|
|
|
|
Setting_btn.setOnClickListener(new View.OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
@ -272,7 +286,6 @@ public class VideoActivity extends AppCompatActivity {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Condition_Init() throws UnknownHostException {
|
|
|
|
|
sendCommand("AUTO");
|
|
|
|
|
ReceiveHandler receiveHandler = new ReceiveHandler();
|
|
|
|
|
UdpReceiveThread StreamThread = new UdpReceiveThread(Recieve_IP,RECEIVE_PORT,receiveHandler);
|
|
|
|
|
try {
|
|
|
|
@ -294,19 +307,22 @@ public class VideoActivity extends AppCompatActivity {
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 执行功能1
|
|
|
|
|
try {
|
|
|
|
|
changetoAuto();
|
|
|
|
|
} catch (UnknownHostException e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
// try {
|
|
|
|
|
// changetoAuto();
|
|
|
|
|
// } catch (UnknownHostException e) {
|
|
|
|
|
// throw new RuntimeException(e);
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
Record_btn.setOnClickListener(new View.OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(View view) {
|
|
|
|
|
saveVideo(bp);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void changetoAuto() throws UnknownHostException {
|
|
|
|
|
sendCommand("AUTO");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void changetoManual() throws UnknownHostException {
|
|
|
|
|
sendCommand("STOP");
|
|
|
|
@ -319,7 +335,10 @@ public class VideoActivity extends AppCompatActivity {
|
|
|
|
|
runOnUiThread(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
imgShow.setImageBitmap(bp);
|
|
|
|
|
int targetWidth = imgShow.getWidth();
|
|
|
|
|
int targetHeight = imgShow.getHeight();
|
|
|
|
|
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bp, targetWidth, targetHeight, true);
|
|
|
|
|
imgShow.setImageBitmap(scaledBitmap);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
@ -466,6 +485,106 @@ public class VideoActivity extends AppCompatActivity {
|
|
|
|
|
running = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String findEncoderCodecName(String mimeType) {
|
|
|
|
|
MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
|
|
|
|
int numCodecs = codecList.getCodecInfos().length;
|
|
|
|
|
for (int i = 0; i < numCodecs; i++) {
|
|
|
|
|
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
|
|
|
|
|
if (!codecInfo.isEncoder()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
String[] types = codecInfo.getSupportedTypes();
|
|
|
|
|
for (String type : types) {
|
|
|
|
|
if (type.equalsIgnoreCase(mimeType)) {
|
|
|
|
|
return codecInfo.getName();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MediaCodec codec;
|
|
|
|
|
private void saveVideo(Bitmap videoBitmap) {
|
|
|
|
|
try {
|
|
|
|
|
String codecName = findEncoderCodecName(MediaFormat.MIMETYPE_VIDEO_AVC);
|
|
|
|
|
if (codecName != null) {
|
|
|
|
|
codec = MediaCodec.createByCodecName(codecName);
|
|
|
|
|
|
|
|
|
|
// 根据视频尺寸设置编码器参数
|
|
|
|
|
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, videoBitmap.getWidth(), videoBitmap.getHeight());
|
|
|
|
|
format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
|
|
|
|
|
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
|
|
|
|
|
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
|
|
|
|
|
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
|
|
|
|
|
|
|
|
|
|
// 配置编码器并启动
|
|
|
|
|
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
|
|
|
|
Surface inputSurface = codec.createInputSurface();
|
|
|
|
|
codec.start();
|
|
|
|
|
|
|
|
|
|
// 创建保存视频的路径和文件名
|
|
|
|
|
String fileName = "video_" + System.currentTimeMillis() + ".mp4";
|
|
|
|
|
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/" + fileName;
|
|
|
|
|
File videoFile = new File(filePath);
|
|
|
|
|
|
|
|
|
|
FileOutputStream fileOutputStream = new FileOutputStream(videoFile);
|
|
|
|
|
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
|
|
|
|
|
|
|
|
|
|
// 循环编码每一帧
|
|
|
|
|
boolean isInputDone = false;
|
|
|
|
|
boolean isOutputDone = false;
|
|
|
|
|
while (!isOutputDone) {
|
|
|
|
|
if (!isInputDone) {
|
|
|
|
|
int index = codec.dequeueInputBuffer(10000);
|
|
|
|
|
if (index >= 0) {
|
|
|
|
|
ByteBuffer inputBuffer = codec.getInputBuffer(index);
|
|
|
|
|
inputBuffer.clear();
|
|
|
|
|
Canvas canvas = inputSurface.lockCanvas(null);
|
|
|
|
|
canvas.drawBitmap(videoBitmap, 0, 0, null);
|
|
|
|
|
inputSurface.unlockCanvasAndPost(canvas);
|
|
|
|
|
codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
|
|
|
|
|
isInputDone = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
|
|
|
|
|
int outputIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
|
|
|
|
|
if (outputIndex >= 0) {
|
|
|
|
|
ByteBuffer outputBuffer = codec.getOutputBuffer(outputIndex);
|
|
|
|
|
byte[] outData = new byte[bufferInfo.size];
|
|
|
|
|
outputBuffer.get(outData);
|
|
|
|
|
bufferedOutputStream.write(outData);
|
|
|
|
|
codec.releaseOutputBuffer(outputIndex, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
|
|
|
|
|
isOutputDone = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关闭文件流
|
|
|
|
|
bufferedOutputStream.flush();
|
|
|
|
|
bufferedOutputStream.close();
|
|
|
|
|
fileOutputStream.close();
|
|
|
|
|
|
|
|
|
|
// 通知媒体库更新文件
|
|
|
|
|
MediaScannerConnection.scanFile(this, new String[]{videoFile.getAbsolutePath()}, null, null);
|
|
|
|
|
|
|
|
|
|
Toast.makeText(this, "视频保存成功", Toast.LENGTH_SHORT).show();
|
|
|
|
|
} else {
|
|
|
|
|
Toast.makeText(this, "无法找到支持的视频编码器", Toast.LENGTH_SHORT).show();
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
} finally {
|
|
|
|
|
if (codec != null) {
|
|
|
|
|
codec.stop();
|
|
|
|
|
codec.release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void showPopup(String speedStatus,String batteryStatus,String distanceStatus) {
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
LayoutInflater inflater = getLayoutInflater();
|
|
|
|
|