Декодируйте видеофайл из памяти, используя 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, This->videoData + This->pos, buf_size);
return buf_size;
}
}

static int write(void *opaque, unsigned char *buf, 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)

[...]

Заранее спасибо,

Дидак Перес

7

Решение

Вы можете создать свой собственный AVIOContext,
Вы должны позвонить ::avio_alloc_context затем установите его AVFormatContext::pb,
Подробнее см. Мой ответ на Как можно использовать libavformat без использования других библиотек libav?

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]