开发指南

1 开发准备

开始前请确保下述前提条件已准备就绪:

解压后 SDK 包的 libs 文件夹中,包含了 dll 库文件和头文件,文件列表如下:

libs
├── lib
│   ├── SDL2.dll
│   ├── avcodec-57.dll
│   ├── avdevice-57.dll
│   ├── avfilter-6.dll
│   ├── avformat-57.dll
│   ├── avutil-55.dll
│   ├── swresample-2.dll
│   ├── swscale-4.dll
│   ├── libcrypto-1_1.dll
│   ├── libssl-1_1.dll
│   ├── msvcp120.dll
│   ├── msvcr120.dll
│   ├── NELivePlayer.dll
│   ├── NELivePlayer.lib
├── include
│   ├── nelp_api.h
│   ├── nelp_define.h
│   ├── nelp_type.h
└──

总体接口约定
SDK 提供的API C类型接口,分别提供 win32 的动态库 NELivePlayer.dll及其对应的导入库 NELivePlayer.lib 方便开发者动态加载或者加载 SDK 库文件。 App 开发者只需要引用 SDK 包里 sdk\include 目录下的头文件即可。关于API类或者函数的定义,可以查看API 文档。

2 集成 SDK

本文介绍sdk接入的整个流程,可在网易云视频官网下载最新的播放器Windows Demo,来查看更多的实现细节。

2.1 导入头文件和库文件

(1)导入库文件
将 SDK 相关的 dll 文件放到App 的运行目录下。SDK 基于vs2013 开发,如果App 没有对应的运行时库文件(msvcp120.dllmsvcr120.dll),请将其放到App 的运行目录下。

(2)引用头文件
由于nelp_api.h里面会引用nelp_type.hnelp_define.h两个头文件,所以开发者只需导入nelp_api.h即可,但是三个头文件需要放在同一目录下,如下所示:

#include "nelp_api.h"

2.2 实现播放功能

(1)创建播放器实例
先通过调用 Nelp_Create(const char *paLogPath, NELP_OUT _HNLPSERVICE *phNLPService)创建播放器实例。
其中:
paLogPath: 为日志文件的输出路径。如果设为NULL则默认保存到当前的工作目录下。
phNLPService: 输出参数,返回创建成功的播放器实例。

示例代码

_HNLPSERVICE m_hNelpService = NULL;
if (NELP_OK != Nelp_Create("E:\\log", &m_hNelpService)) {
    // 创建失败
}
else {
    // 创建成功
    assert(m_hNelpService != NULL);
}

(2) 注册获取消息的回调
注意:在 Nelp_PrepareToPlay 前调用。
播放器SDK在整个播放过程中会有一些状态消息的回调,开发者需要调用 Nelp_RegisterMessageCB(_HNLPSERVICE hNLPService, PFN_NELP_MESSAGE_CB pMessageCB)接口进行注册才能收到相应的消息回调。
其中:
hNLPService: 为创建成功的播放器实例。
pMessageCB: 为接收消息的回调,开发者需要自己实现该回调来处理相应的消息,消息类型参见API文档。

示例代码

    void getMessage(ST_NELP_MESSAGE msg);
    Nelp_RegisterMessageCB(m_hNelpService, getMessage);

    void getMessage(ST_NELP_MESSAGE msg) {
        switch (msg.iWhat) {
        case NELP_MSG_ERROR:
            break;
        case NELP_MSG_PREPARED:
            break;
        case NELP_MSG_VIDEO_SIZE_CHANGED:
            break;
        case NELP_MSG_BUFFERING_START:
            break;
        case NELP_MSG_BUFFERING_END:
            break;
        case NELP_MSG_COMPLETED:
            break;
        case NELP_MSG_VIDEO_RENDERING_START:
            break;
        case NELP_MSG_AUDIO_RENDERING_START:
            break;
        case NELP_MSG_PLAYBACK_STATE_CHANGED:
            break;
        case NELP_MSG_AUDIO_DEVICE_OPEN_FAILED:
            break;
        case NELP_MSG_SEEK_COMPLETED:
            break;
        case NELP_MSG_VIDEO_PARSE_ERROR:
            break;
        default:
            break;
        }
    }

