- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试解码帧,但内存使用量随着每一帧(更具体地说,每次调用 avcodec_send_packet)而增长,直到最后代码因 bad_alloc 而崩溃。这是基本的解码循环:
int rfret = 0;
while((rfret = av_read_frame(inctx.get(), &packet)) >= 0){
if (packet.stream_index == vstrm_idx) {
//std::cout << "Sending Packet" << std::endl;
int ret = avcodec_send_packet(ctx.get(), &packet);
if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
std::cout << "avcodec_send_packet: " << ret << std::endl;
break;
}
while (ret >= 0) {
//std::cout << "Receiving Frame" << std::endl;
ret = avcodec_receive_frame(ctx.get(), fr);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
//std::cout << "avcodec_receive_frame: " << ret << std::endl;
av_frame_unref(fr);
// av_frame_free(&fr);
break;
}
std::cout << "frame: " << ctx->frame_number << std::endl;
// eventually do something with the frame here...
av_frame_unref(fr);
// av_frame_free(&fr);
}
}
else {
//std::cout << "Not Video" << std::endl;
}
av_packet_unref(&packet);
}
void AVFormatContextDeleter(AVFormatContext* ptr)
{
if (ptr) {
avformat_close_input(&ptr);
}
}
void AVCodecContextDeleter(AVCodecContext* ptr)
{
if (ptr) {
avcodec_free_context(&ptr);
}
}
typedef std::unique_ptr<AVFormatContext, void (*)(AVFormatContext *)> AVFormatContextPtr;
typedef std::unique_ptr<AVCodecContext, void (*)(AVCodecContext *)> AVCodecContextPtr;
AVCodecContextPtr createAvCodecContext(AVCodec *vcodec)
{
AVCodecContextPtr ctx(avcodec_alloc_context3(vcodec), AVCodecContextDeleter);
return ctx;
}
AVFormatContextPtr createFormatContext(const std::string& filename)
{
AVFormatContext* inctxPtr = nullptr;
int ret = avformat_open_input(&inctxPtr, filename.c_str(), nullptr, nullptr);
// int ret = avformat_open_input(&inctx, "D:/Videos/test.mp4", nullptr, nullptr);
if (ret != 0) {
inctxPtr = nullptr;
}
return AVFormatContextPtr(inctxPtr, AVFormatContextDeleter);
}
int testDecode()
{
// open input file context
AVFormatContextPtr inctx = createFormatContext("D:/Videos/Matt Chapman Hi Greg.MOV");
if (!inctx) {
// std::cerr << "fail to avforamt_open_input(\"" << infile << "\"): ret=" << ret;
return 1;
}
// retrieve input stream information
int ret = avformat_find_stream_info(inctx.get(), nullptr);
if (ret < 0) {
//std::cerr << "fail to avformat_find_stream_info: ret=" << ret;
return 2;
}
// find primary video stream
AVCodec* vcodec = nullptr;
const int vstrm_idx = av_find_best_stream(inctx.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &vcodec, 0);
if (vstrm_idx < 0) {
//std::cerr << "fail to av_find_best_stream: vstrm_idx=" << vstrm_idx;
return 3;
}
AVCodecParameters* origin_par = inctx->streams[vstrm_idx]->codecpar;
if (vcodec == nullptr) { // is this even necessary?
vcodec = avcodec_find_decoder(origin_par->codec_id);
if (!vcodec) {
// Can't find decoder
return 4;
}
}
AVCodecContextPtr ctx = createAvCodecContext(vcodec);
if (!ctx) {
return 5;
}
ret = avcodec_parameters_to_context(ctx.get(), origin_par);
if (ret) {
return 6;
}
ret = avcodec_open2(ctx.get(), vcodec, nullptr);
if (ret < 0) {
return 7;
}
//print input video stream informataion
std::cout
//<< "infile: " << infile << "\n"
<< "format: " << inctx->iformat->name << "\n"
<< "vcodec: " << vcodec->name << "\n"
<< "size: " << origin_par->width << 'x' << origin_par->height << "\n"
<< "fps: " << av_q2d(ctx->framerate) << " [fps]\n"
<< "length: " << av_rescale_q(inctx->duration, ctx->time_base, {1,1000}) / 1000. << " [sec]\n"
<< "pixfmt: " << av_get_pix_fmt_name(ctx->pix_fmt) << "\n"
<< "frame: " << inctx->streams[vstrm_idx]->nb_frames << "\n"
<< std::flush;
AVPacket packet;
av_init_packet(&packet);
packet.data = nullptr;
packet.size = 0;
AVFrame *fr = av_frame_alloc();
if (!fr) {
return 8;
}
int rfret = 0;
while((rfret = av_read_frame(inctx.get(), &packet)) >= 0){
if (packet.stream_index == vstrm_idx) {
//std::cout << "Sending Packet" << std::endl;
int ret = avcodec_send_packet(ctx.get(), &packet);
if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
std::cout << "avcodec_send_packet: " << ret << std::endl;
break;
}
while (ret >= 0) {
//std::cout << "Receiving Frame" << std::endl;
ret = avcodec_receive_frame(ctx.get(), fr);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
//std::cout << "avcodec_receive_frame: " << ret << std::endl;
av_frame_unref(fr);
// av_frame_free(&fr);
break;
}
std::cout << "frame: " << ctx->frame_number << std::endl;
// do something with the frame here...
av_frame_unref(fr);
// av_frame_free(&fr);
}
}
else {
//std::cout << "Not Video" << std::endl;
}
av_packet_unref(&packet);
}
std::cout << "RFRET = " << rfret << std::endl;
return 0;
}
最佳答案
我有同样的问题。
在使用 av_frame_unref 之前。
调用 av_freep(buffer->data[0])。
av_frame_unref 未在帧中释放原始数据
例子:
av_freep(&pFrame->data[0]);
av_frame_unref(pFrame);
//av_free(pFrame);
while (Framecheck = av_read_frame(pFormatCtx, &packet) == NULL ) {
if (d_end == true)
break;
if (packet.stream_index == VSI) {
if (bool res = avcodec_send_packet(pVideoCodecCtx, &packet)) {
printf("avcodec_send_packet failed %d %d %d\n", res, AVERROR(EINVAL), AVERROR(ENOMEM));
}
if (bool res = avcodec_receive_frame(pVideoCodecCtx, pVFrame) == 0) {
printf("avcodec_receive failed %d %d %d\n", res, AVERROR(EINVAL), AVERROR(ENOMEM));
}
if (pVFrame->data[0] == NULL && pVFrame->data[1] == NULL && pVFrame->data[2] == NULL)
continue;
else {
YUV_frame = Con_yuv_RGB(pVFrame);
QFrame->push(YUV_frame);
PushCount++;
}
}
Sleep(5);
}
if (Framecheck != true){
av_packet_unref(&packet);
d_end = true;
return true;
if (FrameQueue->size()) {
while (FrameQueue->size() > 0) {
av_freep(&FrameQueue->front());
//av_frame_unref(FrameQueue->front());
av_free(FrameQueue->front());
FrameQueue->pop();
}
}
关于ffmpeg avcodec_send_packet/avcodec_receive_frame 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54282660/
我正在尝试解码帧,但内存使用量随着每一帧(更具体地说,每次调用 avcodec_send_packet)而增长,直到最后代码因 bad_alloc 而崩溃。这是基本的解码循环: int rfret =
我正在使用 ffmpeg 库对 MPEG 传输流中的视频进行解码、缩放和重新编码。我刚刚从源代码重新编译到 v3.3.2,并从旧的 avcodec_decode_video2() API 更改为新的发
我正在尝试从来自 mp4 容器的压缩数据中解码数据包。我已经获得了 AVCodecContext,并从 avreadframe() 获得了数据包。问题是当我尝试解码数据包时,eclipse 一直说无法
以下基于 ffmpeg 的代码片段正在 Windows VC2012、VC20155、VC2017 上构建和运行。 在 Ubuntu LTS 16.04 上使用 gcc,这给了我一些问题,更具体地说,
我正在尝试优化一款播放视频的软件,它在内部使用 FFmpeg 库进行解码。我们发现,在一些大型(4K,60fps)视频中,解码一帧的时间有时比应该显示该帧的时间要长;遗憾的是,由于问题域,简单地缓冲/
Windows 10 x64,ffmpeg: 3.1, 预建 dll 这里绝对是新手。 我正在尝试一个非常基本的案例来解码视频文件中的帧,但每次尝试都失败了。最终的代码片段如下所示: #define
我正在考虑如何设计一个循环,从互联网读取帧,馈送到 ffmpeg 解码器,然后从 ffmpeg 接收以发送到渲染。 考虑这个伪代码循环: while true { auto packet =
我是一名优秀的程序员,十分优秀!