FFmpeg使用avcodec_decode_video2解码原始缓冲区

Mar*_*ott 6 c++ ffmpeg libavcodec

我收到一个h264流,我至少知道一帧的大小.流正好进入,因为我可以将其存储在文件中并使用vlc进行播放.回放文件对我来说没问题,因为我包含了libavformat.但是libavformat给了我一个AVPacket,我可以直接给avogramc_decode_video2.在这种情况下,我得到了一个字节流.如何将原始h264流提供给avcodec_decode_video2?如何将数据包装到AVPacket中.VLC不需要猜测任何数据.

Mar*_*ott 6

解码流或多或少都很容易.这段代码对我来说非常合适:

class ffmpegstreamdestination
{
public:
    ffmpegstreamdestination(AVCodecID decoder): 
    {       
        m_pCodec= avcodec_find_decoder(decoder);
        m_pCodecCtx = avcodec_alloc_context3(m_pCodec);
        avcodec_open2(m_pCodecCtx,m_pCodec,0);
        m_pFrame=avcodec_alloc_frame();
    }

    ~ffmpegstreamdestination()
    {
        av_free(m_pFrame);
        avcodec_close(m_pCodecCtx);
    }

    void decodeStreamData(unsigned char * pData, size_t sz)
    {
        AVPacket        packet;
        av_init_packet(&packet);

        packet.data=pData;
        packet.size=(int)sz;
        int framefinished=0;
        int nres=avcodec_decode_video2(m_pCodecCtx,m_pFrame,&framefinished,&packet);

        if(framefinished)
        {
                   // do the yuv magic and call a consumer
        }

        return;
    }

protected:
    AVCodecContext  *m_pCodecCtx;
    AVCodec         *m_pCodec;
    AVFrame         *m_pFrame;
};
Run Code Online (Sandbox Code Playgroud)

调用decodeStreamData期望数据为帧.你必须在你的流中搜索NAL(或多或少的标题幻数),它在h264情况下为0x00000001.它是一个帧的开头.填充AVPacket并不像我想象的那样有问题.如果您没有这些信息,可以将其中的属性保留为av_init_packet中的init.例如,如果您具有不同的帧速率,则只会出现问题.

和往常一样,如果你看到一个错误或认为某些东西会更好地工作,那么欢迎发短信.