FFmpeg安卓流媒体播放项目04:观察者Observer模式的代码实现

263 阅读1分钟

观察者Observer模式的代码实现

观察者详解参考链接:www.runoob.com/design-patt…

本项目中采用观察者模式,主要是为了进行数据的传递,如IDemux解封装出的音视频码流数据时,通知音视频解码类IDecode进行解码

观察者接口类IObserver

  • IObserver.h
#ifndef BOPLAY_IOBSERVER_H
#define BOPLAY_IOBSERVER_H

#include "XData.h"
#include "XThread.h"
#include <vector>
#include <mutex>

//观察者 和 主体
class IObserver : public XThread {
public:
    //观察者必须实现, 观察者接受数据函数, 主体调用观察者的update通知观察者已经收到数据了
    virtual void update(XData xData){}

    //主体函数, 添加观察者(线程安全)
    void addObs(IObserver *observer);

    //通知所有观察者(线程安全)
    void Notify(XData xData);

protected:
    //存储所有观察者
    std::vector<IObserver *> observers;
    //线程锁
    std::mutex mux;
};


#endif //BOPLAY_IOBSERVER_H
  • IObserver.cpp
#include "IObserver.h"

//添加观察者
void IObserver::addObs(IObserver *observer) {
    if (!observer){
        return;
    }
    //加锁保证线程安全
    mux.lock();
    observers.push_back(observer);
    mux.unlock();
}

//调用观察者的update方法即通知观察者有新数据
void IObserver::Notify(XData xData) {
    mux.lock();
    //vector的size()每次调用的时候都会去统计一遍, 如果数量较大, 效率会降低
//    for (int i = 0; i < observers.size(); ++i) {
    for (auto & observer : observers) {
        observer->update(xData);
    }
    mux.unlock();
}

解封装接口类IDemux使用观察者模式

#ifndef BOPLAY_IDEMUX_H
#define BOPLAY_IDEMUX_H

#include "XData.h"
#include "XThread.h"
#include "IObserver.h"

//解封装接口类继承IOberver实现观察者模式
class IDemux: public IObserver {
public:
    //打开文件或者流媒体 rtmp http rtsp
    virtual bool Open(const char *url) = 0;

    //读取一帧数据,数据由调用者清理
    virtual XData Read() = 0;

    //总时长(单位ms)
    int totalMs = 0;
protected:
    //不要让用户访问
    virtual void main();
};


#endif //BOPLAY_IDEMUX_H
  • IDemux.cpp
#include "IDemux.h"
#include "XLog.h"

void IDemux::main() {
    while(!isExit){
        //解封装线程的主函数主要是读取数据
        XData xData = Read();
        if (xData.size > 0){
            //读取到数据后通知观察者
            Notify(xData);
        }
    }
}