rtmp学习记录(4) 回放对接实现

1.客户端(unity)构建一个查询界面,传给服务端要查询哪段时间的哪个摄像头,因为是通过录像机取的,就是哪个通道。

2.服务端调用SDK代码,下载文件。

3.客户端同时轮询下载进度,SDK的Demo就是这么干的,Timer里面轮询进度。

4.下载完成后用ump播放。

客户端没有下载,是服务端下载的,客户端只是根据下载结束后给点一个url,进行hls播放。

一.接口定位(WCF)

 [ServiceContract]
    public interface INVSPlayer
    {
        /// <summary>
        /// 停止下载
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [OperationContract]
        DownloadInfo StopGetNVSVideo(DownloadInfo info);

        /// <summary>
        /// 开始下载
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [OperationContract]
        DownloadInfo StartGetNVSVideo(DownloadInfo info);

        /// <summary>
        /// 获取下载进度
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [OperationContract]
        DownloadProgress GetNVSProgress(DownloadInfo info);
    }
    public class DownloadInfo
    {
        /// <summary>
        /// Dev_Camera的Id,为了获取下面的IP和通道
        /// </summary>
        public int CId { get; set; }

        /// <summary>
        /// 录像机IP
        /// </summary>
        public string Ip { get; set; }

        /// <summary>
        /// 录像机通道
        /// </summary>
        public string Channel { get; set; }

        /// <summary>
        /// 开始时间 2019-07-19 13:07:45 "yyyy-MM-dd HH:mm:ss"
        /// </summary>
        public string StartTime { get; set; }

        /// <summary>
        /// 结束时间
        /// </summary>
        public string EndTime { get; set; }

        /// <summary>
        /// 结果
        /// </summary>
        public bool Result { get; set; }

        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// 下载Id
        /// </summary>
        public int DId { get; set; }

        /// <summary>
        /// hls地址(已经存在该文件的情况下)
        /// </summary>
        public string Url { get; set; }

        public override string ToString()
        {
            //return string.Format("cid:{0},start:{1},end:{2}", CId, StartTime, EndTime);
            string json = JsonConvert.SerializeObject(this);
            return json;
        }
    }
public class DownloadProgress
    {
        /// <summary>
        /// 下载Id
        /// </summary>
        public int DId { get; set; }

        /// <summary>
        /// 进度
        /// </summary>
        public int Progress { get; set; }

        /// <summary>
        /// 进度内容
        /// </summary>
        public string ProgressText { get; set; }

        /// <summary>
        /// 是否完成
        /// </summary>
        public bool IsFinished { get; set; }

        /// <summary>
        ///  hls地址
        /// </summary>
        public string Url { get; set; }

        public override string ToString()
        {
            //return string.Format("cid:{0},Progress:{1},ProgressText:{2},IsFinished:{3},Url{4}", CId, Progress,
            //    ProgressText, IsFinished, Url);

            string json = JsonConvert.SerializeObject(this);
            return json;
        }
    }

二.接口实现

