Supose Ich habe eine ganze Videodatei im Speicher und möchte mit libav die ganzen Bilder dekodieren. Wie soll ich das machen? Der Punkt ist, dass ich es lesen kann direkt aus einer Datei mit avformat_open_input() -Funktion, aber ich muss es tun, aus einer Datei, die im Speicher gespeichert ist.Eine Videodatei mit libav aus dem Speicher dekodieren
Meine AVIOContext Implementierung:
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_;
};
Mein aktueller Code:
[...]
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)
[...]
Vielen Dank im Voraus,
Dídac Pérez
Vielen Dank für Ihre Hilfe, ich werde es jetzt versuchen. –
Ich habe meinen eigenen AVIOContext erstellt, aber die App stürzt ab in avformat_find_stream_info() –