c – 使用libav从内存中解码视频文件

我在内存中有一个完整的视频文件,我想用libav来解码整个帧.我该怎么办?关键是我可以使用avformat_open_input()函数直接从文件中读取,但我确实需要从存储在内存中的文件中进行读取.

我的AVIOContext实现:

class AVIOMemContext
{

public:

    AVIOMemContext(char* videoData,const int videoLen)
    {
        // Output buffer
        bufferSize = 32768;
        buffer = static_cast<char*>(av_malloc(bufferSize));

        // Internal buffer
        pos = 0;
        this->videoData = videoData;
        this->videoLen = videoLen;

        ctx_ = avio_alloc_context((unsigned char*) buffer,bufferSize,AVIO_FLAG_READ,this,&AVIOMemContext::read,&AVIOMemContext::write,&AVIOMemContext::seek);
    }

    ~AVIOMemContext()
    {
        av_free(videoData);
    }

    static int read(void *opaque,unsigned char *buf,int buf_size)
    {
        AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque);

        // Read from pos to pos + buf_size
        if (This->pos + buf_size > This->videoLen)
        {
            int len = This->videoLen - This->pos;
            memcpy(buf,This->videoData + This->pos,len);
            return len;
        }
        else
        {
            memcpy(buf,buf_size);
            return buf_size;
        }
    }

    static int write(void *opaque,int buf_size)
    {
        /*
        AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque);
        return fwrite(buf,1,buf_size,This->f_);
        */

        return 0;
    }

    static int64_t seek(void *opaque,int64_t offset,int whence)
    {
        AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque);

        if (offset + whence > This->videoLen)
        {
            This->pos = This->videoLen;

            return -1;
        }
        else
        {
            This->pos = offset + whence;

            return 0;
        }
    }

    AVIOContext *get_avio()
    {
        return ctx_;
    }

private:

    // Output buffer
    int bufferSize;
    char* buffer;

    // Internal buffer
    int pos;
    char* videoData;
    int videoLen;

    AVIOContext* ctx_;

};

我目前的代码

[...]

av_register_all();
avcodec_register_all();

AVFormatContext* context;
AVCodec* pCodec;
AVPacket packet;
AVCodecContext* pCodecCtx;
int video_stream_index;
int res;
int got_picture;

// Init variables and objects
context = avformat_alloc_context();

AVIOMemContext priv_ctx(videoData,videoLen); 
context->pb = priv_ctx.get_avio();

res = avformat_find_stream_info(context,NULL);

if (res < 0)
{
    // Error
    avformat_free_context(context);

    return 0;
}

// Obtain the video stream of the total set of streams
for (unsigned int k = 0; k < context->nb_streams; ++k)
{
    if (context->streams[k]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        video_stream_index = k;
    context->streams[k]->codec->time_base.den = 90000;
}

pCodecCtx = context->streams[video_stream_index]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

avcodec_open(pCodecCtx,pCodec);

//allocate video frame
AVFrame *pFrame = avcodec_alloc_frame();

unsigned int nFrame = 0;

while (av_read_frame(context,&packet) >= 0)

[...]

提前致谢,

迪亚克·佩雷斯

解决方法

您可以创建自己的AVIOContext.
您必须调用:: avio_alloc_context然后将其设置为AVFormatContext :: pb.
有关详细信息,请参阅我对 How can libavformat be used without using other libav libraries?的回答

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...