下面我们来讲解一下关于EasyPlayerPro接口的调用,主要分为C++和C#两种语言,C++也可以基于VC和QT进行开发,C++以VC MFC框架为例进行讲解,C#以Winform框架为例进行讲解。

  1. VC开发EasyPlayerPro

    首先建一个基于MFC Dialog的工程,取名叫EasyPlayerPro,关于界面逻辑的处理过程就不做过多赘述了,大家有兴趣的可以去看EasyPlayerPro项目代码;下面我们讲解一下EasyPlayerPro的调用流程:

    (1) 打开一个流或文件进行播放

    通过EasyPlayerPro_Open打开一个流或者本地文件,打开以后即播放,不需要调用EasyPlayerPro_Play方法,调用完成后,注意,比如拉网络流的时候,由于Open函数是非阻塞而立即返回的,所以,播放过程可能尚未初始化完成,从而获取流的信息可能获取不到,正确的做法是在线程或者计时器里面轮询获取;Open完成后,我们可以对一些参数进行设置,比如设置OSD和图片叠加,显示模式,音量大小等:

    // player open file
m_player = EasyPlayerPro_Open(str, m_stcVideoWnd->GetSafeHwnd());
if (m_player)
{
m_bPlayPause = FALSE;
SetTimer(TIMER_ID_PROGRESS, 1000, NULL); m_bOpening = TRUE; //字幕和图片叠加
//
// EasyPlayerPro_SetLogo 设置台标/LOGO
// player - 指向 EasyPlayerPro_Open 返回的 player 对象
// bIsUse - 是否使用水印 1=启用 0=不启用
// ePos - 台标位置:1==leftttop 2==righttop 3==leftbottom 4==rightbottom
// eStyle - 水印的风格,见WATERMARK_ENTRY_TYPE声明
// x - 水印左上角位置x坐标
// y - 水印左上角位置y坐标
// width - 宽
// height - 高
// logopath - 水印图片路径
EasyPlayerPro_SetLogo (m_player, 1, 2, 3,
0, 0, 0, 0, "C:\\Dingshuai\\Project\\Easylogo.png"); // EasyPlayerPro_SetOSD 设置叠加字幕
// player - 指向 EasyPlayerPro_Open 返回的 player 对象
// bIsUse - 是否使用水印 1=启用 0=不启用 -1=删除
// nMoveType - 移动类型:0--固定位置,1--从左往右,2--从右往左,
// R,G,B - 字体颜色对应三个分量红绿蓝0-255
// x - 字幕显示左上角位置x坐标
// y - 字幕显示左上角位置y坐标
// weight - 字体权重,见如下声明
// /* Font Weights */
// #define FW_DONTCARE 0
// #define FW_THIN 100
// #define FW_EXTRALIGHT 200
// #define FW_LIGHT 300
// #define FW_NORMAL 400
// #define FW_MEDIUM 500
// #define FW_SEMIBOLD 600
// #define FW_BOLD 700
// #define FW_EXTRABOLD 800
// #define FW_HEAVY 900
// #define FW_ULTRALIGHT FW_EXTRALIGHT
// #define FW_REGULAR FW_NORMAL
// #define FW_DEMIBOLD FW_SEMIBOLD
// #define FW_ULTRABOLD FW_EXTRABOLD
// #define FW_BLACK FW_HEA
// width - 宽
// height - 高
// fontname - 字体名称,如“宋体”“楷体”“隶书”“华文行楷”......
// tittleContent - OSD显示内容
EasyPlayerPro_SetOSD (m_player, 1, 1, 0, 255, 0,
700, 100, 200, 0, -29, "隶书", "你说你爱了不该爱的人,你的心中满是伤痕!");
}

(2) 暂停和单步播放

void CplayerDlg::OnBnClickedBtnPause()
{
// TODO: 在此添加控件通知处理程序代码
if (!m_bPlayPause) EasyPlayerPro_Pause(m_player);
else EasyPlayerPro_Play(m_player);
m_bPlayPause = !m_bPlayPause;
CSkinButton* pBtn = (CSkinButton*)GetItemByName(_T("Pause"));
if(pBtn)
{
if (m_bPlayPause)
{
pBtn->SetBtnText(_T("播放"));
}
else
{
pBtn->SetBtnText(_T("暂停"));
}
}
} void CplayerDlg::OnBnClickedBtnPlayByFrame()
{
// TODO: 在此添加控件通知处理程序代码
//
EasyPlayerPro_StepPlay(m_player);
m_bPlayPause = TRUE;
CSkinButton* pBtn = (CSkinButton*)GetItemByName(_T("Pause"));
if(pBtn)
{
if (m_bPlayPause)
{
pBtn->SetBtnText(_T("播放"));
}
else
{
pBtn->SetBtnText(_T("暂停"));
}
}
}

