gpt4 book ai didi

c++ - libavcodec 返回的损坏的 AVFrame

转载 作者:太空宇宙 更新时间:2023-11-04 13:40:43 24 4
gpt4 key购买 nike

作为一个更大项目的一部分,我正在尝试同时解码多个高清 (1920x1080) 视频流。每个视频流都以原始 yuv420p 格式存储在 AVI 容器中。我有一个 Decoder 类,我从中创建了不同线程中的许多对象(每个线程一个对象)。 Decoder中的两个主要方法是decode()getNextFrame() ,我在下面提供了实现。

当我分离解码逻辑并使用它解码单个流时,一切正常。但是,当我使用多线程代码时,出现段错误并且程序在解码循环的处理代码中崩溃。经过一番调查,我意识到 AVFrame 的数据数组填写getNextFrame()包含超出范围的地址(根据 gdb)。

我真的迷路了!我没有做任何会改变 AVFrame 内容的事情在我的代码中。我尝试访问 AVFrame 的唯一地方是当我调用 sws_scale() 时转换颜色格式,这就是在第二种情况下由于损坏 AVFrame 而发生段错误的地方。 .非常感谢任何关于为什么会发生这种情况的建议。提前致谢。

decode()方法:

void decode() {

QString filename("video.avi");

AVFormatContext* container = 0;

if (avformat_open_input(&container, filename.toStdString().c_str(), NULL, NULL) < 0) {
fprintf(stderr, "Could not open %s\n", filename.toStdString().c_str());
exit(1);
}

if (avformat_find_stream_info(container, NULL) < 0) {
fprintf(stderr, "Could not find file info..\n");
}

// find a video stream
int stream_id = -1;
for (unsigned int i = 0; i < container->nb_streams; i++) {
if (container->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
stream_id = i;
break;
}
}

if (stream_id == -1) {
fprintf(stderr, "Could not find a video stream..\n");
}

av_dump_format(container, stream_id, filename.toStdString().c_str(), false);

// find the appropriate codec and open it
AVCodecContext* codec_context = container->streams[stream_id]->codec; // Get a pointer to the codec context for the video stream

AVCodec* codec = avcodec_find_decoder(codec_context->codec_id); // Find the decoder for the video stream

if (codec == NULL) {
fprintf(stderr, "Could not find a suitable codec..\n");
return -1; // Codec not found
}


// Inform the codec that we can handle truncated bitstreams -- i.e.,
// bitstreams where frame boundaries can fall in the middle of packets
if (codec->capabilities & CODEC_CAP_TRUNCATED)
codec_context->flags |= CODEC_FLAG_TRUNCATED;

fprintf(stderr, "Codec: %s\n", codec->name);

// open the codec
int ret = avcodec_open2(codec_context, codec, NULL);
if (ret < 0) {
fprintf(stderr, "Could not open the needed codec.. Error: %d\n", ret);
return -1;
}


// allocate video frame
AVFrame *frame = avcodec_alloc_frame(); // deprecated, should use av_frame_alloc() instead

if (!frame) {
fprintf(stderr, "Could not allocate video frame..\n");
return -1;
}

int frameNumber = 0;

// as long as there are remaining frames in the stream
while (getNextFrame(container, codec_context, stream_id, frame)) {

// Processing logic here...
// AVFrame data array contains three addresses which are out of range

}

// freeing resources
av_free(frame);

avcodec_close(codec_context);

avformat_close_input(&container);
}

getNextFrame()方法:

bool getNextFrame(AVFormatContext *pFormatCtx,
AVCodecContext *pCodecCtx,
int videoStream,
AVFrame *pFrame) {

uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];

char buf[1024];

int len;

int got_picture;
AVPacket avpkt;

av_init_packet(&avpkt);

memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

// read data from bit stream and store it in the AVPacket object
while(av_read_frame(pFormatCtx, &avpkt) >= 0) {

// check the stream index of the read packet to make sure it is a video stream
if(avpkt.stream_index == videoStream) {

// decode the packet and store the decoded content in the AVFrame object and set the flag if we have a complete decoded picture
avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &avpkt);

// if we have completed decoding an entire picture (frame), return true
if(got_picture) {

av_free_packet(&avpkt);

return true;
}
}

// free the AVPacket object that was allocated by av_read_frame
av_free_packet(&avpkt);
}

return false;

}

锁管理回调函数:

static int lock_call_back(void ** mutex, enum AVLockOp op) {
switch (op) {
case AV_LOCK_CREATE:
*mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
pthread_mutex_init((pthread_mutex_t *)(*mutex), NULL);
break;
case AV_LOCK_OBTAIN:
pthread_mutex_lock((pthread_mutex_t *)(*mutex));
break;
case AV_LOCK_RELEASE:
pthread_mutex_unlock((pthread_mutex_t *)(*mutex));
break;
case AV_LOCK_DESTROY:
pthread_mutex_destroy((pthread_mutex_t *)(*mutex));
free(*mutex);
break;
}

return 0;
}

最佳答案

我找出了问题的原因。就是获取解码帧返回前调用av_free_packet()。我注释掉了那个电话,程序成功了!我仍然不太确定为什么这会影响填充的 AVFrame

我也不确定删除该调用是否会导致我的代码发生内存泄漏。

希望 libavcodec 专家可以阐明这一点并解释我做错了什么。

关于c++ - libavcodec 返回的损坏的 AVFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27702200/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com