各种消息类型的具体含义参见API文档

(3) 注册接收资源释放成功消息的回调
注意:在 Nelp_PrepareToPlay 前调用。
播放器退出播放需要调用Nelp_Shutdown接口来释放相关的资源,当前版本中,资源释放的过程是同步的,释放结束后会上报资源释放成功的消息,开发者调用 Nelp_RegisterResourceReleaseSuccessCB(_HNLPSERVICE hNLPService, P_NELP_RESOURCE_RELEASE_SUCCESS_CB pReleaseCB)接口注册回调函数就可以收到该消息。
其中:
phNLPService: 为创建成功的播放器实例。
pReleaseCB: 为接收资源释放成功消息的回调,开发者需要自己实现该回调来做一些资源释放成功后的操作。

示例代码

    void resourceReleaseSuccess();
    Nelp_RegisterResourceReleaseSuccessCB(m_hNelpService, resouceReleaseSuccess);

    void resourceReleaseSuccess() {
        // 资源释放成功了
    }

注意:如果退出后还需要重新开启播放的话,需要等到Nelp_Shutdown结束的消息后才能开始下一次播放,防止内存泄漏。

(4) 注册接收视频数据的回调
注意:在 Nelp_PrepareToPlay 前调用,若不需要得到视频数据则该步骤忽略。
播放器sdk支持解码后的视频数据的回调,若开发者需要得到解码后的视频数据来进行显示或者处理,则可以调用 Nelp_RegisterGetVideoFrameCB(_HNLPSERVICE hNLPService, EN_NELP_MEDIA_FORMAT eMFormat, NELP_OUT P_NELP_VIDEO_FRAME_CB pVideoFrameCB) 接口来进行注册。
其中:
hNLPService: 为创建成功的播放器实例。
eMFormat: 为希望获取的视频数据的格式
pVideoFrameCB: 为获取视频数据的回调

示例代码

    void getVideoFrame(ST_NELP_FRAME *frame);
    // 不使用sdk内置显示模块进行显示,回调的视频数据格式是YUV420
    Nelp_RegisterGetVideoFrameCB(m_hNelpService, EN_YUV420, getVideoFrame);
    void getVideoFrame(ST_NELP_FRAME *frame) 
    {
        switch (frame->enMFormat) {
            case EN_ARGB8888:
                // ARGB8888 数据格式
                break;
            case EN_YUV420:
                // YUV420 数据格式
                break;
            default:
                break;
        }
    }

(5) 设置视频播放窗口
注意:必须在UI线程调用
播放器sdk内置了视频显示模块。开发者可以调用Nelp_SetDisplay(_HNLPSERVICE hNLPService, void *wnd, ST_NELP_RECT* pstRenderRect)接口将HWND句柄和绘制区域传递给sdk,让sdk在wnd指定窗口(或控件)上绘制视频画面,播放过程中也可多次调用此接口来更新绘制区域。若开发者希望自己绘制,请参见步骤4。
其中:
hNLPService: 为创建成功的播放器实例。
wnd: 为显示窗口(或控件)的HWND句柄。
pstRenderRect: 为画面在窗口控件上的区域

示例代码

    HWND wnd;
    CWnd *pWnd = (CWnd *)GetDlgItem(IDC_RENDER);
    wnd = pWnd->GetSafeHwnd();

    if (NELP_OK != Nelp_SetDisPlay(m_hNelpService, wnd, {0, 0, 1280, 720})) {
        return; // 设置不成功
    }

(6) 设置拉流超时时间
注意:在 Nelp_PrepareToPlay 前调用。
播放器sdk提供了接口Nelp_SetPlaybackTimeout(_HNLPSERVICE hNLPService, int timeout)让用户设置预处理播放(Nelp_PrepareToPlay)时的拉流超时时间。若不设置或设置的时间无效,则sdk使用默认超时时间30秒。
其中:
hNLPService: 为创建成功的播放器实例。
timeout: 为超时时间,单位秒:s。

示例代码

    Nelp_SetPlaybackTimeout(m_hNelpService, 10); //设置拉流超时时间为10秒

