我在内存中有一个完整的视频文件,我想用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?的回答
您必须调用:: avio_alloc_context然后将其设置为AVFormatContext :: pb.
有关详细信息,请参阅我对 How can libavformat be used without using other libav libraries?的回答