package com.runt.live.ui.stream
|
|
import android.graphics.Point
|
import android.os.Handler
|
import android.util.Log
|
import android.view.SurfaceHolder
|
import com.runt.live.R
|
import com.runt.live.cpp.LiveMiniView
|
import com.runt.live.data.StreamWindow
|
import com.runt.live.enum.LiveState
|
import com.runt.live.native.LivePuller
|
import com.runt.live.native.LivePusher
|
import com.runt.live.native.MediaPlayer
|
import com.runt.live.util.BitmapUtils
|
import com.runt.open.mvi.base.model.BaseViewModel
|
import java.util.concurrent.ConcurrentSkipListMap
|
import kotlin.concurrent.thread
|
|
|
/**
|
* @author Runt(qingingrunt2010@qq.com)
|
* @purpose
|
* @date 9/17/24
|
*/
|
class LiveViewModel: BaseViewModel() {
|
|
var pushers = ConcurrentSkipListMap<Int,LivePusher>()
|
var pullers = ConcurrentSkipListMap<Int,LivePuller>()
|
var players = ConcurrentSkipListMap<Int,MediaPlayer>();
|
|
fun createPusher(url:String ,listener : LivePusher.PusherStreamListener):LivePusher{
|
var pusher = LivePusher(url,listener);
|
pushers.put(pusher.code,pusher)
|
pusher.connect();
|
return pusher;
|
}
|
|
fun getPusher(streamCode : Int):LivePusher? {
|
return pushers[streamCode];
|
}
|
|
fun createPlayer(filePath:String,streamWindow : StreamWindow){
|
var player = MediaPlayer(streamWindow)
|
players.put(streamWindow.id,player)
|
player.load(filePath)
|
}
|
|
fun closePlayer(streamCode : Int){
|
players.get(streamCode)?.let {
|
it.close();
|
}
|
}
|
|
fun pausePlayer(streamCode : Int){
|
players.get(streamCode)?.let {
|
it.pause();
|
}
|
}
|
|
fun playPlayer(streamCode : Int){
|
players.get(streamCode)?.let {
|
it.play();
|
}
|
}
|
|
fun setPlayerProgress(streamCode : Int,progress:Long){
|
players.get(streamCode)?.let {
|
it.setProgress(progress)
|
}
|
}
|
|
fun connectRtmpPull(streamWindow : StreamWindow){
|
val puller = LivePuller(streamWindow);
|
pullers.put(streamWindow.id,puller)
|
puller.native_connect(streamWindow.id,streamWindow.remark!!)
|
}
|
|
fun closePuller(streamCode:Int){
|
pullers.get(streamCode)?.let {
|
it.native_close(streamCode);
|
}
|
pullers.remove(streamCode)
|
}
|
|
fun getPusherCode(url:String):Int{
|
var code:Int = -1;
|
for(pusher in pushers.values){
|
if(pusher.url.equals(url)){
|
code = pusher.code;
|
break;
|
}
|
}
|
return code;
|
}
|
|
fun closePusher(code : Int){
|
pushers.get(code)?.let {
|
it.native_close(code);
|
}
|
pushers.remove(code);
|
}
|
|
fun closePusher(url : String){
|
var code = getPusherCode(url);
|
if(code > -1){
|
pushers.get(code)?.let {
|
it.native_close(code);
|
}
|
pushers.remove(code);
|
}
|
}
|
|
fun closeAll(){
|
for(streamCode in pullers.keys){
|
pullers.get(streamCode)?.let {
|
it.native_close(streamCode);
|
}
|
}
|
pullers.clear()
|
for(streamCode in pushers.keys){
|
pushers.get(streamCode)?.let {
|
it.native_close(streamCode);
|
}
|
}
|
pushers.clear()
|
}
|
|
/**
|
* 视频流
|
*/
|
fun pushNV21(streamCode : Int,byteArray : ByteArray){
|
LiveMiniView.native_push_nv21(streamCode,byteArray)
|
}
|
|
fun updateMiniView(index:Int,streamWindow : StreamWindow){
|
LiveMiniView.native_update_mini_view( streamWindow.id, index, streamWindow.sizeState.value.x, streamWindow.sizeState.value.y,
|
streamWindow.positionRateState.value.x, streamWindow.positionRateState.value.y ,
|
streamWindow.audioState.value == LiveState.IN_LIVE,streamWindow.videoState.value == LiveState.IN_LIVE,
|
streamWindow.videoDelay,streamWindow.streamType.value,
|
streamWindow.mainPositionRateState.value, streamWindow.viewRateState.value)
|
|
}
|
|
fun removeMiniView(streamCode :Int){
|
LiveMiniView.native_remove_mini_view(streamCode)
|
}
|
|
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);
|
}
|
//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}" , )
|
}
|
}
|
Handler().postDelayed({streamWindow.listener?.onStarted?.invoke()},500)
|
}
|
|
/**
|
* 拉流
|
*/
|
fun startPullStream(){
|
|
}
|
|
/**
|
* 停止拉流
|
*/
|
fun stopPullStream(){
|
|
}
|
|
}
|