当前位置: 首页 > news >正文

avcodec_send_packet函数阻塞

用ffmpeg4.1.4开发一个播放器,解码过程如下,在每个函数前设置标志,测试发现程序阻塞在avcodec_send_packet函数。

while(true){av_read_frameavcodec_send_packetavcodec_receive_frameav_packet_unref
}

解释如下:

avcodec_send_packetavcodec_receive_frame 的工作原理是,avcodec_send_packet 向解码器发送压缩数据包,而 avcodec_receive_frame 从解码器接收解码后的帧。解码器内部有一个缓冲区,用于存储解码过程中间的数据。如果缓冲区已满(即没有足够的空间来存储新的数据包),avcodec_send_packet 就会阻塞,直到有足够的空间。

我用的是处理器是rk3288,后台打印信息如下:

[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 1615 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 2107 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 2064 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 1504 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 2588 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 1642 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 1721 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Received a frame.
[h264_rkmpp @ 0xa5795e20] Wrote 1437 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2307 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1427 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1638 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2303 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1342 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2193 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1567 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2247 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1396 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2375 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1520 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1663 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2273 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1288 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 2340 bytes to decoder
[h264_rkmpp @ 0xa5795e20] Wrote 1399 bytes to decoder

avcodec_send_packe函数为什么会“get a frame”呢?源码如下,猜测是阻塞到这里

int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
{AVCodecInternal *avci = avctx->internal;int ret;if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))return AVERROR(EINVAL);if (avctx->internal->draining)return AVERROR_EOF;if (avpkt && !avpkt->size && avpkt->data)return AVERROR(EINVAL);av_packet_unref(avci->buffer_pkt);if (avpkt && (avpkt->data || avpkt->side_data_elems)) {ret = av_packet_ref(avci->buffer_pkt, avpkt);if (ret < 0)return ret;}ret = av_bsf_send_packet(avci->filter.bsfs[0], avci->buffer_pkt);if (ret < 0) {av_packet_unref(avci->buffer_pkt);return ret;}if (!avci->buffer_frame->buf[0]) {ret = decode_receive_frame_internal(avctx, avci->buffer_frame);if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)return ret;}return 0;
}static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{int ret;while (!frame->buf[0]) {ret = decode_simple_internal(avctx, frame);if (ret < 0)return ret;}return 0;
}

解决方法:

1、在调用 avcodec_send_packet 之前,可以先调用 avcodec_receive_frame,即使你不确定是否有帧可以接收。这有助于清理缓冲区。