(7) 初始化播放参数,包括设置播放地址,缓冲模式等
注意:在 Nelp_PrepareToPlay 前调用。
上述操作完成后,需要初始化播放所需的相关参数,如播放地址,缓冲模式。开发者可以调用Nelp_InitParam(_HNLPSERVICE hNLPService, ST_NELP_PARAM *pstParam)接口进行初始化设置。
其中:
hNLPService: 为创建成功的播放器实例。
pstParam: 为相关参数的结构体变量。

示例代码

    ST_NELP_PARAM stNelpParam = { 0 };

    typedef enum en_NELP_STREAM_TYPE {
        en_LIVESTREAMING, // 直播流
        en_ONDEMAND       // 点播流
    } EN_NELP_STREAM_TYPE;

    char *url = "http://xxx.xxx.xxx.xxx/xxx.flv"; // 播放地址
    EN_NELP_STREAM_TYPE m_streamType; // 流类型,直播还是点播
    m_streamType = en_LIVESTREAMING; // 为直播流,该处为示例代码,开发者需要根据实际情况进行设置

    stNelpParam.paPlayUrl = url;
    if (m_streamType == en_LIVESTREAMING) { // 直播流
        stNelpParam.enBufferStategy = EN_NELP_LOW_DELAY; // 采用直播低延时模式
    }
    else if (m_streamType == en_ONDEMAND) { // 点播流
        stNelpParam.enBufferStategy = EN_NELP_ANTI_JITTER; // 采用点播抗抖动模式
    }

    // 初始化相关参数
    if (NELP_OK != Nelp_InitParam(m_hNelpService, &stNelpParam)) {
        // 初始化失败
        return;
    }

(8) 预处理播放
上述所有步骤完成后就可以调用 Nelp_PrepareToPlay(_HNLPSERVICE hNLPService)接口进行预处理播放了,该接口主要做了各个模块的线程创建,开始拉流,解析,解码等一系列操作。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    Nelp_PrepareToPlay(m_hNelpService);

预处理完成后会收到NELP_MSG_PREPARED的消息,具体见(步骤2)和API文档。若预处理过程中出现拉流失败,播放出错等问题,则会收到NELP_MSG_ERROR的消息

(9) 开始播放
在调用 Nelp_PrepareToPlay 接口并且收到NELP_MSG_PREPARED消息后,需要调用 Nelp_Start(_HNLPSERVICE hNLPService) 进行播放。若未等待NELP_MSG_PREPARED消息就立刻调用此接口开始播放,接口会阻塞直到播放器预处理完成。 需要注意的是,由于此接口涉及视频画面渲染的一些对象创建,因此应当在程序的UI线程调用。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    Nelp_Start(m_hNelpService);

2.3 播放控制

(1) 暂停播放和继续播放
注意:此功能只适用于点播。
在播放过程中若需要暂停播放,可以调用 Nelp_Pause(_HNLPSERVICE hNLPService) 接口来暂停当前的播放。暂停后调用Nelp_Resume(_HNLPSERVICE hNLPService)方法即可恢复播放。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    Nelp_Pause(m_hNelpService);
    Nelp_Resume(m_hNelpService);

(2) 跳跃播放
注意:此功能只适用于点播。
在播放过程中需要指定到某一时间点播放可以调用 Nelp_SeekTo(_HNLPSERVICE hNLPService, long long llTime) 接口进行设置。
其中:
hNLPService: 为创建成功的播放器实例。
llTime: 为指定的播放时间点(单位秒:s)。

示例代码

    Nelp_SeekTo(m_hNelpService, 300);

(3) 静音功能
在播放过程中需要静音,则可以调用 Nelp_SetMute(_HNLPSERVICE hNLPService, bool bIsMute)接口进行设置。
其中:
hNLPService: 为创建成功的播放器实例。
bIsMute: 为是否静音的标识,true:开启静音 false:取消静音。

示例代码

    bool bIsMute = true;
    if (bIsMute) {
           // 开启静音
        Nelp_SetMute(m_hNelpService, true);
    }
    else {
        // 取消静音
        Nelp_SetMute(m_hNelpService, false);
    }

(4) 音量调节
在播放过程中可以调用 Nelp_SetVolume(_HNLPSERVICE hNLPService, float fVolume)接口进行音量调节。
其中:
hNLPService: 为创建成功的播放器实例。
fVolume: 为设置的音量大小(范围:0.0 ~ 1.0 0.0: 静音 1.0: 原始音量)。

