| | |
| | | package com.runt.live.ui.stream |
| | | |
| | | import android.graphics.Bitmap |
| | | import android.graphics.Canvas |
| | | import android.graphics.Point |
| | | import android.graphics.Rect |
| | | import android.util.Log |
| | | import android.view.SurfaceHolder |
| | | import com.runt.live.R |
| | | import com.runt.live.cpp.LiveMiniView |
| | | import com.runt.live.cpp.LiveMiniView.FRAME_HEIGHT |
| | | import com.runt.live.cpp.LiveMiniView.FRAME_WIDTH |
| | | import com.runt.live.data.StreamWindow |
| | | import com.runt.live.enum.LiveState |
| | | import com.runt.live.enum.StreamType |
| | | import com.runt.live.native.LivePuller |
| | | import com.runt.live.native.LivePusher |
| | | import com.runt.live.native.MediaPlayer |
| | | import com.runt.live.ui.stream.LiveLayoutView.Companion.subStreamsState |
| | | import com.runt.live.util.BitmapUtils |
| | | import com.runt.open.mvi.base.model.BaseViewModel |
| | | import java.nio.ByteBuffer |
| | | import java.util.concurrent.ConcurrentSkipListMap |
| | | import kotlin.concurrent.thread |
| | | |
| | | |
| | | /** |
| | |
| | | players.put(streamWindow.id,player) |
| | | player.load(filePath) |
| | | } |
| | | |
| | | |
| | | |
| | | fun closePlayer(streamCode : Int){ |
| | | players.get(streamCode)?.let { |
| | |
| | | } |
| | | pushers.remove(code); |
| | | } |
| | | |
| | | fun closePusher(url : String){ |
| | | var code = getPusherCode(url); |
| | | if(code > -1){ |
| | |
| | | LiveMiniView.native_remove_mini_view(streamCode) |
| | | } |
| | | |
| | | fun updateText(streamWindow : StreamWindow){ |
| | | thread { |
| | | var bytes = LiveMiniView.native_get_cut_frame(subStreamsState.value.indexOf(streamWindow),streamWindow.id) |
| | | var bitmap = BitmapUtils.instance!!.textToBitmap(streamWindow.remark!!,130f,getActivity().resources.getColor(R.color.white)!!,getActivity().resources.getColor(R.color.transparent)!!) |
| | | |
| | | var cutwidth : Int = (FRAME_WIDTH * streamWindow.viewRateState.value).toInt() |
| | | var cutHeight : Int = (FRAME_WIDTH / ( streamWindow.sizeState.value.x * 1.0 / streamWindow.sizeState.value.y ) * streamWindow.viewRateState.value).toInt() |
| | | |
| | | //涉及到 YUV 4:2:0 格式的图像时,宽度和高度通常需要是 2 的倍数 |
| | | if (cutwidth % 2 == 1) { |
| | | cutwidth += 1 |
| | | } |
| | | if (cutHeight % 2 == 1) { |
| | | cutHeight += 1 |
| | | } |
| | | if (cutwidth > FRAME_WIDTH) { |
| | | cutwidth = FRAME_WIDTH |
| | | } |
| | | if (cutHeight > FRAME_HEIGHT) { |
| | | cutHeight = FRAME_HEIGHT |
| | | } |
| | | val cutBitmap = Bitmap.createBitmap(cutwidth, cutHeight, Bitmap.Config.ARGB_8888) |
| | | Log.e(TAG , "updateText: ${cutwidth}x${cutHeight} ${streamWindow.sizeState.value} ${( streamWindow.sizeState.value.x * 1.0 / streamWindow.sizeState.value.y )}", ) |
| | | val buffer = ByteBuffer.wrap(bytes) |
| | | cutBitmap.copyPixelsFromBuffer(buffer) |
| | | |
| | | val dstBitmap = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888) |
| | | |
| | | val canvas = Canvas(dstBitmap) |
| | | |
| | | // 构建目标区域 |
| | | val destRect = Rect(0,0,dstBitmap.width,dstBitmap.height) |
| | | |
| | | // 绘制小图到大图 |
| | | canvas.drawBitmap(cutBitmap, null, destRect, null) |
| | | //canvas.drawBitmap(bitmap, null, destRect, null) |
| | | |
| | | val width : Int = bitmap.getWidth() |
| | | val height : Int = bitmap.getHeight() |
| | | val argb = IntArray(width * height) |
| | | dstBitmap.getPixels(argb , 0 , width , 0 , 0 , width , height) |
| | | //LiveMiniView.native_push_nv21(streamWindow.id,BitmapUtils.instance!!.argbToNV21(argb,width,height)); |
| | | } |
| | | |
| | | } |
| | | fun openText(streamWindow : StreamWindow){ |
| | | |
| | | var bitmap = BitmapUtils.instance!!.textToBitmap(streamWindow.remark!!,130f,getActivity().resources.getColor(R.color.white)!!,getActivity().resources.getColor(R.color.transparent)!!) |
| | | streamWindow.hasAudioState.value = false; |
| | | streamWindow.hasVideoState.value = true; |
| | | streamWindow.sizeState.value = Point(bitmap.width,bitmap.height); |
| | | streamWindow.surfaceCallBack = object : SurfaceHolder.Callback { |
| | | override fun surfaceCreated(holder : SurfaceHolder) { |
| | | Log.w(TAG , "surfaceCreated: ${holder.hashCode()}") |
| | | } |
| | | |
| | | override fun surfaceChanged(holder : SurfaceHolder , format : Int , width : Int , height : Int) { |
| | | streamWindow.surfaceHolder = holder; |
| | | streamWindow.listener?.onSurfaceUpdate?.let { it(holder.surface) } |
| | | thread { |
| | | BitmapUtils.instance!!.cavansSurface(holder,bitmap); |
| | | val width : Int = bitmap.getWidth() |
| | | val height : Int = bitmap.getHeight() |
| | | val argb = IntArray(width * height) |
| | | bitmap.getPixels(argb , 0 , width , 0 , 0 , width , height) |
| | | LiveMiniView.native_push_nv21(streamWindow.id,BitmapUtils.instance!!.argbToNV21(argb,width,height)); |
| | | } |
| | | //Log.w(TAG , "surfaceChanged: ${holder.hashCode()}" , ) |
| | | } |
| | | |
| | | override fun surfaceDestroyed(holder : SurfaceHolder) { |
| | | streamWindow.surfaceHolder = null; |
| | | streamWindow.listener?.onSurfaceUpdate?.let { it(null) } |
| | | //Log.w(TAG , "surfaceDestroyed: ${holder.hashCode()} ${id}" , ) |
| | | } |
| | | } |
| | | streamWindow.listener?.onStarted?.invoke() |
| | | } |
| | | |
| | | /** |
| | | * 拉流 |
| | | */ |