desc:record部分代码

main
xiaowusky 2 years ago
parent 88261cc7fb
commit 9952ebfe69

@ -101,12 +101,12 @@ class HomeActivity : NoOptionsActivity() {
*/
private fun setForCamera() {
mClient = EasyPlayerClient(this@HomeActivity, mBinding.surface, null) {
// RecordHelper.onFrameAvailable(it)
if (!AppData.hasCameraData()) {
AppData.setCameraData(true)
changeViewStatus()
closeLoadingDialog()
}
// RecordHelper.onFrameAvailable(it.array().copyOf())
watchCamera(DELAY_TIME_CHECK_CAMERA)
}
mClient?.play(CAMERA_URL)

@ -0,0 +1,39 @@
package com.yinuo.safetywatcher.watcher.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
/**
* Created by caydencui on 2018/12/7.
*/
public class NV21ToBitmap {
private RenderScript rs;
private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
private Type.Builder yuvType, rgbaType;
private Allocation in, out;
public NV21ToBitmap(Context context) {
rs = RenderScript.create(context);
yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
}
public Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
if (yuvType == null) {
yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
}
in.copyFrom(nv21);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
out.copyTo(bmpout);
return bmpout;
}
}

@ -1,34 +1,81 @@
package com.yinuo.safetywatcher.watcher.utils
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageFormat
import android.graphics.Rect
import android.graphics.YuvImage
import android.opengl.EGL14
import com.common.commonlib.CommonApplication
import com.common.commonlib.utils.BitmapUtils
import com.yinuo.library.vlc.encoder.BaseMovieEncoder.EncoderConfig
import com.yinuo.library.vlc.encoder.MovieEncoder1
import org.easydarwin.TxtOverlay
import org.easydarwin.sw.JNIUtil
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.nio.ByteBuffer
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue
object RecordHelper {
private val mVideoEncoder: MovieEncoder1
private val mVideoBitmap: Bitmap
init {
val width = 1920
val height = 1080
val utils by lazy {
NV21ToBitmap(CommonApplication.getContext())
}
private val mTaskQueue: BlockingQueue<ByteArray> = LinkedBlockingQueue()
init {
mVideoEncoder = MovieEncoder1(CommonApplication.getContext(), width, height, true)
mVideoBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
Thread {
while (true) {
val take = mTaskQueue.take()
if (take != null) {
val overLayBitmap: Bitmap? = TxtOverlay.getOverlayBitmap()
val dst = ByteArray(take.size)
JNIUtil.ConvertFromI420(take, dst, width, height, 2)
var mVideoBitmap = utils.nv21ToBitmap(dst, width, height)
if (overLayBitmap != null && mVideoBitmap != null) {
mVideoBitmap = BitmapUtils.mergeBitmap(mVideoBitmap!!, overLayBitmap)
}
val baos2 = ByteArrayOutputStream()
mVideoBitmap?.compress(Bitmap.CompressFormat.PNG, 100, baos2)
val data = baos2.toByteArray()
mVideoEncoder.frameAvailable(data, System.nanoTime())
}
}
}.start()
}
fun onFrameAvailable(buffer: ByteBuffer?) {
fun onFrameAvailable(buffer: ByteBuffer) {
val input = ByteArray(buffer.capacity())
buffer.clear()
buffer[input]
TxtOverlay.setShowTip("111@2222")
val overLayBitmap: Bitmap? = TxtOverlay.getOverlayBitmap()
mVideoBitmap.copyPixelsFromBuffer(buffer?.position(0))
if (overLayBitmap != null) {
val mVideoBitmap = BitmapUtils.mergeBitmap(mVideoBitmap, overLayBitmap)
buffer?.clear()
mVideoBitmap?.copyPixelsToBuffer(buffer)
val dst = ByteArray(buffer.capacity())
JNIUtil.ConvertFromI420(input, dst, width, height, 2)
val yuvimage = YuvImage(dst, ImageFormat.NV21, width, height, null)
val baos = ByteArrayOutputStream()
yuvimage.compressToJpeg(Rect(0, 0, width, height), 80, baos)
val toByteArray = baos.toByteArray()
var mVideoBitmap = BitmapFactory.decodeByteArray(toByteArray, 0, toByteArray.size)
baos.close()
if (overLayBitmap != null && mVideoBitmap != null) {
mVideoBitmap = BitmapUtils.mergeBitmap(mVideoBitmap!!, overLayBitmap)
}
mVideoEncoder.frameAvailable(buffer?.array(), System.nanoTime())
val yuvByBitmap = getYUVByBitmap(mVideoBitmap)
buffer.clear()
buffer.limit(yuvByBitmap!!.size)
buffer.put(yuvByBitmap)
}
fun startRecording() {
@ -42,4 +89,151 @@ object RecordHelper {
mVideoEncoder.stopRecording()
}
}
fun rgb2YCbCr420(pixels: IntArray, width: Int, height: Int): ByteArray {
val len = width * height
// yuv格式数组大小y亮度占len长度u,v各占len/4长度。
val yuv = ByteArray(len * 3 / 2)
var y: Int
var u: Int
var v: Int
for (i in 0 until height) {
for (j in 0 until width) {
// 屏蔽ARGB的透明度值
val rgb = pixels[i * width + j] and 0x00FFFFFF
// 像素的颜色顺序为bgr移位运算。
val r = rgb and 0xFF
val g = rgb shr 8 and 0xFF
val b = rgb shr 16 and 0xFF
// 套用公式
y = (66 * r + 129 * g + 25 * b + 128 shr 8) + 16
u = (-38 * r - 74 * g + 112 * b + 128 shr 8) + 128
v = (112 * r - 94 * g - 18 * b + 128 shr 8) + 128
// rgb2yuv
// y = (int) (0.299 * r + 0.587 * g + 0.114 * b);
// u = (int) (-0.147 * r - 0.289 * g + 0.437 * b);
// v = (int) (0.615 * r - 0.515 * g - 0.1 * b);
// RGB转换YCbCr
// y = (int) (0.299 * r + 0.587 * g + 0.114 * b);
// u = (int) (-0.1687 * r - 0.3313 * g + 0.5 * b + 128);
// if (u > 255)
// u = 255;
// v = (int) (0.5 * r - 0.4187 * g - 0.0813 * b + 128);
// if (v > 255)
// v = 255;
// 调整
y = if (y < 16) 16 else if (y > 255) 255 else y
u = if (u < 0) 0 else if (u > 255) 255 else u
v = if (v < 0) 0 else if (v > 255) 255 else v
// 赋值
yuv[i * width + j] = y.toByte()
yuv[len + ((i shr 1) * width) + (j and 1.inv()) + 0] = u.toByte()
yuv[len + (+(i shr 1) * width) + (j and 1.inv()) + 1] = v.toByte()
}
}
return yuv
}
fun decodeYUV420SP(
rgbBuf: ByteArray?, yuv420sp: ByteArray?,
width: Int, height: Int
) {
val frameSize = width * height
if (rgbBuf == null) throw NullPointerException("buffer 'rgbBuf' is null")
if (rgbBuf.size < frameSize * 3) throw IllegalArgumentException(
("buffer 'rgbBuf' size "
+ rgbBuf.size + " < minimum ") + frameSize * 3
)
if (yuv420sp == null) throw NullPointerException("buffer 'yuv420sp' is null")
if (yuv420sp.size < frameSize * 3 / 2) throw IllegalArgumentException(
("buffer 'yuv420sp' size "
+ yuv420sp.size + " < minimum " + (frameSize * 3 / 2))
)
var i = 0
var y = 0
var uvp = 0
var u = 0
var v = 0
var y1192 = 0
var r = 0
var g = 0
var b = 0
var j = 0
var yp = 0
while (j < height) {
uvp = frameSize + (j shr 1) * width
u = 0
v = 0
i = 0
while (i < width) {
y = (0xff and (yuv420sp[yp].toInt())) - 16
if (y < 0) y = 0
if ((i and 1) == 0) {
v = (0xff and yuv420sp[uvp++].toInt()) - 128
u = (0xff and yuv420sp[uvp++].toInt()) - 128
}
y1192 = 1192 * y
r = (y1192 + 1634 * v)
g = (y1192 - (833 * v) - (400 * u))
b = (y1192 + 2066 * u)
if (r < 0) r = 0 else if (r > 262143) r = 262143
if (g < 0) g = 0 else if (g > 262143) g = 262143
if (b < 0) b = 0 else if (b > 262143) b = 262143
rgbBuf[yp * 3] = (r shr 10).toByte()
rgbBuf[yp * 3 + 1] = (g shr 10).toByte()
rgbBuf[yp * 3 + 2] = (b shr 10).toByte()
i++
yp++
}
j++
}
}
/*
* 获取位图的RGB数据
*/
fun getRGBByBitmap(bitmap: Bitmap?): ByteArray? {
if (bitmap == null) {
return null
}
val width = bitmap.width
val height = bitmap.height
val size = width * height
val pixels = IntArray(size)
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
return convertColorToByte(pixels)
}
/*
* 获取位图的YUV数据
*/
fun getYUVByBitmap(bitmap: Bitmap?): ByteArray? {
if (bitmap == null) {
return null
}
val width = bitmap.width
val height = bitmap.height
val size = width * height
val pixels = IntArray(size)
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
// byte[] data = convertColorToByte(pixels);
return rgb2YCbCr420(pixels, width, height)
}
/*
* 像素数组转化为RGB数组
*/
fun convertColorToByte(color: IntArray?): ByteArray? {
if (color == null) {
return null
}
val data = ByteArray(color.size * 3)
for (i in color.indices) {
data[i * 3] = ((color[i] shr 16) and 0xff).toByte()
data[i * 3 + 1] = ((color[i] shr 8) and 0xff).toByte()
data[i * 3 + 2] = (color[i] and 0xff).toByte()
}
return data
}
}

@ -11,7 +11,7 @@ object BitmapUtils {
* @param frontBitmap 盖在上面的位图
* @return
*/
fun mergeBitmap(backBitmap: Bitmap?, frontBitmap: Bitmap?): Bitmap? {
fun mergeBitmap(backBitmap: Bitmap, frontBitmap: Bitmap?): Bitmap {
if (backBitmap == null || backBitmap.isRecycled || frontBitmap == null || frontBitmap.isRecycled) {
return backBitmap
}

Loading…
Cancel
Save