desc:推流相关

main
xiaowusky 1 year ago
parent 3316d8561c
commit f81bd2c76d

@ -32,7 +32,6 @@ object TestUtils {
fun insertData() { fun insertData() {
getSupportCodec() getSupportCodec()
PushHelper.setPushUrl("rtsp://192.168.5.17:554/123")
GlobalScope.launch() { GlobalScope.launch() {
// 构造气体数据 // 构造气体数据
val timeMillis = System.currentTimeMillis() val timeMillis = System.currentTimeMillis()

@ -3,18 +3,8 @@ package com.yinuo.safetywatcher.watcher
import com.common.commonlib.CommonApplication import com.common.commonlib.CommonApplication
import com.common.commonlib.db.DBUtils import com.common.commonlib.db.DBUtils
import com.common.commonlib.db.entity.Warning import com.common.commonlib.db.entity.Warning
import com.yinuo.safetywatcher.R
import com.yinuo.safetywatcher.TestUtils
import com.yinuo.safetywatcher.watcher.constant.CAMERA_DNS
import com.yinuo.safetywatcher.watcher.constant.CAMERA_GATEWAY
import com.yinuo.safetywatcher.watcher.constant.CAMERA_IP
import com.yinuo.safetywatcher.watcher.constant.CAMERA_NETMASK
import com.yinuo.safetywatcher.watcher.port.cmd.GasPortStatus
import com.yinuo.safetywatcher.watcher.utils.GPIOUtils import com.yinuo.safetywatcher.watcher.utils.GPIOUtils
import com.yinuo.safetywatcher.watcher.utils.PlatformUtils import com.yinuo.safetywatcher.watcher.utils.PlatformUtils
import com.yinuo.safetywatcher.watcher.utils.SoundUtils
import com.yinuo.safetywatcher.watcher.wifi.WiFiConfig
import com.yinuo.safetywatcher.watcher.wifi.WiFiModule
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope

@ -29,6 +29,7 @@ import com.yinuo.safetywatcher.watcher.utils.WifiHelper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.easydarwin.PushHelper
import org.easydarwin.TxtOverlay import org.easydarwin.TxtOverlay
import org.easydarwin.video.EasyPlayerClient import org.easydarwin.video.EasyPlayerClient
import java.io.File import java.io.File
@ -101,6 +102,9 @@ class HomeActivity : NoOptionsActivity() {
private fun onCameraOpen() { private fun onCameraOpen() {
// 启动录制编码 // 启动录制编码
RecordHelper.startRecording() RecordHelper.startRecording()
// 启动推送
PushHelper.opSwitch(true)
PushHelper.startStream(true)
// 开启GPIO // 开启GPIO
GPIOUtils.openCamera() GPIOUtils.openCamera()
setForCamera() setForCamera()
@ -109,6 +113,9 @@ class HomeActivity : NoOptionsActivity() {
private fun onCameraClose() { private fun onCameraClose() {
// 暂停录制编码 // 暂停录制编码
RecordHelper.stopRecording() RecordHelper.stopRecording()
// 关闭推流
PushHelper.opSwitch(false)
PushHelper.stop()
// 关闭GPIO // 关闭GPIO
GPIOUtils.closeCamera() GPIOUtils.closeCamera()
// 关闭视频播放 // 关闭视频播放

@ -5,8 +5,10 @@ import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -15,7 +17,6 @@ import com.common.commonlib.utils.LogUtils;
import org.easydarwin.PushHelper; import org.easydarwin.PushHelper;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@TargetApi(Build.VERSION_CODES.M) @TargetApi(Build.VERSION_CODES.M)
@ -42,9 +43,6 @@ public class MediaCodecManager {
private boolean isFlush = false; private boolean isFlush = false;
private long lastPauseTime = -1;//上次暂停时间
private boolean isHasKeyFrame;
private Handler mHandler; private Handler mHandler;
private int off_y = 50, off_x = 100; private int off_y = 50, off_x = 100;
@ -182,14 +180,14 @@ public class MediaCodecManager {
int videoH = rotation == 90 || rotation == 270 ? dstWidth : dstHeight; int videoH = rotation == 90 || rotation == 270 ? dstWidth : dstHeight;
mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,//注意这里旋转后有一个大坑就是要交换mHeight和mWidth的位置。否则录制出来的视频时花屏的。 mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,//注意这里旋转后有一个大坑就是要交换mHeight和mWidth的位置。否则录制出来的视频时花屏的。
videoW, videoH); videoW, videoH);
int frameRate = 25; // 15fps int frameRate = 24; // 15fps
int compressRatio = 256; int compressRatio = 256;
int bitRate = dstWidth * dstHeight * 3 * 8 * frameRate / compressRatio; int bitRate = dstWidth * dstHeight * 3 * 8 * frameRate / compressRatio;
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mColorFormat); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mColorFormat);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); mediaFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 5f);
LogUtils.w("prepare format: " + mediaFormat); LogUtils.w("prepare format: " + mediaFormat);
} }
@ -197,7 +195,6 @@ public class MediaCodecManager {
public static final int NAL_VPS = 32; public static final int NAL_VPS = 32;
private byte[] vps_sps_pps_buf; private byte[] vps_sps_pps_buf;
byte[] outData;
private void start() { private void start() {
if (!isInitCodec) if (!isInitCodec)
@ -244,45 +241,39 @@ public class MediaCodecManager {
@Override @Override
public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) { public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
buildKeyFrame();
ByteBuffer outputBuffer = codec.getOutputBuffer(index); ByteBuffer outputBuffer = codec.getOutputBuffer(index);
if (!isHasKeyFrame && info.flags == MediaCodec.BUFFER_FLAG_KEY_FRAME) { if (outputBuffer == null) {
isHasKeyFrame = true;
}
if (outData == null) {
outData = new byte[info.size];
}
if (outputBuffer == null)
return; return;
else if (info.presentationTimeUs < lastPauseTime || !isHasKeyFrame) {//上一视频的数据,或者无关键帧,丢弃
//视频第一帧一定要是关键帧
outputBuffer.get(outData);
} else if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) { } else if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
LogUtils.w(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG"); LogUtils.w(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
} else { } else {
outputBuffer.position(info.offset); outputBuffer.position(info.offset);
outputBuffer.limit(info.offset + info.size); outputBuffer.limit(info.offset + info.size);
if (androidMuxer != null) { if (androidMuxer != null && mTrackIndex != -1) {
androidMuxer.writeSampleData(mTrackIndex, outputBuffer, info); androidMuxer.writeSampleData(mTrackIndex, outputBuffer, info);
} }
byte[] outData = new byte[info.size];
outputBuffer.get(outData);
int offset = 4; int offset = 4;
if (outData[2] == 0x01) { if (outData[2] == 0x01) {
offset = 3; offset = 3;
} }
int type = (outData[offset] & 0x7E) >> 1; int type = (outData[offset] & 0x7E) >> 1;
Log.i("cyy", "type = " + type);
if (type == NAL_VPS) { if (type == NAL_VPS) {
vps_sps_pps_buf = outData; vps_sps_pps_buf = outData;
PushHelper.INSTANCE.pushData(outData, outData.length, info.presentationTimeUs / 1000); } else {
} else if (type == NAL_I) { if (type == NAL_I && vps_sps_pps_buf != null) {
if (vps_sps_pps_buf != null) {
byte[] newBuf = new byte[vps_sps_pps_buf.length + outData.length]; byte[] newBuf = new byte[vps_sps_pps_buf.length + outData.length];
System.arraycopy(vps_sps_pps_buf, 0, newBuf, 0, vps_sps_pps_buf.length); System.arraycopy(vps_sps_pps_buf, 0, newBuf, 0, vps_sps_pps_buf.length);
System.arraycopy(outData, 0, newBuf, vps_sps_pps_buf.length, outData.length); System.arraycopy(outData, 0, newBuf, vps_sps_pps_buf.length, outData.length);
outData = newBuf; outData = newBuf;
PushHelper.INSTANCE.pushData(outData, outData.length, info.presentationTimeUs / 1000);
} }
} }
PushHelper.INSTANCE.pushData(outData, outData.length, info.presentationTimeUs / 1000);
codec.releaseOutputBuffer(index, false);
} }
codec.releaseOutputBuffer(index, false);
try { try {
Thread.sleep(0); Thread.sleep(0);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -313,6 +304,17 @@ public class MediaCodecManager {
isStart = true; isStart = true;
} }
long timeStamp = -1L;
void buildKeyFrame() {
if (System.currentTimeMillis() - timeStamp >= 5000) {//1000毫秒后设置参数
timeStamp = System.currentTimeMillis();
Bundle params = new Bundle();
params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
mMediaCodec.setParameters(params);
}
}
/** /**
* *
*/ */
@ -320,9 +322,9 @@ public class MediaCodecManager {
LogUtils.w(TAG, "flushMediaCodec"); LogUtils.w(TAG, "flushMediaCodec");
frameBytes.clear(); frameBytes.clear();
isFlush = true; isFlush = true;
lastPauseTime = (System.nanoTime()) / 1000;//记录 // lastPauseTime = (System.nanoTime()) / 1000;//记录
//
isHasKeyFrame = false; // isHasKeyFrame = false;
} }
@ -339,7 +341,7 @@ public class MediaCodecManager {
} }
isStart = false; isStart = false;
isPause = true; isPause = true;
isHasKeyFrame = false; // isHasKeyFrame = false;
LogUtils.w(TAG, "stopMediaCodec video"); LogUtils.w(TAG, "stopMediaCodec video");
}); });
} }

@ -22,8 +22,14 @@ object PushHelper {
private var mInitialized = false private var mInitialized = false
private var switchOpen = true
fun opSwitch(open: Boolean) {
switchOpen = open
}
var callback = InitCallback { code -> var callback = InitCallback { code ->
var msg = "" var msg = "$code"
when (code) { when (code) {
EasyPusher.OnInitPusherCallback.CODE.EASY_ACTIVATE_INVALID_KEY -> msg = "无效Key" EasyPusher.OnInitPusherCallback.CODE.EASY_ACTIVATE_INVALID_KEY -> msg = "无效Key"
EasyPusher.OnInitPusherCallback.CODE.EASY_ACTIVATE_SUCCESS -> msg = "未开始" EasyPusher.OnInitPusherCallback.CODE.EASY_ACTIVATE_SUCCESS -> msg = "未开始"
@ -50,14 +56,16 @@ object PushHelper {
mIp = mUri.host mIp = mUri.host
mPort = mUri.port.toString() mPort = mUri.port.toString()
mId = mUri.path mId = mUri.path
if (mId?.startsWith("/")!!){ if (mId?.startsWith("/")!!) {
mId = mId!!.substring(1) mId = mId!!.substring(1)
} }
} }
fun startStream(hevc: Boolean) { fun startStream(hevc: Boolean) {
stop() if (switchOpen) {
initHelper(hevc) stop()
initHelper(hevc)
}
} }
fun stop() { fun stop() {

Loading…
Cancel
Save