FFmpeg使用avcodec_decode_video2解码原始缓冲区

时间:2013-12-26 14:51:26

标签: c++ ffmpeg libavcodec

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

1 个答案:

答案 0 :(得分: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;
};

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

与往常一样,如果您发现错误或认为某些内容会更好,那么欢迎提供短信。