EasyPlayerPro-win即时回放功能实现

来源:互联网 发布:2016网络伤感歌曲大全 编辑:程序博客网 时间:2024/06/04 18:18

EasyPlayerPro-win即时回放功能实现

背景描述

参照国内视频监控行业监控软件,实现当前视频的即时回放功能;
例如: 监控人员发现刚刚的某个视频点有可疑,就像录像回放一样,想倒回去看一下,但又不想切换到录像回放界面, 此处就体现即时回放的价值了; 还可将回放片断保存为录像文件;

实现流程

在视频播放时, 将收到的帧数据写入待解码播放队列;
当用户切换到即时回放功能, 则停止解码当前的帧;
在解码线程中修改用者ID(涉及到缓冲队列的设计);
解码线程一直读取历史队列中的帧进行解码显示;
当读到队列的最后一帧时,再从头开始循环;

这里写图片描述

代码实现

//即时回放处理: 将当前正在播放的缓冲队列中的数据,拷贝到即时回放队列, 然后从即时回放队列中读取数据进行回放int ChannelManager::InstantReplayProcess(MEDIA_VIDEO_CHANNEL_OBJ_T *pMediaChannel, CONSUMER_HANDLE *handle,                     BUFFER_TYPE_ENUM *bufferType, int *headerSize, char *headerData, int *payloadSize, char *payloadData){if (NULL == pMediaChannel)      return -1;int     ret = -1;CONSUMER_HANDLE consumerHandle = *handle;if (NULL == pMediaChannel->pInstantReplay)      return -1;if ( pMediaChannel->pInstantReplay->instantReplay == 0x01 ){    if (NULL == pMediaChannel->pInstantReplay->bufQueueHandle)      //创建即时回放缓冲队列    {        //创建即时回放缓冲区        int queueSize = pMediaChannel->pSourcePtr->GetQueueSize();        BUFQUE_Create(&pMediaChannel->pInstantReplay->bufQueueHandle, 0, NULL, queueSize, MAX_PRE_RECORDING_SECS, 0, 1);        //此处将sourcePtr中的bufqueue拷贝到 即时回放中的缓冲区        CONSUMER_HANDLE consumerHandleInstantReplay = BUFQUE_RegisterConsumer(pMediaChannel->pInstantReplay->bufQueueHandle,                                                                                 (unsigned int)pMediaChannel, 0x00);        if (NULL == consumerHandleInstantReplay)        {            _TRACE(TRACE_LOG_DEBUG, "channel[%d]注册即时回放调用者失败.\n", pMediaChannel->id);            BUFQUE_Release(&pMediaChannel->pInstantReplay->bufQueueHandle);            return ret;        }        *handle = consumerHandleInstantReplay;        consumerHandle = consumerHandleInstantReplay;        pMediaChannel->pInstantReplay->consumerHandle = BUFQUE_RegisterConsumer(pMediaChannel->pInstantReplay->bufQueueHandle,                                                                             (unsigned int)pMediaChannel->pInstantReplay,                                                                             0x00);  //再注册一个,用于和consumerHandleInstantReplay循环使用        pMediaChannel->pInstantReplay->frameNum = 0;        pMediaChannel->pInstantReplay->frameNo  = 0;        BUFFER_TYPE_ENUM    bufferType = BUFFER_TYPE_UNKNOWN;        CONSUMER_HANDLE     consumerHandleTmp = NULL;        consumerHandleTmp = pMediaChannel->pSourcePtr->RegisterConsumer((unsigned int)&pMediaChannel->pInstantReplay, 0x01);        //从当前正在播放的缓冲队列中,拷贝数据到即时回放队列        if (NULL != consumerHandleTmp)        {            int     headerSize = 0;            EASY_FRAME_INFO     tmpFrameInfo;            memset(&tmpFrameInfo, 0x00, sizeof(EASY_FRAME_INFO));            BUFF_T      buffSource;            memset(&buffSource, 0x00, sizeof(BUFF_T));            BUFF_MALLOC(&buffSource, MAX_ENCODE_FRAME_SIZE);            //最大编码帧大小为MAX_ENCODE_FRAME_SIZE(1024*1024)            int     writeKeyFrame = 0x00;            int     bufferId = 0;            do            {                //从队列中获取音视频和事件数据                bufferType = BUFFER_TYPE_UNKNOWN;                if (0 != pMediaChannel->pSourcePtr->GetSourceData(consumerHandleTmp, NULL, &bufferType,                                             &headerSize, (char *)&tmpFrameInfo, &buffSource.bufpos, buffSource.pbuf, 0x01))                {                    break;                }                //保证第一帧为视频关键帧                if (writeKeyFrame == 0x01 || ( BUFFER_TYPE_VIDEO == bufferType && tmpFrameInfo.type == FRAME_TYPE_I) )                {                    BUFQUE_AddData(pMediaChannel->pInstantReplay->bufQueueHandle, ++bufferId, bufferType, headerSize, (char *)&tmpFrameInfo, buffSource.bufpos, buffSource.pbuf);                    writeKeyFrame = 0x01;                    pMediaChannel->pInstantReplay->frameNum ++;                    //pMediaChannel->pInstantReplay->frameNo = 0;                }            }while (1);            BUFF_FREE(&buffSource);            pMediaChannel->pSourcePtr->UnRegisterConsumer(&consumerHandleTmp);        }    }    //当前对即时回放队列进行录像    if (pMediaChannel->pInstantReplay->recording == 0x01)    {        pMediaChannel->pInstantReplay->recording = 0x00;        InstantReplayRecording(pMediaChannel);              //即时回放录像    }    if (pMediaChannel->pInstantReplay->status==PLAY_SPEED_PAUSED)    {        if (pMediaChannel->pInstantReplay->instantReplay == 0x00)       //暂停状态时, 上层已调用关闭即时回放        {            if (NULL != pMediaChannel->pInstantReplay->bufQueueHandle)            {                if (NULL != consumerHandle)                {                    BUFQUE_UnRegisterConsumer(pMediaChannel->pInstantReplay->bufQueueHandle, &consumerHandle);                    *handle = NULL;                }                if (NULL != pMediaChannel->pInstantReplay->consumerHandle)                {                    BUFQUE_UnRegisterConsumer(pMediaChannel->pInstantReplay->bufQueueHandle, &pMediaChannel->pInstantReplay->consumerHandle);                }                BUFQUE_Release(&pMediaChannel->pInstantReplay->bufQueueHandle);            }            delete pMediaChannel->pInstantReplay;            pMediaChannel->pInstantReplay = NULL;        }        return 0;    }    ret = BUFQUE_GetData(pMediaChannel->pInstantReplay->bufQueueHandle, consumerHandle, NULL, bufferType, headerSize, headerData, payloadSize, payloadData, 0x01);    if (ret < 0)    {        BUFQUE_CopyConsumer(pMediaChannel->pInstantReplay->bufQueueHandle, consumerHandle, pMediaChannel->pInstantReplay->consumerHandle);        ret = BUFQUE_GetData(pMediaChannel->pInstantReplay->bufQueueHandle, consumerHandle, NULL, bufferType, headerSize, headerData, payloadSize, payloadData, 0x01);        if (ret == 0x00)            pMediaChannel->pInstantReplay->frameNo = 1;        else                pMediaChannel->pInstantReplay->frameNo = 0;    }    else if (ret == 0 && *bufferType==BUFFER_TYPE_VIDEO)    {        pMediaChannel->pInstantReplay->frameNo ++;    }}else if (pMediaChannel->pInstantReplay->instantReplay == 0x00)      //关闭即时回放{    if (NULL != pMediaChannel->pInstantReplay->bufQueueHandle)    {        if (NULL != consumerHandle)        {            BUFQUE_UnRegisterConsumer(pMediaChannel->pInstantReplay->bufQueueHandle, &consumerHandle);            *handle = NULL;        }        if (NULL != pMediaChannel->pInstantReplay->consumerHandle)        {            BUFQUE_UnRegisterConsumer(pMediaChannel->pInstantReplay->bufQueueHandle, &pMediaChannel->pInstantReplay->consumerHandle);        }        BUFQUE_Release(&pMediaChannel->pInstantReplay->bufQueueHandle);    }    delete pMediaChannel->pInstantReplay;    pMediaChannel->pInstantReplay = NULL;    ret = 100;}return ret;}

