From b81662a42a8446cb02485463302f112eb8579f07 Mon Sep 17 00:00:00 2001 From: CYZ <2782394648@qq.com> Date: Tue, 27 Jun 2023 19:48:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BD=95=E5=88=B6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../f4a01d6a4fcb971362ec00a83903fd3902f52164 | 0 .../.idea/sonarlint/issuestore/index.pb | 2 - src/sixaunyi/app/build.gradle | 1 + .../com/example/sixaunyi/VideoActivity.java | 139 ++++++++++++++++-- 4 files changed, 130 insertions(+), 12 deletions(-) delete mode 100644 src/sixaunyi/.idea/sonarlint/issuestore/f/4/f4a01d6a4fcb971362ec00a83903fd3902f52164 diff --git a/src/sixaunyi/.idea/sonarlint/issuestore/f/4/f4a01d6a4fcb971362ec00a83903fd3902f52164 b/src/sixaunyi/.idea/sonarlint/issuestore/f/4/f4a01d6a4fcb971362ec00a83903fd3902f52164 deleted file mode 100644 index e69de29..0000000 diff --git a/src/sixaunyi/.idea/sonarlint/issuestore/index.pb b/src/sixaunyi/.idea/sonarlint/issuestore/index.pb index bd69223..d34424b 100644 --- a/src/sixaunyi/.idea/sonarlint/issuestore/index.pb +++ b/src/sixaunyi/.idea/sonarlint/issuestore/index.pb @@ -13,8 +13,6 @@ i 9app/src/main/java/com/example/sixaunyi/FirstFragment.java,0\3\0336633037f72ee431c162e8d6cbc29d1cd6fa5d ? settings.gradle,0\5\05efc8b1657769a27696d478ded1e95f38737233 -@ -app/build.gradle,f\4\f4a01d6a4fcb971362ec00a83903fd3902f52164 j :app/src/main/java/com/example/sixaunyi/SecondFragment.java,1\2\12963d86ac5c2888cc2a9ae459de5665bc06b01f j diff --git a/src/sixaunyi/app/build.gradle b/src/sixaunyi/app/build.gradle index 8d7d5e6..1f65d5b 100644 --- a/src/sixaunyi/app/build.gradle +++ b/src/sixaunyi/app/build.gradle @@ -46,6 +46,7 @@ dependencies { implementation 'pub.devrel:easypermissions:3.0.0' //Material库 implementation 'com.google.android.material:material:1.6.1' + implementation 'androidx.media:media:1.3.0' //定位功能 diff --git a/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java b/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java index b1c91be..e640036 100644 --- a/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java +++ b/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java @@ -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();