VLC-SDK调用学习

时间:2021-08-16 15:51:53

VLC-SDK调用学习

VLC属于Video LAN开源项目组织中的一款全开源的流媒体服务器和多媒体播放器。作为流媒体服务器,VLC跨平台,支持多操作系统和计算机体系结构;作为多媒体播放器,VLC可以播放多种格式的媒体文件。主要包括有:WMV、ASF、MPG、MP、AVI、H.264等多种常见媒体格式。


通过查看官方文档,学习的了下VLC简单的调用接口,实现了一个音乐播放器,其实还是挺简单的。

VLC-SDK调用学习

为此特意将VLC的调用封装一个类:

QVlcPlayer

#ifndef QVLCPLAYER_H
#define QVLCPLAYER_H

#include <QObject>

typedef void (* pfnPosChanged) (void *data, int iPos);  // 文件位置变化

struct libvlc_instance_t;
struct libvlc_media_player_t;
struct libvlc_event_t;

class QVlcPlayer : public QObject
{
    Q_OBJECT
public:
    explicit QVlcPlayer(QObject *parent = 0);
    ~QVlcPlayer();

    bool Play(QString strPath);                     // 播放路径为strPath的文件
    void Play ();                                   // 播放
    void Pause();                                   // 暂停
    void Stop ();                                   // 停止
// void PlayPreviouse(); // 播放上一首
// void PlayNext(); // 播放下一首
    void Volume(int nVol);                          // 音量设置为nVol
    void VolumeIncrease();                          // 音量增大
    void VolumeReduce();                            // 音量减小

    void SeekTo(int nPos);                          // 跳到指定位置nPos
    void SeekForward();                             // 快进
    void SeekBackward();                            // 快退

    void SetCallback(pfnPosChanged pfn);            // 设置文件位置改变时的回调函数
    pfnPosChanged GetCallback();                    // 获取文件位置改变时的回调函数

    bool    IsOpen();                               // 文件是否打开
    bool    IsPlaying();                            // 文件是否正在播放
    bool    IsPause();                              // 是否暂停
    int     GetPos();                               // 获取文件当前播放的位置
    qint64 GetTime();                               // 获取时间
    void SetPlayTime(qint64 time);                  // 设置播放时间
    qint64 GetLength();                             // 获取长度
    int GetPlayStatue();                            // 获取播放状态
    const char* getLibVlcVersion();

private:
    libvlc_instance_t     *m_pVLC_Inst;             // VLC实例
    libvlc_media_player_t *m_pVLC_Player;           // VLC播放器
    pfnPosChanged          m_pfn;                   // 文件位置改变时的回调函数

    QString m_filePath;                             // 文件路径
    void Init();                                    // 初始化
    QString UnicodeToUTF8(const QString &strWide);  // 编码转化
    void Release();                                 // 清理内存

};

#endif // QVLCPLAYER_H

QVlcPlayer.cpp

#include "qvlcplayer.h"
#include "vlc/vlc.h"
#include "vlc/libvlc_media.h"
#include <qmath.h>
#include <QStringList>
#include <QTextCodec>

// VLC的事件管理
void OnVLC_EndReached(const libvlc_event_t *event, void *data);
void OnVLC_PositionChanged(const libvlc_event_t *event, void *data);

QVlcPlayer::QVlcPlayer(QObject *parent)
    : QObject(parent),
      m_pVLC_Inst(NULL),
      m_pVLC_Player(NULL),
      m_pfn(NULL)
{
}

//
QVlcPlayer::~QVlcPlayer()
{
    this->Release();
}