关于EasyPlayerPro

EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP、RTMP、HTTP、HLS、UDP、RTP、File等多种流媒体协议播放、支持本地文件播放,支持本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种功能特性,核心基于ffmpeg,稳定、高效、可靠、可控,支持Windows、Android、iOS三个平台,目前在多家教育、安防、行业型公司,都得到的应用,广受好评!

EasyPlayerPro:https://github.com/EasyDSS/EasyPlayerPro

点击链接加入群【EasyPlayer & EasyPlayerPro】:544917793

技术支持

  • 邮件:support@easydarwin.org

  • QQ交流群:544917793

EasyPlayerPro是一款非常稳定的全协议/全功能播放器组件,可以通过以上渠道进行更深入的技术与合作咨询;

获取更多信息

EasyDarwin开源流媒体服务器:www.EasyDarwin.org

EasyDSS商用流媒体解决方案:www.EasyDSS.com

EasyNVR无插件直播方案:www.EasyNVR.com

Copyright © EasyDarwin Team 2012-2017

EasyDarwin

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 建滔焦化 同泰焦化 焦化捣固机 焦化招聘 正大焦化 焦化工艺 焦化消泡剂 傅山焦化 山西焦化股票 山西焦化股吧 600740山西焦化 焦化厂工艺流程 新泰焦化厂招工简介楼德 山西焦化资金流向 陕西黑猫焦化股份有限公司 山西焦化集团有限公司 焦化厂是干什么的 邢台旭阳焦化招聘 北京焦化厂搬迁 旭阳焦化有限公司 旭阳焦化集团有限公司 焦化用消泡剂 旭阳焦化集团 焦化行业准入 煤焦化产业链 河北中煤旭阳焦化有限公司 焦圈 焦圈和油条的区别 北京焦圈 末世之焦土绿洲 焦土政策 焦土之城 焦土战术 焦土 外焦里嫩 茄子怎么炸外焦里嫩 烧茄子怎么做外焦里嫩 焦大 焦姣 焦字组词 焦家家谱28个字辈