qt下使用第三方播放器

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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值