这里直接调用即可,不做过多赘述。

(3) 快放和慢放

void CplayerDlg::OnBnClickedBtnRatePlay()
{ int nRate = 0;
switch(m_speedRate)
{
case SPEED_SLOW_X4:
nRate = 25;
break;
case SPEED_SLOW_X2:
nRate = 50;
break;
case SPEED_NORMAL:
nRate = 100;
break;
case SPEED_FAST_X2:
nRate = 200;
break;
case SPEED_FAST_X4:
nRate = 300;
break;
case SPEED_FAST_X8:
nRate = 400;
break;
case SPEED_FAST_X16:
nRate = 500;
break;
case SPEED_FAST_X64:
nRate = 600;
break; }
EasyPlayerPro_Setparam(m_player, EASY_PARAM_PLAY_SPEED, &nRate);
}

目前定义慢放范围为2倍和4倍,快放范围为2,4,8,16,64倍,超过这个范围则无明显反应或者意义。

(4) 抓图接口调用

void CplayerDlg::OnBnClickedBtnSnapshot()
{
// TODO: 在此添加控件通知处理程序代码
//
TCHAR sPath[512];
memset(sPath, 0x00, sizeof(TCHAR) * 512);
GetWorkDirectory(sPath, 512); int nPathLen = _tcslen(sPath); if ((sPath[nPathLen - 1] != '/' && sPath[nPathLen - 1] != '\\'))
{
sPath[nPathLen] = '\\';
} unsigned int timestamp = (unsigned int)time(NULL);
time_t tt = timestamp;
struct tm _time;
::localtime_s(&_time, &tt);
char szTime[64] = { 0, };
strftime(szTime, 32, "\\pic_%Y%m%d%H%M%S.jpg", &_time); CString strTime = (CString)szTime; CString sScreenPath = _T("");
sScreenPath.Format(_T("%s%s"), sPath, _T("ScreenShot"));
bool bSec = EnsureDirExist(sScreenPath);
sScreenPath += strTime; USES_CONVERSION; EasyPlayerPro_Snapshot(m_player, T2A(sScreenPath), 0, 0, 1000); }

抓图接口直接调用即可,注意保存的路径需要存在,否则,抓图保存将会失败。

(5) 录像接口调用

void CplayerDlg::OnBnClickedBtnRecord()
{
// TODO: 在此添加控件通知处理程序代码
if(!m_player)
return ;
CSkinButton* pBtn = (CSkinButton*)GetItemByName(_T("Record"));
if (!pBtn)
{
return;
} if (!m_bRecording)
{
pBtn->SetBtnText(_T("停止录像")); TCHAR sPath[512];
memset(sPath, 0x00, sizeof(TCHAR)*512);
GetWorkDirectory(sPath, 512); int nRecordPathLen = _tcslen(sPath); if ((sPath[nRecordPathLen - 1] != '/' && sPath[nRecordPathLen - 1] != '\\'))
{
sPath[nRecordPathLen] = '\\';
} unsigned int timestamp = (unsigned int)time(NULL);
time_t tt = timestamp;
struct tm _time;
::localtime_s(&_time, &tt);
char szTime[64] = { 0, };
strftime(szTime, 32, "\\record_%Y%m%d%H%M%S.mp4", &_time); CString strTime = (CString)szTime; CString sRecordPath = _T("");
sRecordPath.Format(_T("%s%s"), sPath, _T("Record"));
bool bSec = EnsureDirExist(sRecordPath);
sRecordPath += strTime; UpdateData(TRUE);
CString sRecDuration = _T("");
if(m_editRecPieceTime)
m_editRecPieceTime->GetWindowText(sRecDuration);
int nDuration = _ttoi( sRecDuration.GetBuffer()); //m_SNPlayOcx.EasyPlayPro_PlayOcx_Record(sRecordPath, m_sRtspUrl, nDuration);
//m_SNPlayOcx.EasyPlayPro_PlayOcx_Record(_T("D:\\test.mp4"), m_sRtspUrl);
USES_CONVERSION;
EasyPlayerPro_Record(m_player, T2A(sRecordPath), nDuration); m_lRecordTime = 0;//IDC_STATIC_RECORD_STATUS
SetTimer(TIMER_RECORD_STATUS, 300, NULL);
}
else
{
pBtn->SetBtnText(_T("录像"));
EasyPlayerPro_Stoprecord(m_player); KillTimer(TIMER_RECORD_STATUS); EasyPlayerPro_Getparam(m_player, EASY_PARAM_RECORD_TIME, &m_lRecordTime);
EasyPlayerPro_Getparam(m_player, EASY_PARAM_RECORD_PIECE_ID, &m_lRecordSliceUp);
int thh, tmm, tss = 0;
thh = m_lRecordTime / 3600;
tmm = (m_lRecordTime % 3600) / 60;
tss = (m_lRecordTime % 60); CString sShowRec = _T("");
if (m_lRecordSliceUp > -1)
sShowRec.Format(_T("录像已停止 录制时间:%02d:%02d:%02d 切片ID:%d"), thh, tmm, tss, m_lRecordSliceUp);
else
sShowRec.Format(_T("录像已停止 录制时间:%02d:%02d:%02d"), thh, tmm, tss); SetString(4, sShowRec); m_lRecordTime = 0;//IDC_STATIC_RECORD_STATUS
}
m_bRecording = !m_bRecording;
}