2、在while循环中等待avcodec_receive_frame

    ret = avcodec_send_packet(codec_ctx, packet); while (ret >= 0) {AVFrame *frame = av_frame_alloc();if (!frame) {// 处理内存分配错误return AVERROR(ENOMEM);}ret = avcodec_receive_frame(codec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {// 没有更多帧可以接收,退出循环av_frame_free(&frame);break;} else if (ret < 0) {// 处理接收帧错误av_frame_free(&frame);return ret;}}

3、正常情况下向解码器发送一包数据会收到一个解码后的帧,因此增加一个检测机制,当多次发送数据包但没有收到解码帧后则重置解码器。

void reset_decoder(AVCodecContext* codecContext) {// 刷新解码器缓冲区avcodec_flush_buffers(codecContext);// 关闭解码器avcodec_close(codecContext);// 重新打开解码器if (avcodec_open2(codecContext, codecContext->codec, nullptr) < 0) {std::cerr << "Could not re-open codec" << std::endl;}
}

相关文章:

avcodec_send_packet函数阻塞

用ffmpeg4.1.4开发一个播放器&#xff0c;解码过程如下&#xff0c;在每个函数前设置标志&#xff0c;测试发现程序阻塞在avcodec_send_packet函数。 while(true){av_read_frameavcodec_send_packetavcodec_receive_frameav_packet_unref } 解释如下&#xff1a; avcodec_se…...

一个parquet-go例子

一个parquet-go例子 使用go读写parquet&#xff0c;使用到了框架github.com/xitongsys/parquet-go 代码: package mainimport ("log""time""github.com/xitongsys/parquet-go-source/local""github.com/xitongsys/parquet-go/parquet&qu…...

扩散模型笔记

长参数“T”决定了生成全噪声图像所需的步长。在本文中&#xff0c;该参数被设置为1000&#xff0c;这可能显得很大。我们真的需要为数据集中的每个原始图像创建1000个噪声图像吗?马尔可夫链方面被证明有助于解决这个问题。由于我们只需要上一步的图像来预测下一步&#xff0c…...

上海-LM科技(面经)

上海-LM科技 hr电话面 个人简介 个人信息的询问 是否知道芋道框架 技术面 算法题 14. 最长公共前缀&#xff08;写出来即可&#xff09; 聊一下Docker Docker核心概念总结Docker实战 聊一下AOP Spring AOP详解 聊一下JWT JWT 基础概念详解JWT 身份认证优缺点分析 Spring…...

用 Echarts 画折线图

https://andi.cn/page/621503.html...

C++的map / multimap容器

一、介绍 在C的map / multimap容器中&#xff0c;所有的元素均是pair类型&#xff08;有关pair类型可以参考我之前写的 《C的set / multiset容器》的3.2中有介绍到&#xff09;。 每对pair的第一个元素被称为关键字key&#xff0c;第二个元素被称为值value。因此&#xff0c;ma…...

双向链表 -- 详细理解和实现

欢迎光顾我的homepage 前言 双向链表是一种带头双向循环的链表。在双向链表中&#xff0c;首先存在着一个头结点&#xff1b;其次每个节点有指向下一个节点的指针next 和指向上一个节点的指针prev &#xff1b…...

WebGIS面试题

文章目录 1. 前端1.1. 选择器的优先级1.2. CSS 中它的布局有哪些&#xff1f;1.3. CSS3 的新特性1.4. CSS 的两种盒子模型1.5. CSS 的伪元素选择器和伪类选择器有哪些&#xff1f;1.6. ES6 的新特性1.7. 谈谈你对 promise 的理解1.8. 简单说一下原型链1.9. 简单说一下深浅拷贝1…...

代码随想录算法训练营:21/60

非科班学习算法day21 | LeetCode669:修剪二叉搜索树 &#xff0c;Leetcode108:将有序数组转换为二叉搜索树 &#xff0c;Leetcode538:把二叉搜索树转换为累加树 介绍 包含LC的两道题目&#xff0c;还有相应概念的补充。 相关图解和更多版本&#xff1a; 代码随想录 (progra…...

数据结构——二叉树之c语言实现堆与堆排序

目录 前言&#xff1a; 1.二叉树的概念及结构 1.1 特殊的二叉树 1.2 二叉树的存储结构 1.顺序存储 2.链式存储 2. 二叉树的顺序结构及实现 2.1 堆的概念 ​编辑 2.2 堆的创建 3.堆的实现 3.1 堆的初始化和销毁 初始化&#xff1a; 销毁&#xff1a; 插入&…...

#数据结构 链表

单向链表 1. 概念 单向链表 单向循环链表 双向链表 双向循环链表 解决&#xff1a;长度固定的问题&#xff0c;插入和删除麻烦的问题 1、逻辑结构&#xff1a; 线性结构 2、存储结构&#xff1a; 链式存储 链表就是将 结点 用链串起来的线性表&#xff0c;链就是 结点 中的…...

单片机软件架构连载(4)-结构体

枚举、指针、结构体&#xff0c;我愿称为C语言"三板斧"。 用人话来讲&#xff0c;几乎所有c语言高阶编程&#xff0c;都离不开这这3个知识点的应用。 今天站在实际产品常用的角度&#xff0c;给大家讲一下结构体。 1.结构体概念 结构体可以用来构建更复杂的数据结…...

工厂方法模式在金融业务中的应用及其框架实现

引言 工厂方法模式&#xff08;Factory Method Pattern&#xff09;是一种创建型设计模式&#xff0c;它定义了一个创建对象的接口&#xff0c;但由子类决定实例化哪一个类。工厂方法模式使得类的实例化延迟到子类。在金融业务中&#xff0c;工厂方法模式可以用于创建不同类型…...

python库(6):Pygments库

1 Pygments介绍 在软件开发和文档编写中&#xff0c;代码的可读性是至关重要的一环。无论是在博客文章、技术文档还是教程中&#xff0c;通过代码高亮可以使程序代码更加清晰和易于理解。而在Python世界中&#xff0c;Pygments库就是这样一个强大的工具&#xff0c;它能够将各…...

金斗云 HKMP智慧商业软件 任意用户创建漏洞复现

0x01 产品简介 金斗云智慧商业软件是一款功能强大、易于使用的智慧管理系统,通过智能化的管理工具,帮助企业实现高效经营、优化流程、降低成本,并提升客户体验。无论是珠宝门店、4S店还是其他零售、服务行业,金斗云都能提供量身定制的解决方案,助力企业实现数字化转型和智…...

前端JS特效第24集:jquery css3实现瀑布流照片墙特效

jquery css3实现瀑布流照片墙特效&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8" /> <title>jquerycss3实现瀑…...

区块链论文速读A会-ISSTA 2023(2/2)如何检测DeFi协议中的价格操纵漏洞

Conference&#xff1a;ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA) CCF level&#xff1a;CCF A Categories&#xff1a;Software Engineering/System Software/Programming Languages Year&#xff1a;2023 第1~5篇区块链文章 请点击此…...

权力之望怎么下载客户端 权力之望一键下载

《权力之望》是一款由NX3 Games开发、Smilegate发行的多人在线动作MMORPG游戏。这款游戏最大的特点是高度的自由度和丰富的角色定制选项。我们在游戏中不仅可以自由更换武器&#xff0c;而且游戏还提供了54种能力和60多种职业选择&#xff0c;让我们可以根据自己的游戏风格和喜…...

Oracle PL/SQL 循环批量执行存储过程

1. 查询存储过程 根据数据字典USER_OBJECTS查询出所有存储过程。 2. 动态拼接字符串&#xff08;参数等&#xff09; 根据数据字典USER_ARGUMENTS动态拼接参数。 3. 动态执行 利用EXECUTE IMMEDIATE动态执行无名块。 4. 输出执行信息 利用DBMS_OUTPUT.PUT_LINE输出执行成功与…...

kafka 生产者

生产者 生产者负责创建消息&#xff0c;然后将其投递到Kafka中。 负载均衡 轮询策略。随机策略。按照 key 进行hash。 Kafka 的默认分区策略&#xff1a;如果指定了 key&#xff0c;key 相同的消息会发送到同一个分区&#xff08;分区有序&#xff09;&#xff1b;如果没有…...

保姆级教程:在Ubuntu 24.04上用QEMU桥接网络,让虚拟机秒连外网

在Ubuntu 24.04上实现QEMU虚拟机与宿主机网络互通的终极指南 对于需要在本地环境测试国产操作系统或运行隔离开发环境的开发者来说&#xff0c;QEMU虚拟化方案因其轻量高效而备受青睐。但让虚拟机与宿主机网络互通往往成为新手的第一道门槛。本文将彻底解决这个问题——通过桥接…...

AI报告文档审核赋能数据不出域:IACheck重构机械制造行业本地化质量管控体系

在机械制造行业不断推进数字化与智能化转型的过程中&#xff0c;“数据不出域”逐渐从合规要求演变为一种核心能力&#xff0c;即在保障数据安全的前提下&#xff0c;实现数据的高效利用与价值转化&#xff0c;而在这一背景下&#xff0c;检测报告作为连接生产过程与质量评估的…...

Evolutionary Architecture by Example:如何避免过度工程化陷阱

Evolutionary Architecture by Example&#xff1a;如何避免过度工程化陷阱 【免费下载链接】evolutionary-architecture-by-example Navigate the complex landscape of .NET software architecture with our step-by-step, story-like guide. Unpack the interplay between m…...

FinalShell v4.5.12 安装避坑指南:为什么你的远程连接总是失败?

FinalShell 4.5.12 高效配置手册&#xff1a;从安装到稳定连接的进阶实践 远程终端工具的选择往往决定了运维效率的天花板。作为一款集SSH连接、文件传输、性能监控于一体的全能型工具&#xff0c;FinalShell近年来在开发者社区中积累了不错的口碑。但不少用户在初次接触时&…...

解决Legado书源调试难题:从问题诊断到环境优化的完整指南

解决Legado书源调试难题&#xff1a;从问题诊断到环境优化的完整指南 【免费下载链接】legado Legado 3.0 Book Reader with powerful controls & full functions❤️阅读3.0, 阅读是一款可以自定义来源阅读网络内容的工具&#xff0c;为广大网络文学爱好者提供一种方便、快…...

实战教你用美股api获取实时行情与报价

前几天我在整理投资数据&#xff0c;突然发现自己平时关注的几支热门美股&#xff0c;价格波动比新闻还快。光靠网页刷新完全跟不上节奏&#xff0c;尤其是NVDA、META这样的科技股&#xff0c;几分钟就能有明显变化。想随时看到最新行情&#xff0c;又不想盯着网页刷新&#xf…...

深入RK3588 NPU架构:从NVDLA远亲到CNN加速器的设计取舍与性能真相

RK3588 NPU架构深度解构&#xff1a;CNN加速器的设计哲学与性能边界 当一块指甲盖大小的芯片宣称能提供6 TOPS的AI算力时&#xff0c;我们不禁要问&#xff1a;这数字背后隐藏着怎样的工程智慧与妥协&#xff1f;RK3588的NPU模块正引发这样的思考——它既非纯粹的学术创新&…...

GD32F4xx GPIO实战:用按键控制LED,详解输入输出配置与防抖处理

GD32F4xx GPIO实战&#xff1a;从按键消抖到LED控制的完整设计指南 在嵌入式开发中&#xff0c;GPIO&#xff08;通用输入输出&#xff09;是最基础却至关重要的外设模块。对于GD32F4xx系列微控制器而言&#xff0c;掌握GPIO的高效配置不仅关乎功能实现&#xff0c;更直接影响系…...

无人机飞控实战:四元数微分方程在PX4中的实现与调参技巧

无人机飞控实战&#xff1a;四元数微分方程在PX4中的实现与调参技巧 当无人机在复杂环境中执行高速机动时&#xff0c;传统欧拉角描述姿态会出现万向节锁死现象。去年调试一台行业级六旋翼时&#xff0c;就曾遇到俯仰角接近90时控制器突然发散的情况——这正是欧拉角奇异点的典…...

StructBERT中文相似度模型保姆级教学:如何用TSNE可视化高维句向量空间分布

StructBERT中文相似度模型保姆级教学&#xff1a;如何用TSNE可视化高维句向量空间分布 1. 引言&#xff1a;为什么需要可视化句向量&#xff1f; 当你使用StructBERT这样的模型计算句子相似度时&#xff0c;你得到的只是一个0到1之间的数字。这个数字告诉你两个句子“有多像”…...