desc:新推流

main
xiaowusky 1 year ago
parent 40bcacfcce
commit b57348ad15

@ -110,14 +110,14 @@ class HomeActivity : NoOptionsActivity() {
}
private fun onCameraOpen() {
// 启动录制编码
RecordHelper.startRecording()
// 启动推送
PushHelper.opSwitch(true)
PushHelper.startStream(true)
// 开启GPIO
GPIOUtils.openCamera()
setForCamera()
// 启动录制编码
RecordHelper.startRecording()
}
private fun onCameraClose() {

@ -2,20 +2,16 @@ package com.yinuo.safetywatcher.watcher.utils
import android.graphics.Bitmap
import android.view.TextureView
import com.yinuo.library.vlc.encoder.MediaCodecManager
import org.easydarwin.TxtOverlay
import org.easydarwin.push.HWConsumer
object RecordHelper {
private val codecManager: MediaCodecManager = MediaCodecManager.getInstance()
private const val width = 1920
private const val height = 1080
private const val overlayOffset = 20
private var recording = false;
init {
codecManager.initCodecManager(width, height, 0)
}
private var consumer: HWConsumer? = null
fun onFrameAvailable(view: TextureView, nv12Data: ByteArray) {
if (!recording) {
@ -44,20 +40,22 @@ object RecordHelper {
}
}
}
codecManager.addFrameData(nv12Data)
consumer?.onVideo(nv12Data, 0)
}
fun startRecording() {
if (!recording) {
recording = true
codecManager.startMediaCodec()
consumer = HWConsumer()
consumer?.onVideoStart(width, height)
}
}
fun stopRecording() {
if (recording) {
recording = false
codecManager.stopMediaCodec()
consumer?.onVideoStop()
consumer = null
}
}
}

