ffmpeg播放器5

117 阅读2分钟

1背景

hplayer学习 上一篇中追踪到了start设置回调,这一篇继续后续

2步骤

2.1 start如下

void HVideoWidget::start() {
    if (media.type == MEDIA_TYPE_NONE) {
        QMessageBox::information(this, tr("Info"), tr("Please first set media source, then start."));
        updateUI();
        return;
    }

    if (!pImpl_player) {
        pImpl_player = HVideoPlayerFactory::create(media.type);
        pImpl_player->set_media(media);
        pImpl_player->set_event_callback(hplayer_event_callback, this);
        title = media.src.c_str();
        int ret = pImpl_player->start();
        if (ret != 0) {
            onOpenFailed();
        }
        else {
            onOpenSucceed();
        }
        updateUI();
    }
    else {
        if (status == PAUSE) {
            resume();
        }
    }
}

从title = media.src.c_str();开始 从前几篇有提到media是一个结构体,有type和src以及index,src是选择的文件路径。

2.2 pImpl_player->start()

之后的int ret = pImpl_player->start();,这里pImpl_player工厂方法是HFFPlayer,申明的时候是HVideoPlayer。

先看申明(src/ui/HVideoWidget.h)

class HVideoWidget : public QFrame
public:
    HVideoPlayer*   pImpl_player;

再从HVideoPlayer的头文件(src/video/HVideoPlayer.h)查看

class HVideoPlayer
{
public:
    virtual int start() = 0;

再看工厂方法对象,找头文件(src/video/hffplayer.h)

class HFFPlayer : public HVideoPlayer, public HThread {
public:
    virtual int start() {
        quit = 0;
        return HThread::start();
    }

这里用了多态

在C++中,当父类的函数声明为虚函数,子类重写该函数(无论是否显式添加 virtual 关键字),并通过父类指针或引用指向子类对象时,实际调用的是子类的函数。这是由虚函数的动态绑定机制(运行时多态)决定的。

父类为虚函数,子类的函数只要签名(名称,参数,返回值)一样,virtual和override加不加都一样,加了可读性更好一点。

在C++中,如果父类的函数不是虚函数,而子类将同名函数声明为虚函数,当通过父类指针调用该函数时,实际调用的是父类的函数。

所以上面实际调用的是HFFPlayer的虚函数(子类,这里加上override,可读性更好),因为基类是虚函数,子类加不加都是虚函数。如果父类不是虚函数,子类加了或者不加,用父类申明,子类初始化,都是调用的父类的函数。

2.3 HThread::start()---待续

2.4 后续的updateUI

在HVideoWidget.h头文件中

class HVideoWidget : public QFrame
protected:
    void initUI();
    void initConnect();
    void updateUI();

在HVideoWidget.cpp中有如下代码

void HVideoWidget::updateUI() {
    titlebar->labTitle->setText(QString::asprintf("%02d ", playerid) + title);

    toolbar->btnStart->setVisible(status != PLAY);
    toolbar->btnPause->setVisible(status == PLAY);

    btnMedia->setVisible(status == STOP);

    if (status == STOP) {
        toolbar->sldProgress->hide();
        toolbar->lblDuration->hide();
    }
}