qt下使用第三方播放器
底层播放器构建
基于全志封装的tplayer多媒体播放接口,再封装一层通用型多媒体播放api。
封装api所需文件:
tina_multimedia_demo/videoplayerinterface
├── Makefile
└── src
├── Makefile
├── videoplayerinterface.cpp
└── videoplayerinterface.h
1 directory, 4 files
videoplayerinterface.h
文件为api的定义头文件,为上层qt提供调用播放器接口。videoplayerinterface.cpp
文件为api的主体封装部分,封装内容为tplayer提供的播放接口。剩下的Makefile
文件是基于tina系统编写的,为生成libvideoplayerinterface.so
提供相关的编译配置和参数。
第一层Makefile
文件所在路径:
tina_multimedia_demo/videoplayerinterface
├── Makefile
配置如下:
include $(TOPDIR)/rules.mk
include $(BUILD_DIR)/kernel.mk
PKG_NAME:=videoplayerinterface
PKG_VERSION:=1
PKG_RELEASE:=1
PKG_BUILD_DEPENDS:=libcedarx
PKG_BUILD_DIR := $(COMPILE_DIR)/$(PKG_NAME)
include $(BUILD_DIR)/package.mk
define Package/$(PKG_NAME)
SUBMENU:=tina_multimedia_demo
SECTION:=utils
CATEGORY:=Allwinner
TITLE:=use tplayer interface in tina_multimedia
DEPENDS:= @TPLAYER libcedarx libstdcpp
endef
define Package/$(PKG_NAME)/description
CedarX2.8 videoplayerinterface
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) -r ./src/* $(PKG_BUILD_DIR)/
endef
TARGET_CFLAGS += $(if $(CONFIG_USE_GLIBC),-pthread) -shared -fPIC
TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-ldl -lm)
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/ \
ARCH="$(TARGET_ARCH)" \
AR="$(TARGET_AR)" \
CC="$(TARGET_CC)" \
CXX="$(TARGET_CXX)" \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
TARGET_BOARD="$(TARGET_BOARD_PLATFORM)" \
ONLY_ENABLE_AUDIO="$(CONFIG_ONLY_ENABLE_AUDIO)"
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/lib/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/libvideoplayerinterface.so $(1)/usr/lib/
cp -rvf $(PKG_BUILD_DIR)/libvideoplayerinterface.so ~/work/video-player-interface/
cp -rfv $(PKG_BUILD_DIR)/videoplayerinterface.* ~/work/video-player-interface/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
第二层Makefile
文件所在路径:
tina_multimedia_demo/videoplayerinterface/src
├── Makefile
配置如下:
Target = libvideoplayerinterface.so
SourceIncludePath := -I$(STAGING_DIR)/usr/include/allwinner/include -I$(STAGING_DIR)/usr/include/allwinner
CompileFlags = $(CFLAGS) $(SourceIncludePath)
ifeq ($(ONLY_ENABLE_AUDIO),y)
CompileFlags += -DONLY_ENABLE_AUDIO
endif
LoadFlags += -ltplayer -lrt -lstdc++
$(Target): videoplayerinterface.cpp
$(CC) -o $@ $^ $(CompileFlags) $(LDFLAGS) $(LoadFlags)
播放器封装实现
videoplayerinterface.h
实现如下:
#pragma once
#include <sys/types.h>
typedef enum VPINotifyAppType
{
VPI_NOTIFY_PREPARED = 0,
VPI_NOTIFY_PLAYBACK_COMPLETE = 1,
VPI_NOTIFY_SEEK_COMPLETE = 2,
VPI_NOTIFY_MEDIA_ERROR = 3,
VPI_NOTIFY_NOT_SEEKABLE = 4,
VPI_NOTIFY_BUFFER_START = 5, /*this means no enough data to play*/
VPI_NOTIFY_BUFFER_END = 6, /*this means got enough data to play*/
VPI_NOTIFY_DOWNLOAD_START = 7,//not support now
VPI_NOTIFY_DOWNLOAD_END = 8,//not support now
VPI_NOTIFY_DOWNLOAD_ERROR = 9,//not support now
VPI_NOTIFY_MEDIA_VIDEO_SIZE = 10, /*notified while video size changed*/
VPI_NOTIFY_VIDEO_FRAME = 11,//notify the decoded video frame
VPI_NOTIFY_AUDIO_FRAME = 12,//notify the decoded audio frame
VPI_NOTIFY_SUBTITLE_FRAME = 13,//notify the decoded subtitle frame
VPI_NOTYFY_DECODED_VIDEO_SIZE =14,//notify the decoded video size
}VPINotifyAppType;
class videoplayerinterfacePrivate;
struct KeyValuePairS_VPI {
char *key;
char *val;
};
typedef struct KeyValuePairS_VPI KeyValuePairT_VPI;
struct CdxKeyedVectorS_VPI {
int size;
int index;
KeyValuePairT_VPI item[0];
};
typedef int (*VideoPlayerInterfaceNotifyCallback)(void* pUser, int msg, int ext1, void* para);
typedef struct CdxKeyedVectorS_VPI CdxKeyedVectorT_VPI;
typedef enum VideoRotateType_VPI
{
VPI_VIDEO_ROTATE_DEGREE_0 = 0, /*do not rotate*/
VPI_VIDEO_ROTATE_DEGREE_90 = 90, /*rotate 90 degree clockwise*/
VPI_VIDEO_ROTATE_DEGREE_180 = 180, /*rotate 180 degree clockwise*/
VPI_VIDEO_ROTATE_DEGREE_270 = 270, /*rotate 270 degree clockwise*/
}VideoRotateType_VPI;
typedef enum PlaySpeedType_VPI
{
VPI_PLAY_SPEED_FAST_FORWARD_16 = 0, /*fast forward 16 times*/
VPI_PLAY_SPEED_FAST_FORWARD_8 = 1, /*fast forward 8 times*/
VPI_PLAY_SPEED_FAST_FORWARD_4 = 2, /*fast forward 4 times*/
VPI_PLAY_SPEED_FAST_FORWARD_2 = 3, /*fast forward 2 times*/
VPI_PLAY_SPEED_1 = 4, /*normal play*/
VPI_PLAY_SPEED_FAST_BACKWARD_2 = 5, /*fast backward 2 times*/
VPI_PLAY_SPEED_FAST_BACKWARD_4 = 6, /*fast backward 4 times*/
VPI_PLAY_SPEED_FAST_BACKWARD_8 = 7, /*fast backward 8 times*/
VPI_PLAY_SPEED_FAST_BACKWARD_16 = 8, /*fast backward 16 times*/
}PlaySpeedType_VPI;
class videoplayerinterface
{
public:
typedef enum EVideoPlayerType {
VIDEO_AUDIO_PLAYER = 0,
AUDIO_PLAYER = 1,
}VideoPlayerType;
videoplayerinterface(/* args */);
~videoplayerinterface();
bool create(VideoPlayerType type = VIDEO_AUDIO_PLAYER);
void destroy();
int setDebugFlag(bool debugFlag);
int videoPlayerInterfaceSetNotifyCallback(VideoPlayerInterfaceNotifyCallback notifier, void* pUserData);
int setDataSource(const char* pUrl, const CdxKeyedVectorT_VPI* pHeaders);
int prepare();
int prepareAsync();
void play();
void stop();
void pause();
void reset();
void setVolume(int volume);
int getVolume();
int seekTo(int nSeekTimeMs);
bool isPlaying();
int getCurrentPosition(int* msec);
int setLooping(bool bLoop);
int setRotate(VideoRotateType_VPI rotate);
int setSpeed(PlaySpeedType_VPI nSpeed);
int setAudioMute(bool mute);
int setExternalSubUrl(const char* filePath);
int setExternalSubFd(int fd, int64_t offset, int64_t len, int fdSub);
int getSubDelay();
int setSubDelay(int nTimeMs);
int getSubCharset(char *charset);
int setSubCharset(const char* strFormat);
int switchAudio(int nStreamIndex);
int switchSubtitle(int nStreamIndex);
void setSubtitleDisplay(bool onoff);
void setVideoDisplay(bool onoff);
void setDisplayRect(int x, int y, unsigned int width, unsigned int height);
void setSrcRect(int x, int y, unsigned int width, unsigned int height);
void setBrightness(unsigned int grade);
void setContrast(unsigned int grade);
void setHue(unsigned int grade);
void setSaturation(unsigned int grade);
void setEnhanceDefault();
int getVideoDispFramerate(float* dispFramerate);
int setHoldLastPicture(int bHoldFlag);
private:
videoplayerinterfacePrivate *const d_ptr;
friend class videoplayerinterfacePrivate;
};
videoplayerinterface.cpp
实现如下:
#include "videoplayerinterface.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
#include <allwinner/tplayer.h>
#define TOTAL_VIDEO_AUDIO_NUM 100
#define MAX_FILE_NAME_LEN 256
#define FILE_TYPE_NUM 21
#define FILE_TYPE_LEN 10
class videoplayerinterfacePrivate
{
public:
typedef struct VideoPlayerContext
{
TPlayer* mTPlayer;
int mSeekable;
int mError;
int mVideoFrameNum;
bool mPreparedFlag;
bool mLoopFlag;
bool mSetLoop;
char mUrl[512];
MediaInfo* mMediaInfo;
char mVideoAudioList[TOTAL_VIDEO_AUDIO_NUM][MAX_FILE_NAME_LEN];
int mCurPlayIndex;
int mRealFileNum;
sem_t mPreparedSem;
}VideoPlayerContext;
videoplayerinterfacePrivate()
: volume(6)
, playerType(videoplayerinterface::VIDEO_AUDIO_PLAYER)
{
}
int volume;
videoplayerinterface::VideoPlayerType playerType;
VideoPlayerContext playerContext;
};
videoplayerinterface::videoplayerinterface(/* args */)
: d_ptr(new videoplayerinterfacePrivate)
{
}
videoplayerinterface::~videoplayerinterface()
{
}
bool videoplayerinterface::create(VideoPlayerType type)
{
d_ptr->playerType = type;
d_ptr->playerContext.mTPlayer = ::TPlayerCreate((TplayerType)d_ptr->playerType);
if (d_ptr->playerContext.mTPlayer == NULL) {
return false;
}
return true;
}
void videoplayerinterface::destroy()
{
::TPlayerDestroy(d_ptr->playerContext.mTPlayer);
}
int videoplayerinterface::setDebugFlag(bool debugFlag)
{
return ::TPlayerSetDebugFlag(d_ptr->playerContext.mTPlayer, debugFlag);
}
int videoplayerinterface::videoPlayerInterfaceSetNotifyCallback(VideoPlayerInterfaceNotifyCallback notifier, void* pUserData)
{
return ::TPlayerSetNotifyCallback(d_ptr->playerContext.mTPlayer, notifier, pUserData);
}
int videoplayerinterface::setDataSource(const char* pUrl, const CdxKeyedVectorT_VPI* pHeaders)
{
return ::TPlayerSetDataSource(d_ptr->playerContext.mTPlayer, pUrl, (CdxKeyedVectorT*)pHeaders);
}
int videoplayerinterface::prepare()
{
return ::TPlayerPrepare(d_ptr->playerContext.mTPlayer);
}
int videoplayerinterface::prepareAsync()
{
return ::TPlayerPrepareAsync(d_ptr->playerContext.mTPlayer);
}
void videoplayerinterface::play()
{
::TPlayerStart(d_ptr->playerContext.mTPlayer);
}
void videoplayerinterface::stop()
{
::TPlayerStop(d_ptr->playerContext.mTPlayer);
}
void videoplayerinterface::pause()
{
::TPlayerPause(d_ptr->playerContext.mTPlayer);
}
void videoplayerinterface::reset()
{
::TPlayerReset(d_ptr->playerContext.mTPlayer);
}
void videoplayerinterface::setVolume(int volume)
{
TPlayerSetVolume(d_ptr->playerContext.mTPlayer, volume);
}
int videoplayerinterface::getVolume()
{
return ::TPlayerGetVolume(d_ptr->playerContext.mTPlayer);
}
int videoplayerinterface::seekTo(int nSeekTimeMs)
{
return ::TPlayerSeekTo(d_ptr->playerContext.mTPlayer, nSeekTimeMs);
}
bool videoplayerinterface::isPlaying()
{
return ::TPlayerIsPlaying(d_ptr->playerContext.mTPlayer);
}
int videoplayerinterface::getCurrentPosition(int* msec)
{
return ::TPlayerGetCurrentPosition(d_ptr->playerContext.mTPlayer, msec);
}
int videoplayerinterface::setLooping(bool bLoop)
{
return ::TPlayerSetLooping(d_ptr->playerContext.mTPlayer, bLoop);
}
int videoplayerinterface::setRotate(VideoRotateType_VPI rotate)
{
return ::TPlayerSetRotate(d_ptr->playerContext.mTPlayer, static_cast<TplayerVideoRotateType>(rotate));
}
int videoplayerinterface::setSpeed(PlaySpeedType_VPI nSpeed)
{
return ::TPlayerSetSpeed(d_ptr->playerContext.mTPlayer, (TplayerPlaySpeedType)nSpeed);
}
int videoplayerinterface::setAudioMute(bool mute)
{
return ::TPlayerSetAudioMute(d_ptr->playerContext.mTPlayer, mute);
}
int videoplayerinterface::setExternalSubUrl(const char* filePath)
{
return ::TPlayerSetExternalSubUrl(d_ptr->playerContext.mTPlayer, filePath);
}
int videoplayerinterface::setExternalSubFd(int fd, int64_t offset, int64_t len, int fdSub)
{
return ::TPlayerSetExternalSubFd(d_ptr->playerContext.mTPlayer, fd, offset, len, fdSub);
}
int videoplayerinterface::getSubDelay()
{
return ::TPlayerGetSubDelay(d_ptr->playerContext.mTPlayer);
}
int videoplayerinterface::setSubDelay(int nTimeMs)
{
return ::TPlayerSetSubDelay(d_ptr->playerContext.mTPlayer, nTimeMs);
}
int videoplayerinterface::getSubCharset(char *charset)
{
return ::TPlayerGetSubCharset(d_ptr->playerContext.mTPlayer, charset);
}
int videoplayerinterface::setSubCharset(const char* strFormat)
{
return ::TPlayerSetSubCharset(d_ptr->playerContext.mTPlayer, strFormat);
}
int videoplayerinterface::switchAudio(int nStreamIndex)
{
return ::TPlayerSwitchAudio(d_ptr->playerContext.mTPlayer, nStreamIndex);
}
int videoplayerinterface::switchSubtitle(int nStreamIndex)
{
return ::TPlayerSwitchSubtitle(d_ptr->playerContext.mTPlayer, nStreamIndex);
}
void videoplayerinterface::setSubtitleDisplay(bool onoff)
{
::TPlayerSetSubtitleDisplay(d_ptr->playerContext.mTPlayer, onoff);
}
void videoplayerinterface::setVideoDisplay(bool onoff)
{
::TPlayerSetVideoDisplay(d_ptr->playerContext.mTPlayer, onoff);
}
void videoplayerinterface::setDisplayRect(int x, int y, unsigned int width, unsigned int height)
{
::TPlayerSetDisplayRect(d_ptr->playerContext.mTPlayer, x, y, width, height);
}
void videoplayerinterface::setSrcRect(int x, int y, unsigned int width, unsigned int height)
{
::TPlayerSetSrcRect(d_ptr->playerContext.mTPlayer, x, y, width, height);
}
void videoplayerinterface::setBrightness(unsigned int grade)
{
::TPlayerSetBrightness(d_ptr->playerContext.mTPlayer, grade);
}
void videoplayerinterface::setContrast(unsigned int grade)
{
::TPlayerSetContrast(d_ptr->playerContext.mTPlayer, grade);
}
void videoplayerinterface::setHue(unsigned int grade)
{
::TPlayerSetHue(d_ptr->playerContext.mTPlayer, grade);
}
void videoplayerinterface::setSaturation(unsigned int grade)
{
::TPlayerSetSaturation(d_ptr->playerContext.mTPlayer, grade);
}
void videoplayerinterface::setEnhanceDefault()
{
::TPlayerSetEnhanceDefault(d_ptr->playerContext.mTPlayer);
}
int videoplayerinterface::getVideoDispFramerate(float* dispFramerate)
{
return ::TPlayerGetVideoDispFramerate(d_ptr->playerContext.mTPlayer,dispFramerate);
}
int videoplayerinterface::setHoldLastPicture(int bHoldFlag)
{
return ::TPlayerSetHoldLastPicture(d_ptr->playerContext.mTPlayer, bHoldFlag);
}
#undef TOTAL_VIDEO_AUDIO_NUM
#undef MAX_FILE_NAME_LEN
#undef FILE_TYPE_NUM
#undef FILE_TYPE_LEN
使用播放器接口
UVideoPlayer.cpp
实现:
#pragma once
#include <QWidget>
typedef int (*UVideoPlayerNotifyCallback)(void* pUser, int msg, int ext1);
class videoplayerinterface;
class QLabel;
class UVideoPlayer: public QWidget
{
Q_OBJECT
Q_PROPERTY(bool loopPlayback READ getLoopPlayback WRITE setLoopPlayback)
Q_PROPERTY(uint volume READ getVolume WRITE setVolume)
Q_PROPERTY(QRect size READ getSize WRITE setSize)
Q_PROPERTY(QString url READ getPlayUrl WRITE setPlayUrl)
~UVideoPlayer();
public:
explicit UVideoPlayer(QWidget *parent = 0);
bool getLoopPlayback() const;
uint getVolume() const;
QRect getSize() const;
void init();
QString getPlayUrl() const;
QString getNextUrl();
videoplayerinterface *mvideoplayer;
UVideoPlayerNotifyCallback userCallback = NULL;
protected:
void paintEvent(QPaintEvent *) override;
void resizeEvent(QResizeEvent *event) override;
public slots:
void setLoopPlayback(bool isPlaybacked);
void setVolume(uint volume);
void setSize(const QRect &size);
void setPlayUrl(const QString &url);
private:
bool isPlaybacked = true;
uint volume = 6;
QRect rectsize;
QWidget *parentWidget;
QString playUrl="/mnt/SDCARD/";
QStringList urlList;
int playIndex = 0;
};
UVideoPlayer.h
实现:
#include "UVideoPlayer.h"
#include "qpainter.h"
#include "qtimer.h"
#include "qdebug.h"
#include <QTextOption>
#include <QString>
#include <QLabel>
#include <QFileDialog>
#include <QFile>
#include "LanguageManager.h"
#include <QFileInfoList>
#include <QFileInfo>
//#define __aarch64__
#ifdef __aarch64__
#include "videoplayerinterface.h"
#endif
UVideoPlayer::~UVideoPlayer()
{
#ifdef __aarch64__
mvideoplayer->destroy();
#endif
}
UVideoPlayer::UVideoPlayer(QWidget *parent)
: QWidget(parent)
, parentWidget(parent)
{
#ifdef __aarch64__
QPalette pal = palette();
pal.setColor(QPalette::Window, QColor(0x00, 0xff, 0x00, 0x00));
setPalette(pal);
#else
#endif
init();
}
bool UVideoPlayer::getLoopPlayback() const
{
return this->isPlaybacked;
}
uint UVideoPlayer::getVolume() const
{
return this->volume;
}
QRect UVideoPlayer::getSize() const
{
return this->geometry();
}
QString UVideoPlayer::getNextUrl()
{
if (playIndex == urlList.count())
playIndex = 0;
return urlList.at(playIndex);
playIndex++;
}
int callbackForPlayer(void* pUser, int msg, int ext1, void* para)
{
Q_UNUSED(pUser)
Q_UNUSED(msg)
Q_UNUSED(ext1)
Q_UNUSED(para)
#ifdef __aarch64__
UVideoPlayer *uVideoPlayer = static_cast<UVideoPlayer*>(para);
int ret = 0xff;
if (uVideoPlayer->userCallback)
ret = uVideoPlayer->userCallback(pUser, msg, ext1);
if (-ret != msg) {
switch (msg) {
case VPI_NOTIFY_PLAYBACK_COMPLETE:
uVideoPlayer->mvideoplayer->setDataSource(uVideoPlayer->getNextUrl().toUtf8(), NULL);
uVideoPlayer->mvideoplayer->prepare();
uVideoPlayer->mvideoplayer->setHoldLastPicture(false);
uVideoPlayer->mvideoplayer->play();
break;
default:
break;
}
}
#endif
return 0;
}
#ifdef __aarch64__
void UVideoPlayer::init()
{
urlList.clear();
QStringList filterStr;
filterStr << ".avi" << ".mkv" << ".flv" << ".ts" << ".mp4" << ".ts" << ".webm" << ".asf" << ".mpg"
<<".mov" << ".vob" << ".mp1" << ".mp2" << ".mp3" << ".ogg" << ".flac" << ".ape" << ".wav"
<<".m4a" << ".amr" << ".aac";
QDir dir(playUrl);
QFileInfoList list = dir.entryInfoList();
foreach (QFileInfo info, list) {
if(info.fileName() == "." || info.fileName() == "..")
continue;
if (info.isDir())
continue;
if (!filterStr.contains(QString(".%1").arg(info.completeSuffix())))
continue;
urlList << info.absoluteFilePath();
}
mvideoplayer = new videoplayerinterface;
if (false == mvideoplayer->create()) {
qDebug() << "videoplayer creater fail!";
}
mvideoplayer->setDisplayRect(x(), y(), width(), height());
mvideoplayer->videoPlayerInterfaceSetNotifyCallback(callbackForPlayer, mvideoplayer);
mvideoplayer->reset();
mvideoplayer->setDataSource(getNextUrl().toUtf8(), NULL);
mvideoplayer->prepare();
mvideoplayer->setHoldLastPicture(false);
mvideoplayer->play();
qDebug() << "videoplayer run!";
}
#else
void UVideoPlayer::init() {}
#endif
QString UVideoPlayer::getPlayUrl() const
{
return this->playUrl;
}
void UVideoPlayer::paintEvent(QPaintEvent *)
{
#ifdef __aarch64__
QPainter painter(this);
painter.setCompositionMode(QPainter::CompositionMode_Clear);
painter.fillRect(rect(), Qt::SolidPattern);
#else
QPainter painter(this);
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::black);
painter.drawRect(rect());
painter.restore();
#endif
}
void UVideoPlayer::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
#ifdef __aarch64__
if (mvideoplayer) {
QMetaObject::invokeMethod(parentWidget, "onTransparentRectChanged", Q_ARG(const QRect &, this->geometry()));
mvideoplayer->setDisplayRect(x(), y(), width(), height());
}
#endif
}
void UVideoPlayer::setLoopPlayback(bool isPlaybacked)
{
this->isPlaybacked = isPlaybacked;
}
void UVideoPlayer::setVolume(uint volume)
{
this->volume = volume;
}
void UVideoPlayer::setSize(const QRect &size)
{
this->rectsize = size;
this->setGeometry(this->rectsize);
update();
}
void UVideoPlayer::setPlayUrl(const QString &url)
{
if (!url.isEmpty())
this->playUrl = url;
}