EasyPlayPro_PlayOcx_Record接口调用进行录像,EasyPlayerPro_Stoprecord接口调用停止录像,EasyPlayerPro_Getparam接口获取录像的时间和当前录像的PieceId, 具体参数见上一篇文章EasyPlayerPro接口说明

(6) 本地文件和点播拖拽

 a. 进度显示计时
    case TIMER_ID_PROGRESS://进度条计时器
{
#if 1
if (m_totalDuration <= 0)
{
LONGLONG ltotal = 0;
EasyPlayerPro_Getparam(m_player, EASY_PARAM_MEDIA_DURATION, &ltotal);
if (ltotal>1)
{
m_totalDuration = ltotal/1000;
int totalSeconds = (int)m_totalDuration;
int gTotalSeconds = totalSeconds;
int gTotalMinute = (int)(totalSeconds / 60);
int nTotalHour = (int)(gTotalMinute / 60); //时
int nTotalMinute = (int)(gTotalMinute % 60);//分
int totalSecond = (int)(totalSeconds % 60); //秒 m_strPlayFileTime.Format(_T("%02d:%02d:%02d"), nTotalHour, nTotalMinute, totalSecond);
if (m_sliderPlay)
{
m_sliderPlay->SetRange(0, m_totalDuration);
m_sliderPlay->SetPos(0);
}
m_sliderPlay->EnableWindow(TRUE);
}
} LONGLONG llCurPos = 0;
LONGLONG llPos = 0;
EasyPlayerPro_Getparam(m_player, EASY_PARAM_MEDIA_POSITION, &llPos);
llCurPos = llPos/1000;
TRACE("Position == %d\r\n",llCurPos);
int totalSeconds = (int)llCurPos;
int gTotalSeconds = totalSeconds;
int gTotalMinute = (int)(totalSeconds / 60);
int nTotalHour = (int)(gTotalMinute / 60); //时
int nTotalMinute = (int)(gTotalMinute % 60);//分
int totalSecond = (int)(totalSeconds % 60); //秒
CString strTemp = _T(""); if (m_totalDuration>0 )
{
if (llCurPos<m_totalDuration)
{
strTemp.Format(_T("%02d:%02d:%02d/%s"), nTotalHour, nTotalMinute, totalSecond, m_strPlayFileTime);
if (m_sliderPlay)
{
m_sliderPlay->SetPos(llCurPos);
}
}
else
{
#if 0
KillTimer(TIMER_ID_PROGRESS);
PlayerCloseFile();
SetString(2,_T(""));
m_totalDuration = -1;
m_sliderPlay->SetRange(0, 2000);
m_sliderPlay->SetPos(0);
m_speedRate = 0;
#endif
OnBnClickedBtnClose();
strTemp = _T("");
}
}
else
strTemp.Format(_T("%02d:%02d:%02d/../../.."), nTotalHour, nTotalMinute, totalSecond);
SetString(2,strTemp);
#endif
}
break;

b. 拖拽进度条OnHScroll消息处理

    if (m_sliderPlay==pSliderTmp)
{
if (nSBCode == 5)
{
int nPos = m_sliderPlay->GetPos();
TRACE("nPos==%d\r\n", nPos);
//如果处于断点循环
#if 0
if (m_bLoopAB)
{
if(nPos<m_dbBreakPtA || nPos>m_dbBreakPtB)
{
nPos = m_dbBreakPtA;
}
}
#endif
if (m_totalDuration>0)
{
EasyPlayerPro_Seek(m_player, nPos*1000);
}
}
}

