[✔️]cocos2dx中播视频的实现思路以及存在的问题

323 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15 天,点击查看活动详情

视频、动画的原理就是逐帧播放

先看一段伪代码:

class VideoPlayer{
    void init(string mp4File) {
        auto textures = ffmpeg.decode(mp4File);
        for(int i=0; i< textures.size(); i++){
           this->_textureMaps[i]=textures.at(i);
        }
    }
    void play() {
        this->_state="playing";
    }
    void update(float dt){
        if(this->_state == "playing"){
            this->frameIndex++;
            auto frame = video->getFrame();
            this->render(frame);
        }
    }
    Texture* getFrame(){
        return this->_textureMaps[this->frameIndex];
    }
}

这段代码是最初我对视频的一个理解,大致的思路就是将视频的每一帧画面都解析出来后,以帧为key,保存到一个map中,当播放的时候,依次按照顺序从头开始依次播放。

这么实现视频播放的确能看到效果,视频的确播放起来了。

存在的问题

上边的思路,其实存在非常多的问题。

内存会爆表

如果一个60fps的10秒时长视频,分辨率是 1920 * 1080 分辨率,如果解析为RGBA8888,大概占用的内存大小为60x10x1920x1080x4字节这么大,当然你可以给视频减配,但是这个问题仍旧存在,本质是缓存cache导致的。

导致严重的卡顿

因为视频的解码是一个密集运算的逻辑,当然也可以通过多线程解决这个问题。

播放速率

每一帧所处的时间,在解码结果里面是有这个信息的,因为播放依赖update驱动,需要自己根据update的dt参数,自己计算当前走到了第几帧,这里面就牵扯到了同步的问题,有很多思路,后续会逐步展开。

音频怎么同步

上述代码中其实也没有说明音频是如何同步的,在FFMpeg中,音视频都是一个stream,我们需要做的就是拿到这个steam之后,按照自己的需求处理,但是因为音视频的处理方式是不同的,所以这里又牵扯到了同步问题

总结

初次接触音视频开发,可以看到细节还是非常多的,经过我的深入思考和多方面的请教,在主线程中解码视频并立即播放,这种方式存在大量的弊端,所以专业的音视频开发者都不会这么搞,多线程是肯定的,其次,关于cache,一般都会做容量的限制,像伪代码里面这种做法,会被人笑掉大牙的。