public DownloadInfo StopGetNVSVideo(DownloadInfo info)
        {
            try
            {
                Log.Info(LogTags.DbGet, "StopGetNVSVideo:" + info);
                NVSManage.GetPlayBackFormEx(info.Ip, (f, s) => { f.Stop(); });
                return info;
            }
            catch (Exception e)
            {
                Log.Error(LogTags.DbGet, "LocationService.StopGetNVSVideo:" + ToString());
                return null;
            }
        }

        public DownloadInfo StartGetNVSVideo(DownloadInfo info)
        {
            try
            {
                Log.Info(LogTags.DbGet, "StartGetNVSVideo:"+ info);
                if (info == null) return null;

                //客户端可以把IP(录像机的IP)和Channel传过来(不用查数据库),也可以只传一个摄像机Id(要查数据库)
                if (string.IsNullOrEmpty(info.Ip) || string.IsNullOrEmpty(info.Channel)) 
                {
                    Log.Info(LogTags.DbGet, "GetIpAndChannelFormDb");

                    if (!GetIpAndChannelFormDb(info))//GetIpAndChannelFormDb里面会填充Ip和Channel信息,但是没有找到摄像头的话就返回了。
                    {
                        info.Result = false;
                        info.Message = "camera == null";
                        return info;
                    } 
                }

                Log.Info(LogTags.DbGet, "info:"+ info);

                var start = info.StartTime.ToDateTime();
                var end = info.EndTime.ToDateTime();
                var file = Downloader.GetFileName(start, end);//视频文件的名称(预订)
                Log.Info(LogTags.DbGet, string.Format("start:{0},end:{1},file:{2}",start,end,file));

                if (Downloader.IsFileExist(file))//文件已经存在
                {
                    string url = Downloader.GetHlsUrl(NVSManage.RTMP_Host, file);
                    info.Url = url;
                    info.Result = true;
                    info.Message = "ExistFile";
                    Log.Info(LogTags.DbGet, string.Format("ExistFile url:{0}", url));
                }
                else
                {
                    var waitForLogin = true;

                    NVSManage.GetPlayBackFormEx(info.Ip, (form1,loginState) =>
                    {
                        Log.Info(LogTags.DbGet, string.Format("loginState:{0}", loginState));
                        if (loginState)
                        {
                            var channel = info.Channel.ToInt();
                            var r = form1.Download(channel, start, end);//有文件正在下载的情况
                            info.Result = r;
                            if (r == false)
                            {
                                Log.Error(LogTags.DbGet, form1.Message);
                                info.Message = form1.Message;
                            }
                            else
                            {
                                info.DId = form1.downloader.m_iDLTimeId;//下载用的Id,查询下载进度用
                            }
                        }
                        else
                        {
                            info.Result = false;
                            info.Message = form1.Message;
                        }
                        waitForLogin = false;
                    });

                    for (int i = 0; i < 300; i++)//等待登录结果
                    {
                        if (waitForLogin == false) break;
                        Application.DoEvents();
                        Thread.Sleep(50);//等待登录结果
                    }
                }
                Log.Info(LogTags.DbGet, string.Format("Return:{0}", info));
                return info;
            }
            catch (Exception e)
            {
                Log.Error(LogTags.DbGet, "LocationService.StartGetNVSVideo:"+ToString());
                return null;
            }
        }

        //private bool waitForLogin;

        private bool GetIpAndChannelFormDb(DownloadInfo info)
        {
            var camera = db.Dev_CameraInfos.Find(info.CId); //摄像机Id
            if (camera == null)
            {
                Log.Error(LogTags.DbGet, "camera == null");
                return false;
            }

            var rtsp = camera.RtspUrl; //"rtsp://admin:1111@192.168.108.107/13"
            Log.Info(LogTags.DbGet, "rtsp:" + rtsp);
            string[] parts = rtsp.Split('@');
            string[] parts2 = parts[1].Split('/');

            string ip = parts2[0];
            info.Ip = ip;
            string channel = parts2[1];
            info.Channel = channel;
            return true;
        }

        public DownloadProgress GetNVSProgress(DownloadInfo info)
        {
            try
            {

                Log.Info(LogTags.DbGet, "GetNVSProgress:" + info);
                if (info == null) return null;

                DownloadProgress progress = new DownloadProgress();
                progress.DId = info.DId;

                PlayBackForm form1 = NVSManage.Form;
                var downloader = form1.downloader;
                if (downloader == null)
                {
                    progress.Progress = 0;
                    progress.ProgressText = "downloader == null";
                    progress.IsFinished = false;
                }
                else
                {
                    if (downloader.m_iDLTimeId != info.DId)//当前下载的文件不是客户端申请的,多个客户端下载文件的话。
                    {
                        progress.Progress = 0;
                        progress.ProgressText = "downloader.m_iDLTimeId != info.DId";
                        progress.IsFinished = false;
                    }
                    else
                    {
                        progress.Progress = downloader.Progress;
                        progress.ProgressText = downloader.ProgressText;
                        progress.IsFinished = downloader.IsFinished;
                        if (progress.IsFinished)
                        {
                            progress.Url = downloader.GetUrl(NVSManage.RTMP_Host);
                            if (!progress.Url.StartsWith("http"))
                            {
                                Log.Error(LogTags.DbGet, progress.Url);
                            }
                            else
                            {
                                Log.Info(LogTags.DbGet, "GetNVSProgress Finished !!!!!!!!:" + progress);
                            }
                        }
                    }
                }
                Log.Info(LogTags.DbGet, "GetNVSProgress:" + progress);
                return progress;
            }
            catch (Exception e)
            {
                Log.Error("LocationService.GetNVSProgress", e.ToString());
                return null;
            }
        }

三.SDKDemo修改

1.增加了一个日志窗口

2.录像机能自动登录

3.录像机能切换登录(录像机上有两个Ip,两个ip上的通道映射到所有的摄像头)

   登录成功失败都加了回调函数

4.下载部分提取成了一个类

 

