对avformat_find_stream_info的调用阻止对简单PNG图像进行解码
Call to avformat_find_stream_info prevents decoding of simple PNG image?
我在用libav解码一个简单的PNG图像时遇到了一个问题。在对avcodec_decode_video2
的调用之后的decode_ok
标志被设置为0
,即使分组包含整个图像。通过一些实验,我已经确定了这个问题,它似乎与调用avformat_find_stream_info
有关。如果调用被删除,则示例将成功运行。但是,我希望对其他媒体使用相同的代码,并且在文档中建议调用avformat_find_stream_info
。
下面的最小示例说明了这种行为(不幸的是仍然有点长):
#include <iostream>
extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
// Nothing to see here, it's just a helper function
AVCodecContext* open(AVMediaType mediaType, AVFormatContext* formatContext)
{
auto ret = 0;
if ((ret = av_find_best_stream(formatContext, mediaType, -1, -1, nullptr, 0)) < 0)
{
std::cerr << "Failed to find video stream." << std::endl;
return nullptr;
}
auto codecContext = formatContext->streams[ret]->codec;
auto codec = avcodec_find_decoder(codecContext->codec_id);
if (!codec)
{
std::cerr << "Failed to find codec." << std::endl;
return nullptr;
}
if ((ret = avcodec_open2(codecContext, codec, nullptr)) != 0)
{
std::cerr << "Failed to open codec context." << std::endl;
return nullptr;
}
return codecContext;
}
// All the interesting bits are here
int main(int argc, char* argv[])
{
auto path = "/path/to/test.png"; // Replace with valid path to PNG
auto ret = 0;
av_log_set_level(AV_LOG_DEBUG);
av_register_all();
avcodec_register_all();
auto formatContext = avformat_alloc_context();
if ((ret = avformat_open_input(&formatContext, path, NULL, NULL)) != 0)
{
std::cerr << "Failed to open input." << std::endl;
return -1;
}
av_dump_format(formatContext, 0, path, 0);
//*/ Info is successfully found, but interferes with decoding
if((ret = avformat_find_stream_info(formatContext, nullptr)) < 0)
{
std::cerr << "Failed to find stream info." << std::endl;
return -1;
}
av_dump_format(formatContext, 0, path, 0);
//*/
auto codecContext = open(AVMEDIA_TYPE_VIDEO, formatContext);
AVPacket packet;
av_init_packet(&packet);
if ((ret = av_read_frame(formatContext, &packet)) < 0)
{
std::cerr << "Failed to read frame." << std::endl;
return -1;
}
auto frame = av_frame_alloc();
auto decode_ok = 0;
if ((ret = avcodec_decode_video2(codecContext, frame, &decode_ok, &packet)) < 0 || !decode_ok)
{
std::cerr << "Failed to decode frame." << std::endl;
return -1;
}
av_frame_free(&frame);
av_free_packet(&packet);
avcodec_close(codecContext);
avformat_close_input(&formatContext);
av_free(formatContext);
return 0;
}
avformat_find_stream_info
打印前的格式转储:
输入#0,image2,从'/path/to/test.png':持续时间:N/A,比特率:N/A流#0:0,0,1/25:视频:png,25 tbn
avformat_find_stream_info
打印后的格式转储:
输入#0,image2,来自'/path/to/test.png':持续时间:00:00:00-04,开始时间:0.000000,比特率:N/A流#0:0,1,1/25:视频:png,rgba,512x512[SAR 3780:3780 DAR 1:1],1/25,25 tbr,25 tbn,25 tbc
因此,看起来搜索会产生潜在的有用信息。有人能阐明这个问题吗?其他图像格式似乎可以正常工作。我认为这是一个简单的用户错误,而不是一个bug。
编辑:调试日志记录已启用,但PNG解码器不会产生大量输出。我还尝试过设置一个自定义日志回调。
当解码成功时,如果不调用avformat_find_stream_info
,我会得到以下结果:
统计信息:52125字节读取,0次查找
当解码失败时,我会调用avformat_find_stream_info
得到以下结果:
统计数据:52125字节读取,0次查找检测到8个逻辑核心
图像为52125字节,因此读取整个文件。我不确定逻辑核心指的是什么。
libav中似乎存在一些多线程问题。禁用多线程可以修复此问题。
codecContext->thread_count=1;
if ((ret = avcodec_open2(codecContext, codec, nullptr)) < 0)
{
std::cerr << "Failed to open codec context." << std::endl;
return nullptr;
}
相关文章:
- Qt-png图像未显示在部署应用程序中
- C++gdi::内存中的位图到PNG图像
- 当我调用它来解码 Blob 对象中的 png 图像时,"Magick++::readImages"引发警告
- 为什么PNG图像的stdout有时会在printf中刷新图像的一半
- 为嵌入式系统加载 png 图像
- OPENCV IMREAD 8BPP PNG图像错误
- OpenGL - SOIL 不会加载 JPG 或 PNG 图像
- 如何使用OPENCV C 将24位转换为8位深度PNG图像
- 如何使用GDI 显示具有25%不透明度的PNG图像?(MFC)
- 在窗口上绘制 PNG 图像 - C++ SDL 2.0
- .png图像信息
- 如何使用索引的 PNG 图像作为 SDL2/OpenGL 的纹理
- 使用 Allegro 5 加载.png图像文件
- 在 C 或 C++ 中将 JPEG 或 PNG 图像作为像素数据打开
- 为什么我的libharu pdf过大,带有.png图像
- png图像的大小
- 读取尺寸大于200x200像素的png图像时,0x77662D37(ntdll.dll)处出现未处理的异常
- 如何在boost::gil中使用alpha运河调整png图像的大小
- 在c++中嵌入PNG图像作为矢量或数组
- 使背景的QLabel png图像透明的设计时间