示例代码

    Nelp_SetVolume(m_hNelpService, 0.8);

(5) 获取文件总时长
注意:此功能只适用于点播。
对于点播视频文件可以调用Nelp_GetDuration(_HNLPSERVICE hNLPService)接口来获取点播文件的总时长,单位秒:s。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    long long lDuration = Nelp_GetDuration(m_hNelpService); 
    if (lDuration < 0) {
        // 获取失败;
    }

(6) 获取当前播放的时间点
在播放过程中可以调用Nelp_GetCurrentPlaybackTime(_HNLPSERVICE hNLPService)接口来获取当前播放的时间点,单位秒:s。此功能适用于直播和点播。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    long lCurrentPos = Nelp_GetCurrentPlaybackTime(m_hNelpService); 
    if (lCurrentPos < 0) {
        // 获取失败;
    }

(7) 获取当前可播放的时间点
注意:此功能只适用于点播。
对于点播视频文件可以调用Nelp_GetPlayableDuration(_HNLPSERVICE hNLPService)接口来获取当前可播放的时间点,即已缓存的位置,单位秒:s。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    long lPlayablePos = Nelp_GetPlayableDuration(m_hNelpService); 
    if (lPlayablePos < 0) {
        // 获取失败;
    }

(8) 获取当前播放器的状态
在播放过程中,开发者可以调用 Nelp_GetPlaybackState(_HNLPSERVICE hNLPService)接口来获取当前播放器的状态,具体的状态值参见API文档EN_NELP_PLAYBACK_STATE枚举类型。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    EN_NELP_PLAYBACK_STATE playState = Nelp_GetPlaybackState(m_hNelpService);
    if (playState == EN_NELP_GET_PLAYBACK_STATE_FAILED) {
        // 获取状态失败
    }

(9) 截图功能
在播放过程中,可以调用 Nelp_GetSnapshot(_HNLPSERVICE hNLPService, EN_NELP_PICTURE_FORMAT ePFormat)接口进行截图。返回的是调用时刻的视频画面的位图数据,可以指定为ARGB32或RGB24格式。 注意,返回的ST_NELP_PICTURE *指针指向的内存不需要调用者释放,不能保存此指针,也不能跨线程使用(若要跨线程使用,调用者需要自己申请内存并拷贝数据)。
其中:
hNLPService: 为创建成功的播放器实例。
ePFormat: 为返回的图片格式,具体参见API文档。

示例代码

    ST_NELP_PICTURE *sPicture = NULL;
    sPicture = Nelp_GetSnapshot(m_hNelpService, EN_PIC_ARGB8888); // 返回的是ARGB8888格式的图片类型

(9) 获取SDK版本号

此接口返回SDK版本号,const char* 类型。注意,此字符串内存不需要调用者释放。

示例代码

    char *paSdkVersion;
    paSdkVersion = Nelp_GetSDKVersion();

(10) 停止播放
在成功开始播放后,若想停止播放,需要调用 Nelp_Stop(_HNLPSERVICE hNLPService) 接口。此接口相当于Nelp_Start的逆操作,也需要在UI线程调用。如果忘记调用,sdk会在Nelp_Shutdown接口内部调用它。
其中:
hNLPService: 为创建成功的播放器实例。

示例代码

    Nelp_Stop(m_hNelpService);

(11) 关闭播放器

关闭播放器需要调用Nelp_Shutdown(_HNLPSERVICE hNLPService)接口,此接口停止一切解码和播放任务,销毁播放器实例的所有成员对象,并最终销毁播放器实例。接口调用后,应将播放器实例句柄置为NULL。 其中:
hNLPService: 为创建成功的播放器实例。

示例代码

     Nelp_Shutdown(m_hNelpService);
     m_hNelpService = NULL;

关闭成功,上层会收到资源释放成功的回调,见2.2中的步骤(3)。

3 SDK 打包说明

开发者在打包自己的应用时,应确保将以下 SDK 相关文件打包进去。

4 API说明

有关API的详细说明,可参见下面的在线文档。

网易云视频播放器NELivePlayer Windows SDK API详细文档