四:客户端实现(WPF)

 private DispatcherTimer timer;

        LocationServiceClient client;
        private DownloadInfo info;
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            info = new DownloadInfo();
            info.CId = TbCid.Text.ToInt();
            info.StartTime = TbStart.Text;
            info.EndTime = TbEnd.Text;
            info.Channel = TbChannel.Text;
            info.Ip = TbIp.Text;

            var r = client.StartGetNVSVideo(info);
            if (r != null)
            {
                WriteLog(r.Result+"|"+r.Message);

                if (r.Result)
                {
                    if (string.IsNullOrEmpty(r.Url))
                    {
                        WriteLog("启动计时器");
                        if (timer == null)
                        {
                            timer = new DispatcherTimer();
                            timer.Interval = TimeSpan.FromMilliseconds(100);
                            timer.Tick += Timer_Tick;
                        }
                        timer.Start();
                    }
                    else
                    {
                        MessageBox.Show("已经下载过:" + r.Url);
                    }
                }
                else
                {
                    MessageBox.Show("下载错误:" + r.Message);
                }
            }
            else
            {
                MessageBox.Show("结果为空");
            }
        }

        private string _log = "";

        private void WriteLog(string log)
        {
            string txt = string.Format("[{0}]{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), log);
            _log = txt + "\n" + _log;
            TbResult.Text = _log;
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            var progress = client.GetNVSProgress(info);
            if (progress != null)
            {
                WriteLog("p:"+progress.Progress);
                ProgressBar1.Value = progress.Progress;
                if (progress.IsFinished)
                {
                    timer.Stop();
                    WriteLog("下载完成:" + progress.Url);
                    MessageBox.Show("下载完成:"+ progress.Url);
                    
                }
            }
            else
            {

                timer.Stop();
                MessageBox.Show("进度为空");
            }

        }

五:客户端实现(Unity)

基于ump的demo改造的

using System;
using System.Collections;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using UMP;
using UnityEngine;
using UnityEngine.UI;
using WCFServiceForWPF.LocationServices;

public class NVSPlayerClient : MonoBehaviour
{

    public InputField TbCid;

    public InputField TbIp;
    public InputField TbChannel;

    public InputField TbStart;

    public InputField TbEnd;

    public InputField TbURL;

    public UniversalMediaPlayer Player;

    public Toggle CbIsFinished;

    public Slider Slider1;

    public Text restul;

    public string ip = "127.0.0.1";
    public string port = "8733";

    private LocationServiceClient client;

    public LocationServiceClient CreateServiceClient()
    {
        string hostName = ip;
        string portNum = port;
        Binding wsBinding = new BasicHttpBinding();
        //Binding wsBinding = new WSHttpBinding();
        string url =
            string.Format("http://{0}:{1}/LocationService/",
                hostName, portNum);
        Debug.Log("Create Service Client:" + url);

        LocationServiceClient client = null;
        try
        {
            EndpointAddress endpointAddress = new EndpointAddress(url);
            Debug.Log("endpointAddress:" + endpointAddress);
            client = new LocationServiceClient(wsBinding, endpointAddress);
            Debug.Log("client:" + client);
        }
        catch
        {
            Debug.LogError("CreateServiceClient报错了!");
            return null;
        }

        return client;
    }

    private DownloadInfo info;

    public void Play()
    {
        info = new DownloadInfo();
        info.CId = int.Parse(TbCid.text);
        info.StartTime = TbStart.text;
        info.EndTime = TbEnd.text;
        info.Channel = TbChannel.text;
        info.Ip = TbIp.text;

        var r = client.StartGetNVSVideo(info);//开始下载视频
        if (r != null)
        {
            WriteLog(r.Result + "|" + r.Message+"|"+r.Url);

            if (r.Result)
            {
                if (string.IsNullOrEmpty(r.Url))
                {
                    InvokeRepeating("GetProgress", 0, 1);//开始获取下载进度
                }
                else
                {
                    Play(r.Url);//已经查询并下载成功了的时间段
                }
            }
            else
            {
                if (r.Message == "It is downloading!")//有文件在下载
                {
                    //todo:等待,休眠1s,并重新尝试下载。重试次数10次,还是这样则提示,并不重试。
                }
                else
                {
                    //todo:提示Message内容
                }
            }
        }
        else
        {
            WriteLog("结果为空");
        }
    }

    private string _log;

    private void WriteLog(string log)
    {
        string txt = string.Format("[{0}]{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), log);
        _log = txt + "\n" + _log;
        restul.text = _log;
        Debug.Log(log);
    }

    public void GetProgress()
    {
        var progress = client.GetNVSProgress(info);
        if (progress != null)
        {
            //TbResult.Text = progress.ToString();
            //ProgressBar1.Value = progress.Progress;

            Slider1.value = progress.Progress;
            WriteLog(progress.ProgressText);
            if (progress.IsFinished)
            {
               CancelInvoke("GetProgress");
               WriteLog("下载完成:"+progress.Url);
               Play(progress.Url);
            }
        }
        else
        {
            CancelInvoke("GetProgress");
            WriteLog("进度为空");
        }
    }

    private void Play(string url)
    {
        TbURL.text = url;

        Player.Path = url;
        Player.Play();
    }

	// Use this for initialization
    void Start()
    {
        Debug.Log("Start" );
        client = CreateServiceClient();
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.UserName = "Admin";
        loginInfo.Password = "Admin@123456";
        Debug.Log("loginInfo:" + loginInfo);
        var r = client.Login(loginInfo);
        Debug.Log("r:"+ r);
        WriteLog(r.Result + "|" + r.Authority+"|"+r.Session);
    }

    // Update is called once per frame
	void Update () {
		
	}
}

六:遗留问题

  1.多客户端访问

  2.大时间段下载

  3.缓存清理

  4.提前下载缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值