@ -98,7 +98,7 @@ object PushHelper {
mPusher?.initPush(mApplicationContext, callback)
mPusher?.setMediaInfo(
if (hevc) Pusher.Codec.EASY_SDK_VIDEO_CODEC_H265 else Pusher.Codec.EASY_SDK_VIDEO_CODEC_H264,
24,
17,
Pusher.Codec.EASY_SDK_AUDIO_CODEC_AAC,
1,
8000,

@ -0,0 +1,243 @@
package org.easydarwin.push;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.yinuo.library.vlc.encoder.AndroidMuxer;
import org.easydarwin.PushHelper;
import org.easydarwin.muxer.EasyMuxer;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Created by apple on 2017/5/13.
*/
public class HWConsumer extends Thread implements VideoConsumer {
private static final String TAG = "HWConsumer";
private static final String MIME_TYPE = "video/hevc";
private int mHeight;
private int mWidth;
private MediaCodec mMediaCodec;
private ByteBuffer[] inputBuffers;
private ByteBuffer[] outputBuffers;
private volatile boolean mVideoStarted;
private MediaFormat newFormat;
private AndroidMuxer androidMuxer;
private int mTrackIndex = -1;
public HWConsumer() {
}
@Override
public void onVideoStart(int width, int height) {
newFormat = null;
this.mWidth = width;
this.mHeight = height;
startMediaCodec();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + 1) {
inputBuffers = outputBuffers = null;
} else {
inputBuffers = mMediaCodec.getInputBuffers();
outputBuffers = mMediaCodec.getOutputBuffers();
}
androidMuxer = new AndroidMuxer();
start();
mVideoStarted = true;
}
// final int millisPerframe = 1000 / 17;
// long lastPush = 0;
@Override
public int onVideo(byte[] nv12, int format) {
if (!mVideoStarted) return 0;
try {
byte[] data = nv12;
// if (lastPush == 0) {
// lastPush = System.currentTimeMillis();
// }
// long time = System.currentTimeMillis() - lastPush;
// if (time >= 0) {
// time = millisPerframe - time;
// if (time > 0) Thread.sleep(time / 2);
// }
int bufferIndex = mMediaCodec.dequeueInputBuffer(0);
if (bufferIndex >= 0) {
Log.d(TAG, "onVideo: " + bufferIndex);
ByteBuffer buffer = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
buffer = mMediaCodec.getInputBuffer(bufferIndex);
} else {
buffer = inputBuffers[bufferIndex];
}
buffer.clear();
buffer.put(data);
buffer.clear();
mMediaCodec.queueInputBuffer(bufferIndex, 0, data.length, System.nanoTime() / 1000, MediaCodec.BUFFER_FLAG_KEY_FRAME);
}
// if (time > 0) Thread.sleep(time / 2);
// lastPush = System.currentTimeMillis();
} catch (Exception ex) {
ex.printStackTrace();
}
return 0;
}
@Override
public void run() {
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = 0;
int NAL_I = 19;
int NAL_VPS = 32;
byte[] vps_sps_pps_buf = null;
do {
outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
// no output available yet
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// not expected for an encoder
outputBuffers = mMediaCodec.getOutputBuffers();
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
synchronized (HWConsumer.this) {
newFormat = mMediaCodec.getOutputFormat();
if (androidMuxer != null) {
// should happen before receiving buffers, and should only happen once
mTrackIndex = androidMuxer.addTrack(newFormat);
}
}
} else if (outputBufferIndex < 0) {
// let's ignore it
} else {
ByteBuffer outputBuffer;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
outputBuffer = mMediaCodec.getOutputBuffer(outputBufferIndex);
} else {
outputBuffer = outputBuffers[outputBufferIndex];
}
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
if (androidMuxer != null && mTrackIndex != -1) {
androidMuxer.writeSampleData(mTrackIndex, outputBuffer, bufferInfo);
}
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
int offset = 4;
if (outData[2] == 0x01) {
offset = 3;
}
int type = (outData[offset] & 0x7E) >> 1;
Log.i("cyy", "type = " + type);
if (type == NAL_VPS) {
if (vps_sps_pps_buf == null) {
vps_sps_pps_buf = outData;
}
} else if (type == NAL_I) {
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(outData, 0, newBuf, vps_sps_pps_buf.length, outData.length);
outData = newBuf;
}
PushHelper.INSTANCE.pushData(outData, outData.length, bufferInfo.presentationTimeUs / 1000, 1);
mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
}
while (mVideoStarted);
}
@Override
public void onVideoStop() {
do {
newFormat = null;
mVideoStarted = false;
try {
join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (isAlive());
if (androidMuxer != null) {
androidMuxer.release();
}
if (mMediaCodec != null) {
stopMediaCodec();
mMediaCodec = null;
}
}
@Override
public synchronized void setMuxer(EasyMuxer muxer) {
}
/**
*
*/
private void startMediaCodec() {
/*
SD (Low quality) SD (High quality) HD 720p
1 HD 1080p
1
Video resolution 320 x 240 px 720 x 480 px 1280 x 720 px 1920 x 1080 px
Video frame rate 20 fps 30 fps 30 fps 30 fps
Video bitrate 384 Kbps 2 Mbps 4 Mbps 10 Mbps
*/
int framerate = 17;
// if (width == 640 || height == 640) {
// bitrate = 2000000;
// } else if (width == 1280 || height == 1280) {
// bitrate = 4000000;
// } else {
// bitrate = 2 * width * height;
// }
int bitrate = (int) (mWidth * mHeight * 20 * 2 * 0.05f);
if (mWidth >= 1920 || mHeight >= 1920)
bitrate *= 0.3;
else if (mWidth >= 1280 || mHeight >= 1280)
bitrate *= 0.4;
else if (mWidth >= 720 || mHeight >= 720)
bitrate *= 0.6;
try {
// mMediaCodec = MediaCodec.createByCodecName("0MX.rk.video_encoder.avc");
mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
} catch (IOException e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate + 3000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mMediaCodec.start();
Bundle params = new Bundle();
params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mMediaCodec.setParameters(params);
}
}
/**
*
*/
private void stopMediaCodec() {
mMediaCodec.stop();
mMediaCodec.release();
}
}
Loading…
Cancel
Save