- 博客(328)
- 收藏
- 关注
原创 Stagefright 的 Buffer 流转
Stagefright 最复杂、也最容易出 bug 的地方就在这里。在 Stagefright 里,,它同时承载三件事:1. 数据(bitstream / pixel)2. 元数据(timestamp / flags)3. 生命周期控制权(谁能读 / 谁能写 / 何时释放)
2025-12-23 18:15:18
403
原创 DTS和PTS
送给 decoder 的数据:输入顺序 = 编码顺序(decode order)每个 access unit 携带的是 PTS(显示时间)decoder 内部:根据 bitstream(slice / reference / DPB)做 frame reorderdecoder 输出:输出顺序 = 显示顺序(presentation order)输出的 timestamp = 原来就带着的那个 PTS不存在“把 DTS 转成 PTS”的过程。
2025-12-23 17:59:56
355
原创 用大白话来解释OpenGLES3.0渲染管线
为每个片段计算出从顶点着色器传来的各种属性(如颜色、纹理坐标)的平滑过渡值。:例如,进行深度测试,决定这个片段颜色是否应该覆盖缓冲区中已有的像素颜色。计算和输出后续阶段所需的数据,如颜色、纹理坐标等,并传递给光栅化阶段。:对每个片段,使用插值得到的纹理坐标去查询纹理贴图,获得颜色,并输出。等操作,最终输出的是完整的、位于屏幕空间的二维图形轮廓。:“每个像素的纹理处理” —— 抓住了重点,但范围更广。:在此阶段,系统将顶点着色器处理后的顶点,按照指定的。:根据插值得到的纹理坐标,从纹理中取出颜色。
2025-12-23 10:38:46
299
原创 【无标题】
编码 vs. 封装:这些编码标准(H.264, H.265, AV1)生成的码流,都可以封装在你之前学习的MP4、MKV、TS等容器中。在MP4中,H.265的配置信息存放在hvcC盒子中,对应H.264的avcC。数据格式:和H.264一样,H.265也有Annex-B(用于传输,带起始码)和HVCC(用于MP4封装,带长度前缀)两种格式。系统集成:在Android上,硬解H.265通常依赖MediaCodecAPI,由芯片厂商实现。软解(如用FFmpeg的libavcodec)则更通用但更耗电。
2025-12-23 10:34:03
433
原创 其他container
特性MP4MKVF4V核心理念国际标准,严谨模块化开源灵活,高度可扩展基于MP4的Flash专用变种结构基础盒子EBML元素盒子MIME类型video/mp4audio/mp4通常被识别为video/mp4或通常由或处理核心理解:容器的“盒子/原子”结构与Android的“MIME驱动Extractor”机制,共同构成了多媒体处理的基石。ftyp是容器自我声明的起点,系统据此选择正确的“翻译官”。整个识别链条可以总结如下:所以,无论是复杂的MP4还是相对简单的MP3,
2025-12-23 10:23:30
823
原创 Annex-B格式 vs. AVC格式 (AVCC)
编码标准:两者都是H.264/AVC编码。封装格式:RTP传输通常使用Annex-B格式,而MP4文件使用AVC格式。理解这个区别对于处理视频的转封装、流媒体服务和播放器开发至关重要,格式不匹配是导致“能播MP4但不能播同编码RTP流”或“花屏”等问题的常见原因。
2025-12-23 10:12:24
327
原创 OpenGL相关学习
其实我之前对Texture纹理的理解一直是:对像素的最后一步修饰。因为在纹理加入之前,前面其实只有图形,没有图像。但是回忆以前看过的很多代码,它其实具备了一个"framebuffer"的功能,是渲染的目的地。
2025-12-22 11:09:18
125
原创 rtp时间戳
*MP4 timestamp 是“内容时间轴”,RTP timestamp 是“传输中的内容时间轴”。它们都不关心“现在几点”,真正让媒体落到现实时间上的,是 RTCP/NTP。**
2025-12-20 11:19:24
567
原创 Run-Length Encoding(RLE,游程编码)详解
Run-Length Encoding(游程编码)是一种,特别适用于处理包含大量连续重复数据的数据序列。
2025-12-20 11:04:04
431
原创 接上一篇,一般情况下timescale = 90000
音频、视频、字幕都能用同一机制。(解析的时候都换算成具体时间值,就变成同一timescale了)大段相同 delta 可以 run-length 编码。(相比用ns等单位直接存具体时间)播放器解复用 → 计算 → 同步 → drift。这和多媒体系统里见过的很多东西是同源设计。MPEG / 视频系统常用 90kHz。RTP video 也用 90kHz。累计 1 小时误差多大?不同平台浮点表示不同。
2025-12-20 10:59:05
283
原创 stts —— Sample Decoding Time box详解
官方名称作用:建立样本序号到解码时间(DTS)的映射关系核心功能:告诉你每个视频帧/音频样本应该在什么时间被解码重要概念区分:什么时候解码(由stts定义):什么时候显示(由ctts定义,如果存在)对于没有B帧的视频,DTS = PTS// 条目数量for (i=0;i++) {// 连续样本数量// 每个样本的持续时间。
2025-12-20 10:34:25
473
原创 MP4容器里的时间戳详解
MP4 用的是:至少要分清这三个:所有 sample 时间,最终都落在 track timescale 上例如:那就和 RTP video 的 90 kHz 非常像,但语义完全不同。stbl(Sample Table Box)里,真正决定时间的只有三个 box:含义是:这就是“不是逐 sample 存 timestamp”的原因。30 fps 视频,timescale = 90000:计算方式:第 N 个 sample 的 DTS: —— Composition Time Of
2025-12-20 10:23:50
352
原创 extern “C“
extern "C"在 C 调用 C++ 和 C++ 调用 C 的场景下,确实有不同的含义,尽管它们的核心概念都是告诉编译器如何处理符号(即函数名)的方式。
2025-12-20 09:15:42
348
原创 音频方面的一些硬件常识
DMA是高效数据搬运的"搬运工",解放CPUI2S是音频数据的"传输协议",定义格式和时序适合普通立体声应用通过TDM技术扩展通道数,适合专业音频Multi-Channel I2S提供高通道数的物理接口,DMA负责高效搬运大量音频数据,CPU专注于高层音频处理和解码,共同实现高质量、实时的音频体验。这种架构不仅用于音频,类似的设计思想也广泛应用于其他数据流处理场景,如视频流、网络数据包、传感器数据采集等。
2025-12-16 10:33:41
619
原创 软件工程师补充芯片相关知识
特性Power Rail本质关时钟信号关电源供应电源供应网络本身目的降低动态功耗消除动态+静态功耗分配和输送电源电压实现层级RTL/门级,自动系统级,需特殊单元物理设计(布局布线)省电效果中等(只省动态)极强(全消除)不直接省电,是供电基础唤醒延迟极短(1个周期)很长(几千周期)不适用设计复杂性低高非常高(影响芯片成败)类比停掉生产线传送带拉掉整个工厂电闸工厂的输电网和电线Power Rail是“路”是“交通信号灯”(让车流停止),是“收费站闸口”(直接把路封了,彻底没车)。
2025-12-16 10:22:21
707
原创 关于DDR的一些科普
Channel第一级,通常在内存控制器层面。现代系统支持双通道、四通道等。每个通道是独立的数据通路和地址命令总线。你拥有的内存条会安装到不同的通道上,这提供了最顶层的并行性。Rank属于同一个通道内的结构。一个物理内存条(DIMM)上可以有一颗或多颗DRAM芯片。这些芯片并联在一起,共同组成一个数据位宽(如64位)的实体,就是一个Rank。同一个通道内可以有多个Rank(通过片选信号CS_n选择)。访问不同Rank的数据比访问同一Rank内不同Bank的延迟稍高,但可以隐藏预充电等操作。Bank这是。
2025-12-16 10:12:50
712
原创 池化技术的概括
malloc/free 或 new/delete 每次都可能涉及内核调用、锁竞争、碎片整理。对象池 + 线程池 → 避免线程/对象频繁创建销毁带来的锁竞争。:提前分配一批资源,然后重复使用,而不是每次都动态申请和释放。:减少分配/释放的开销、避免内存碎片、提升性能、降低延迟。:分配一块固定大小内存 / N 个对象 / M 个线程。:记录空闲资源、在池满/空时可能扩容或等待。大量小对象频繁申请/释放容易造成碎片。:高频率创建/销毁资源的场景。池化可以直接从预分配的块里拿。:从池里拿一个空闲资源。
2025-11-18 17:44:49
615
原创 NEON intrinsic 的命名
→ 128-bit 寄存器(4 个 float)→ 64-bit 寄存器(2 个 float)所有 NEON intrinsic 函数都以。→ vector duplicate(复制)从内存连续加载一组向量。
2025-11-18 17:32:54
366
原创 使用NEON指令集进行优化
以上是对卷积的优化。如果你一次只处理一个元素:需要 16 次 mul需要 16 次 add需要 16 次 loadCPU 负担重NEON 版本一次处理 4 个元素:4 次 load → 1 次 vld1q4 次 mul → 1 次 vmulq4 次 add → 1 次 vaddq🚀。
2025-11-18 17:29:03
161
原创 关于xrun
period_size 越大 → 每次 IRQ 间隔越长 → 应用必须在 IRQ 前读取 period,否则可能丢帧。当 buffer 空时,DSP 依然写入数据 → buffer 中至少有一个 period 存数据。buffer 空 = 应用没读 → 不会丢数据 → 没有 underrun。buffer 满 = 新数据来不及写 → overrun → 数据丢失。buffer 越大 → 容忍应用读取慢 → 减少 overrun。buffer 满 = 写阻塞 → 不会丢数据。新数据来不及写 → 被丢弃。
2025-11-18 16:44:27
240
原创 关于audio的古老的笔记3
在注意:这里的 frame 指的是“声道打包后的最小单位”,例如 stereo 16bit → frame = 2*2 bytes = 4 bytes。
2025-11-18 11:24:17
335
原创 关于audio的古老的笔记2
参数物理意义DMA 每消耗 period_size frames,就触发一次 IRQring buffer 中 period 的个数,用于双缓冲或多缓冲ring buffer 总容量示例:period_size = 240 frames period_count = 2 buffer_size = 480 frames sample_rate = 48000 Hz latency = 480 / 48000 = 0.01 秒 = 10ms。
2025-11-18 11:19:00
520
原创 关于audio的古老的笔记
如果你在设备上做性能分析 /测延迟 (audio latency) 时,可以根据这些配置算理论延迟。:压缩格式(如 mp3 / AAC /其他 DSP 编码)播放,把压缩交给 DSP 处理,用 fragment 而不是 PCM 连续写。:超低延迟 (超实时) 模式,通常用于 no-IRQ /特殊 use-case,但 buffer 比较大 (总帧数高) 保证稳定。:期望很低延迟,buffer 小 (period 小, count 少),适合对实时性要求高(比如游戏音效、UI 音效)
2025-11-18 10:47:04
573
原创 C2ComponentStore
接口定义(Google AOSP,抽象类)。:厂商实现(Qualcomm,继承并实现 C2ComponentStore,用于硬件 codec)。其他厂商(联发科 MTK、三星 Exynos 等)也会有自己的或,逻辑类似。面向 HAL,封装 AIDL/HIDL,提供 API 给 framework 使用。就像「钥匙」,能打开 HAL 的 codec 工厂和组件。CCodec面向 Stagefright/MediaCodec 层,是 Codec2.0 的插件。内部依赖去真正调用 HAL。
2025-08-21 22:29:32
1009
原创 OMX_UseBuffer和OMX_AllocateBuffer的区别
你(客户端)分配内存,然后交给 OMX 使用。OMX 组件自己分配内存,你只拿到指针。OMX 自己调用malloc或 ION(甚至 gralloc)来分配内存你只拿到 buffer header,内部 buffer 归组件所有你先分配好内存(如malloc()),然后告诉 OMX 用这块内存组件不会再调用自己的分配器,而是直接使用你提供的 buffer使用让事情简单,使用提高性能和灵活性,但你要管理好 buffer 生命周期与内存属性。可被 DMA 或 IOMMU 访问(ION 或物理地址)
2025-08-06 08:19:23
661
原创 IntraRefreshVOP是什么
IntraRefreshVOP 是一种特殊的帧内刷新方式,通常用于 MPEG-4 或特定硬件平台上,能在不插入完整 I 帧的前提下刷新一部分帧内容为帧内编码,从而达到节省码率和提升抗误码能力的目的。如你使用的是 Qualcomm 平台,并看到这个参数出现在 HAL 或 OpenMAX 中,可能是历史兼容逻辑或者平台特定优化路径。
2025-08-06 08:07:08
3740
原创 QOMX_INDEXEXTRADATATYPE.nIndex
中的一些枚举值,这些值用于配置视频编码器在每帧输出中附带的,以便后续模块(如帧处理器、播放器、网络传输等)可以获取更多关于帧的信息。这些是(QOMX - Qualcomm OMX),在使用 Qualcomm 视频编码器(如 Snapdragon 平台)时非常常见。
2025-08-06 07:58:15
676
原创 OMX_IndexParamVideoIntraRefresh(output port)
帧内刷新是一种视频压缩技术,用于替代频繁插入完整的 I 帧,以降低码率波动,同时还能让码流具备较好的错误恢复能力(例如在网络丢包时)。编码器按照固定顺序周期性地将一些宏块(macroblocks)刷新为帧内编码(类似于局部 I 帧)。:通常是视频编码器的输出端口(即 compressed stream output)。综合使用两种策略,有更强的鲁棒性,但可能稍微增加编码复杂度。编码器根据图像内容或错误概率判断哪些宏块需要帧内刷新。枚举值),用于配置视频编码器的。:指定帧内刷新方式,下面详细解释。
2025-08-06 07:46:17
400
原创 Default node,Bypassable node,Inplace node
这几个术语(Default Node、Bypassable Node、Inplace Node)是指。
2025-07-23 09:58:26
445
原创 使用错误的 gralloc usage flag甚至会掉帧
Gralloc(Graphics Allocation)是 Android HAL 中用于 GPU/Camera/Display/Codec 等模块分配图形 buffer 的服务。这些 buffer 的用途千差万别,所以需要使用一组标志()告诉 gralloc:谁会访问这个 buffer(CPU 还是 GPU 还是硬件 codec)?怎么访问(读?写?频繁?偶尔?是否需要物理连续内存?是否用于 DMA?缺少正确的。
2025-07-23 09:36:05
488
原创 CHI定制
Pipeline 决定了一帧图像是怎么被处理的,比如:是否经过 IPE / BPS / FD / JPEG 节点是否分成多个输出路径(例如 Preview + Snapshot)
2025-07-23 08:38:54
433
原创 多camera同步
层级同步目标实现机制Sensor 层同步快门采集HAL Session 层同步 Request同步提交、GroupID、DeferThreadCHI Usecase 层同步结果处理pipeline join、统一 output 拼接pacer/follower 模型虽然是来自 display,但它的思想在 camera 中同样存在,只是换了名字和实现机制。
2025-07-23 08:33:44
1472
原创 compare_exchange_weak详解
对于类型的变量atomic_var特点内容功能CAS(Compare And Swap):相等就替换类型weak允许虚假失败,适合 retry 循环关键参数expected是传引用,会在失败时被更新用途lock-free 数据结构(栈、队列、哈希表)和锁对比更高性能、更复杂、更容易出错常见错误忘了处理 expected 被修改、忽视内存序影响会自动更新expected// 读当前 head!// CAS 尝试替换 head为什么不重新load()也可以继续工作?
2025-06-26 10:54:16
1092
原创 C++内存序memory_order
C++ 原子操作提供,分别控制编译器和 CPU 如何对内存操作进行重排序优化,确保并发程序在多线程之间的行为可控、正确。
2025-06-25 14:21:26
982
原创 std::atomic_flag实现自旋锁
代码解释:这段代码实现了一个简单的自旋锁(spinlock),其中用到了,它是 C++ 提供的最轻量级的原子类型之一,专门用于实现自旋锁等低级同步原语。
2025-06-25 14:06:30
290
原创 对future,promise,async,packaged_task的彻底理解
future的引入是为了解决thread并不提供直接接收返回值的机制的问题。的设计理念是:只负责调度和执行线程函数,不负责管理其结果。所以,如果你想要线程函数返回值,你需要使用 std::future配合 std::async或 std::promise来实现。
2025-06-18 10:48:13
373
原创 为什么 C++ 的 const 成员函数也要加锁?mutable 的使用详解
如果另一个线程正在调用 push(),你这边的 empty() 就可能访问到未同步的状态,从而导致数据竞争、未定义行为。// ✅ mutable 允许在 const 函数中加锁。std::mutex 是可变状态,需要 mutable 才能在 const 函数里使用;C++ 官方文档:mutable、std::mutex、std::lock_guard。你在 const 成员函数里调用它会报错,因为你不能修改非 mutable 成员。std::mutex::lock() 是非 const 的成员函数;
2025-06-18 10:00:49
595
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