c. 音量调节进度条OnHScroll消息处理

    else if (m_sliderSound == pSliderTmp)//音量调节
{
int nValue = m_sliderSound->GetPos();
nValue -= 255;
EasyPlayerPro_Setparam(m_player, EASY_PARAM_AUDIO_VOLUME, &nValue);
}
  1. C#开发EasyPlayerPro

C#我真不擅长,故此,只对libEasyPlayerPro的调用做简单介绍;

首先,创建一个Winform程序(类似于MFC的Dialog程序),然后导入 libeasyplayerpro.dll,生成实体类,即可调用接口。

(1) libeasyplayerpro.dll接口类化

导入dll,生产类,声明需要用到的参数列表如下:

        public enum tagEASY_PARAM_ID
{
//++ public
// duration & position
PARAM_MEDIA_DURATION = 0x1000,
PARAM_MEDIA_POSITION, // media detail info
PARAM_VIDEO_WIDTH,
PARAM_VIDEO_HEIGHT, // video display mode
PARAM_VIDEO_MODE, // audio volume control
PARAM_AUDIO_VOLUME, // playback speed control
PARAM_PLAY_SPEED, // video decode thread count
PARAM_DECODE_THREAD_COUNT, // visual effect mode
PARAM_VISUAL_EFFECT, // audio/video sync diff
PARAM_AVSYNC_TIME_DIFF, // player event callback
PARAM_PLAYER_CALLBACK, // audio/video stream
PARAM_AUDIO_STREAM_TOTAL,
PARAM_VIDEO_STREAM_TOTAL,
PARAM_SUBTITLE_STREAM_TOTAL,
PARAM_AUDIO_STREAM_CUR,
PARAM_VIDEO_STREAM_CUR,
PARAM_SUBTITLE_STREAM_CUR,
//-- public //++ for adev
PARAM_ADEV_RENDER_TYPE = 0x2000,
//-- for adev //++ for vdev
PARAM_VDEV_RENDER_TYPE = 0x3000,
PARAM_VDEV_FRAME_RATE,
//-- for vdev //++ for render
PARAM_RENDER_UPDATE = 0x4000,
PARAM_RENDER_START_PTS,
//-- for render
};

声明Easyplayerpro接口如下:

        //初始化播放视频
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Open", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr EasyPlayerPro_Open(string file, IntPtr hwnd); //关闭视频
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Close", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Close(IntPtr player); //播放视频
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Play", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Play(IntPtr player); //单针播放视频
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_StepPlay", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_StepPlay(IntPtr player); //暂停视频
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Pause", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Pause(IntPtr player); //设置时长
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Seek", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Seek(IntPtr player, long ms); //设置窗口
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Resize", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Resize(IntPtr player, int type, int x, int y, int w, int h); //截图
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Snapshot", CallingConvention = CallingConvention.Cdecl)]
static extern int EasyPlayerPro_Snapshot(IntPtr player, string file, int w, int h, int wait); //设置参数
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Setparam", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Setparam(IntPtr player, uint id, ref IntPtr param); //得到参数
[DllImport("libEasyplayerpro.dll", EntryPoint = "EasyPlayerPro_Getparam", CallingConvention = CallingConvention.Cdecl)]
static extern void EasyPlayerPro_Getparam(IntPtr player, uint id, ref IntPtr param);

声明一个指针变量用于存放播放器指针:

private IntPtr mPlayer;

创建一个按钮,点击消息处理:

    private void button1_Click(object sender, EventArgs e)
{ EasyPlayerPro_Open("rtmp://live.hkstv.hk.lxdns.com/live/hks", panel1.Handle);
}

其中,panel1是创建的一个pannel,用于显示视频的窗口;

这样,其他接口调用也类似,具体可参考C++的调用流程,这里不做过多赘述;

关于EasyPlayerPro

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

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

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

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Copyright © EasyDarwin.org 2012-2017