//播放媒体
bool QVlcPlayer::Play(QString strPath)
{
    if (!m_pVLC_Inst)
    {
        this->Init();
    }
    if (strPath.isEmpty() || !m_pVLC_Inst)
    {
        return false;
    }

    this->Stop();

    bool bRet = false;
    libvlc_media_t *m;

#if defined(Q_OS_WIN)
    m_filePath = strPath.replace("/","\\",Qt::CaseSensitive);
#elif defined(Q_OS_LINUX)
    m_filePath = strPath;
#endif
    //将文件路径进行编码转换(不转换的话不能识别中文,进而会出现错误)
    m_filePath = UnicodeToUTF8(m_filePath);

    m = libvlc_media_new_path(m_pVLC_Inst,m_filePath.toAscii());
    if (m)
    {
        m_pVLC_Player = libvlc_media_player_new_from_media(m);
        if (m_pVLC_Player)
        {
            libvlc_media_player_play(m_pVLC_Player);
            // 事件管理
            libvlc_event_manager_t *vlc_evt_man = libvlc_media_player_event_manager(m_pVLC_Player);
            libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerEndReached, ::OnVLC_EndReached, this);
            libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerPositionChanged, ::OnVLC_PositionChanged, this);
            bRet = true;
        }
        libvlc_media_release(m);
    }
    return bRet;
}

void QVlcPlayer::Play()
{
    if (m_pVLC_Player)
    {
        libvlc_media_player_play(m_pVLC_Player);
    }
}

//暂停
void QVlcPlayer::Pause()
{
    if (m_pVLC_Player)
    {
        libvlc_media_player_pause(m_pVLC_Player);
    }
}

//停止播放媒体
void QVlcPlayer::Stop()
{
    if (m_pVLC_Player)
    {
        libvlc_media_player_stop(m_pVLC_Player);    /*stop playing*/
        libvlc_media_player_release(m_pVLC_Player); /*Free the media_player*/
        m_pVLC_Player = NULL;
    }
}

void QVlcPlayer::Volume(int nVol)
{
    if (m_pVLC_Player)
    {
        libvlc_audio_set_volume(m_pVLC_Player,nVol);
    }
}

//增加音量
void QVlcPlayer::VolumeIncrease()
{
    if (m_pVLC_Player)
    {
        int nVol = libvlc_audio_get_volume(m_pVLC_Player);
        Volume((int)ceil(nVol * 1.1));
    }
}

//减小音量
void QVlcPlayer::VolumeReduce()
{
    if (m_pVLC_Player)
    {
        int nVol = libvlc_audio_get_volume(m_pVLC_Player);
        Volume((int)floor(nVol * 0.9));
    }
}

void QVlcPlayer::SeekTo(int nPos)
{
    if (m_pVLC_Player)
    {
        libvlc_media_player_set_position(m_pVLC_Player, nPos/(float)10000.0);
    }
}

//快进
void QVlcPlayer::SeekForward()
{
    int nPos = GetPos();
    //SeekTo(ceil(nPos * 1.1));
    SeekTo(nPos + 10);
}

//快退
void QVlcPlayer::SeekBackward()
{
    int nPos = GetPos();
    //SeekTo(floor(nPos * 0.9));
    SeekTo(nPos - 10);
}

void QVlcPlayer::SetCallback(pfnPosChanged pfn)
{
    m_pfn = pfn;
}

pfnPosChanged QVlcPlayer::GetCallback()
{
    return m_pfn;
}

bool QVlcPlayer::IsOpen()
{
    return NULL != m_pVLC_Player;
}

bool QVlcPlayer::IsPlaying()
{
    if (m_pVLC_Player)
    {
        return libvlc_media_player_is_playing(m_pVLC_Player);
    }

    return FALSE;
}

bool QVlcPlayer::IsPause()
{
    bool tem;
    if (m_pVLC_Player)
    {
        int state = libvlc_media_player_get_state(m_pVLC_Player);
        switch(state)
        {
        case libvlc_Paused:
        case libvlc_Stopped:
            tem = true;
            break;
        default:
            break;
        }
    }else{
        tem = false;
    }
    return tem;
}

//获取文件当前播放的位置
int QVlcPlayer::GetPos()
{
    if (m_pVLC_Player)
    {
        return (int)(100 * libvlc_media_player_get_position(m_pVLC_Player));
    }

    return 0;
}

