ffmpeg播放器21(播放视频)

58 阅读1分钟

1背景

上一篇结尾的时候只处理了一帧,这一篇继续把后续的补上。

2步骤

2.1 视频循环播放

hthread.h中取消run中while注释

    virtual void run(){
        while(status!= STOP){
            doTask();
        }
    }

image.png hframebuf.cpp 中修改pop和push如下

int HFrameBuf::push(HFrame *pFrame)
{
    std::lock_guard<std::mutex> locker(this->mutex);
    if(pFrame->isNull())
        return -10;


    if(frames.size()>=(size_t)cache_num){
        HFrame frame = std::move(frames.front()); // 移动所有权
        frames.pop_front();  // 先移除,避免析构冲突

        free(frame.buf.len);   // 安全释放内存
        frame.buf = {nullptr, 0}; // 必须置空!

        if (frame.userdata) {
            ::free(frame.userdata);
            frame.userdata = nullptr;
        }
    }
    int ret=0;
    if(isNull()){
        resize(pFrame->buf.len*cache_num);
        ret=1;
    }

    HFrame frame;
    frame.buf.base=alloc(pFrame->buf.len);
    frame.buf.len=pFrame->buf.len;
    frame.copy(*pFrame);
    frames.push_back(frame);
    return ret;
}

int HFrameBuf::pop(HFrame *pFrame)
{
    std::lock_guard<std::mutex> locker(this->mutex);

    if(isNull())
        return -10;


    if(frames.size()==0){
        return -20;
    }

    HFrame frame = std::move(frames.front());
    frames.pop_front();

    if(frame.isNull()){
        return -30;
    }

    pFrame->copy(frame);

    free(frame.buf.len);
    frame.buf={nullptr,0};

    if(frame.userdata){
        ::free(frame.userdata);
        frame.userdata=nullptr;
    }

    return 0;
}

image.png

2.2 循环效果

播放器.gif

2.3 视频播放不正常的bug修复

上面换个有声音的视频重新播放

image.png

上面因为生产太快,缓存就10帧,满了会替换旧的一帧。。当然如果没播放就丢掉了。。。

hframebuf.h中添加

    std::condition_variable buffer_not_full;
    std::condition_variable buffer_not_empty;

hframebuf.cpp 中修改如下

int HFrameBuf::push(HFrame *pFrame)
{
    std::unique_lock<std::mutex> locker(this->mutex);
    if(pFrame->isNull())
        return -10;

    this->buffer_not_full.wait(locker,[this](){
        return frames.size() < cache_num;
    });

    if(frames.size()>=(size_t)cache_num){
        HFrame frame = std::move(frames.front()); // 移动所有权
        frames.pop_front();  // 先移除,避免析构冲突

        free(frame.buf.len);   // 安全释放内存
        frame.buf = {nullptr, 0}; // 必须置空!

        if (frame.userdata) {
            ::free(frame.userdata);
            frame.userdata = nullptr;
        }
    }
    int ret=0;
    if(isNull()){
        resize(pFrame->buf.len*cache_num);
        ret=1;
    }

    HFrame frame;
    frame.buf.base=alloc(pFrame->buf.len);
    frame.buf.len=pFrame->buf.len;
    frame.copy(*pFrame);
    frames.push_back(frame);

    locker.unlock();
    this->buffer_not_empty.notify_one();
    return ret;
}

int HFrameBuf::pop(HFrame *pFrame)
{
    std::unique_lock<std::mutex> locker(this->mutex);

    if(isNull())
        return -10;


    if(frames.size()==0){
        return -20;
    }

    this->buffer_not_empty.wait(locker, [this] {
        return  !frames.empty();
    });


    HFrame frame = std::move(frames.front());
    frames.pop_front();

    if(frame.isNull()){
        return -30;
    }

    pFrame->copy(frame);

    free(frame.buf.len);
    frame.buf={nullptr,0};

    if(frame.userdata){
        ::free(frame.userdata);
        frame.userdata=nullptr;
    }

    locker.unlock();
    this->buffer_not_full.notify_one();

    return 0;
}

void HFrameBuf::clear()
{
    std::unique_lock<std::mutex> locker(this->mutex);
    frames.clear();
    HRingBuf::clear();
}

更换锁

image.png

2.4 正常播放效果

正常播放2.gif

2.5 以上代码

github.com/xcyxiner/xp…

总的分支 github.com/xcyxiner/xp…

未完待续