EasyPlayerPro(Windows)流媒体播放器开发之跨语言调用的更多相关文章

  1. EasyPlayerPro(Windows)流媒体播放器开发之框架讲解

    EasyPlayerPro for Windows是基于ffmpeg进行开发的全功能播放器,开发过程中参考了很多开源的播放器,诸如vlc和ffplay等,其中最强大的莫过于vlc,但是鉴于vlc框架过 ...

  2. EasyPlayerPro(Windows)流媒体播放器开发之接口设计

    EasyPlayerPro(windows)接口说明如下: EasyPlayerPro_Open 说明:打开一个媒体流或者媒体文件进行播放,同时返回一个 player 对象指针 参数说明: fileU ...

  3. EasyPlayerPro(Windows)流媒体播放器功能介绍及应用场景

    EasyPLyerPro(Windows)经过为期一个月的开发已经基本完成,虽然目前仍存在一些小问题,但是总体功能还是趋于比较稳定和强大的,下面对其功能和应用场景做简要介绍. 一.EasyPlayer ...

  4. EasyPlayerPro(Windows)流媒体播放器开发之ffmpeg log输出报错

    EasyPlayerPro主要基于ffmpeg进行开发,在EasyPlayerPro开发过程中,曾遇到一个相对比较棘手的问题,该问题一般在播放不是很标准的流或者网络情况较差,容易出现丢帧的情况特别容易 ...

  5. EasyPlayerPro Windows流媒体播放器(RTSP/RTMP/HTTP/HLS/File/TCP/RTP/UDP都能播)发布啦

    EasyPlayerPro简介 EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放.支持本地文件播放,支持本地 ...

  6. Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用

    目录: 一.什么是Thrift? 1) Thrift内部框架一瞥 2) 支持的数据传输格式.数据传输方式和服务模型 3) Thrift IDL 二.Thrift的官方网站在哪里? 三.在哪里下载?需要 ...

  7. vs2019 Com组件初探-简单的COM编写以及实现跨语言调用

    前提条件 1.掌握C++基础语法 2.平台安装 vs2019 3.本地平台为 windows 10 1909 X64 4.了解vbs基础语法 本次目标 1.掌握Com组件的概念及原理 2.编写一个简单 ...

  8. Golang通过Thrift框架完美实现跨语言调用

    每种语言都有自己最擅长的领域,Golang 最适合的领域就是服务器端程序. 做为服务器端程序,需要考虑性能同时也要考虑与各种语言之间方便的通讯.采用http协议简单,但性能不高.采用TCP通讯,则需要 ...

  9. 跨语言调用Hangfire定时作业服务

    跨语言调用Hangfire定时作业服务 背景 Hangfire允许您以非常简单但可靠的方式执行后台定时任务的工作.内置对任务的可视化操作.非常方便. 但令人遗憾的是普遍都是业务代码和hagnfire服 ...

随机推荐

  1. react native windows create bundle folder

    生成bundle 文件 命令 react-native bundle --platform android --dev false --entry-file index.js --bundle-out ...

  2. Codeforces 762A k-th divisor(数论)

    题目链接:k-th divisor 求出N的第K大因子,满足N <= 10^15,K <= 10^9 直接暴力…… #include <bits/stdc++.h> using ...

  3. Artix : Arch拥抱OpenRC 使用笔记

    轻量桌面Archlinux用户逃离systemd,拥抱Gentoo的openrc. 镜像源:官方镜像源非常慢,曾经一度体验artix后就放弃了,后来发现了清华和腾讯云的镜像,速度非常快,现在又重新安装 ...

  4. CMake的应用(在vision studio2008中去掉 ALL_BUILD 和 ZERO_CHECK)

    from  http://blog.csdn.net/jtop0/article/details/6167432 一般由CMake是 跨平台软件开发和维护过程的 工程构建工具.“在每个系统构建你的工程 ...

  5. Delphi 释放数组中的数据

    FillChar(aryTest[Low(aryTest)],    Length(aryTest) * SizeOf(aryTest[Low(aryTest)]), 0);

  6. Android BroadcastReceiver 注册和反注册

    说起来这个问题很简单,只要注册和反注册成对出现就行,好像很多教材都是如此介绍.但实际开发中,对广播注册和反注册的时机把握还是很重要的. 关于广BroadcastReceiver注册和反注册时机,主要有 ...

  7. (转)python装饰器二

    Python装饰器进阶之二 保存被装饰方法的元数据 什么是方法的元数据 举个栗子 def hello(): print('Hello, World.') print(dir(hello)) 结果如下: ...

  8. SVN切分支步骤

    1.右键project选择Brankch/Tag 2.选择SVN路径并在改路径下填写project名称 3.选择最新版本号 4.填写必要的凝视备忘,方便日后查看 5.刷新父文件夹文件夹.下载被切出来的 ...

  9. [C++设计模式] state 状态模式

    <head first 设计模式>中的样例非常不错,想制造一个自己主动交易的糖果机,糖果机有四个状态:投入钱不足,投入钱足够,出售糖果,糖果售罄. 糖果机的当前状态处于当中不同的状态时,它 ...

  10. axios 异步加载 导致 {{}} 中变量为 undefined 报错 的 解决方案

    情景:axios 异步加载数据,当返回数据为一个 数组 时,双花括号中 这样写 会报错 {{informationDetail[0].img}} 解决方案一:通过 v-if 进行判断 解决方案二:单独 ...