//获取时间:当前播放的时间
qint64 QVlcPlayer::GetTime()
{
    if (m_pVLC_Player)
    {
        return libvlc_media_player_get_time(m_pVLC_Player);
    }

    return 0;
}

void QVlcPlayer::SetPlayTime(qint64 time)
{
    if (m_pVLC_Player)
    {
        libvlc_media_player_set_time(m_pVLC_Player,time);
    }
}

//获取长度:当前媒体的总时间长度
qint64 QVlcPlayer::GetLength()
{
    if (m_pVLC_Player)
    {
        return libvlc_media_player_get_length(m_pVLC_Player);
    }
    return 0;
}
/* typedef enum libvlc_state_t { libvlc_NothingSpecial = 0, libvlc_Opening, libvlc_Buffering, libvlc_Playing, libvlc_Paused, libvlc_Stopped, libvlc_Ended, libvlc_Error } libvlc_state_t; */
int QVlcPlayer::GetPlayStatue()
{
    if (m_pVLC_Inst)
    {
        return libvlc_media_player_get_state(m_pVLC_Player);
    }
    return 0;
}

const char *QVlcPlayer::getLibVlcVersion()
{
    if (m_pVLC_Inst)
    {
        return libvlc_get_version();
    }
    return "";
}

//VLC实例初始化
void QVlcPlayer::Init()
{
    if (!m_pVLC_Inst)
    {
        m_pVLC_Inst = libvlc_new(0,NULL);
    }

    m_filePath = "";
}

//unicode转utf8
QString QVlcPlayer::UnicodeToUTF8(const QString &strWide)
{
    QString strUtf8;
    QStringList t;
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    for (int i = 0; i <strWide.length(); i+=4)
    {
        t.append(strWide.mid(i,4));
    }
    foreach (const QString &str, t) {
        strUtf8.append(str);
    }

    return codec->fromUnicode(strUtf8);
}

void QVlcPlayer::Release()
{
    this->Stop();

    if (m_pVLC_Inst)
    {
        libvlc_release(m_pVLC_Inst);
        m_pVLC_Inst = NULL;
    }
}

void OnVLC_EndReached(const libvlc_event_t *event,void *data)
{

}

void OnVLC_PositionChanged(const libvlc_event_t *event, void *data)
{
    switch (event->type)
    {
    case libvlc_MediaPlayerPositionChanged:
    {
        float fPos = event->u.media_player_position_changed.new_position;
        QVlcPlayer *pAVPlayer = (QVlcPlayer *) data;

        if (pAVPlayer)
        {
            pfnPosChanged pfn = pAVPlayer->GetCallback();

            if (pfn)
            {
                pfn(pAVPlayer, int(fPos * 100));
            }
        }
    }
        break;
    case libvlc_MediaPlayerSnapshotTaken:
        break;
    default:
        break;
    }
}

以上代码就是播放器的核心部分,代码注释很详细,完全可以看懂。而VLC又是跨平台的,因此这完全可以在linux、MAC下运行,只需要相应的动态库即可。关于编译不同平台的VLC动态库,官网有详细的介绍,这里就不做过多的介绍。

关于这个播放器界面,实现起来也很简单,参考我模仿的酷狗音乐界面,完全可以实现。

写完播放器很想让它在我的ARM板上跑起来,但是在编译VLC库时,遇到了很多问题,不得已而终止,心里还是有些许的遗憾的。编译ARM版本动态库的路上遇到了奇怪的问题,而这些问题网上的资料也很少,究其原因是因为VLC的依赖库太多了,好多的错误提示是缺少相应的库,安装上这些库之后又提醒某个文件中缺少头文件,很是让人头疼!看来只能转向Mplayer播放器了!


一下是configure之后的截图,这一步算数成功了。
VLC-SDK调用学习

在之后的make过程中,错误百出!

若是有哪位大神编译好了ARM版本的VLC库,还是很希望能交流下,不胜感激!


技术在于交流、分享……
博客地址:http://blog.****.net/u013704336\
Email:kevinlq0912@163.com
QQ:936563422