尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Linux PipeWire深度解析之pw_stream_return_buffer调用流程与实战(五十一)

Linux PipeWire深度解析之pw_stream_return_buffer调用流程与实战(五十一) 简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1.前言要点概括2.应用场景与用法函数原型参数说明返回值应用场景3.调用流程剖析3.1核心步骤3.2调用流程图3.3生命周期图4.实战应用案例5.一句话总结1.前言本篇目的Linux PipeWire深度解析之pw_stream_return_buffer调用流程与实战。要点概括核心功能把已经dequeue但不准备作为有效媒体数据提交的pw_buffer退回给PipeWireStream。工作机制应用从Stream中取出Buffer后如果发现当前Buffer不适合继续处理或者本周期决定放弃提交就调用pw_stream_return_buffer把Buffer还回Stream内部队列。典型用途Buffer检查失败、数据源不足、业务决定丢弃本周期输出、采集数据不再处理、异常路径下避免Buffer泄漏。pw_stream_return_buffer的本质不是“提交媒体数据”而是“退回Buffer使用权”。它解决的问题是应用已经通过pw_stream_dequeue_buffer拿到了Buffer但后续判断发现不应该把它作为正常数据送入PipeWire图调度此时需要把Buffer还回去。它和pw_stream_queue_buffer的区别非常关键。queue_buffer表示Buffer已经完成正常处理可以进入后续媒体链路return_buffer表示放弃本次使用只是把Buffer归还给Stream不表达有效媒体数据提交语义。它也不是内存释放函数。Buffer内存仍然由PipeWireStream管理应用不能手动释放pw_buffer也不能在return之后继续访问该Buffer。return之后Buffer所有权重新回到PipeWire后续可能被再次dequeue复用。2.应用场景与用法pw_stream_return_buffer是PipeWireStream API中用于退回已取出Buffer的接口。它位于PipeWireStream数据路径的异常分支或放弃分支中。正常媒体数据处理路径通常是dequeue、处理、queue而return_buffer处理的是dequeue之后不想提交有效数据的场景。pw_stream_return_buffer用于把已经dequeue但不准备提交的Buffer退回给PipeWireStream。函数原型intpw_stream_return_buffer(structpw_stream*stream,structpw_buffer*buffer);参数说明structpw_stream*stream;stream表示当前Buffer所属的PipeWireStream对象。该Stream必须是有效Stream并且必须和buffer来源一致。不能从一个Stream中dequeue出Buffer再通过另一个Stream调用return_buffer。structpw_buffer*buffer;buffer表示需要退回的pw_buffer对象。该Buffer通常来自同一个Stream的pw_stream_dequeue_buffer。调用return_buffer之后应用不应继续读取、写入或修改该Buffer中的spa_buffer、spa_data、spa_chunk等字段。返回值成功时通常返回0。失败时返回负值错误码。工程代码中应按“小于0为失败”的方式处理。return_buffer失败通常说明调用关系不正确例如Stream无效、Buffer无效、Buffer不属于当前Stream或者Buffer当前状态不允许被退回。应用场景第一类场景是Buffer检查失败。应用dequeue到Buffer后发现data-data为空、data-chunk为空、maxsize不足、格式状态不符合预期此时不应把该Buffer当作有效数据queue出去可以直接return_buffer退回。第二类场景是播放流数据不足。例如播放器、网络音频、解码器或环形缓冲区当前没有足够PCM数据。如果业务策略不是补静音而是放弃本周期提交就可以return_buffer退回Buffer。第三类场景是采集数据丢弃。采集流中如果当前输入数据不再需要处理例如录音暂停、上层丢弃、算法模块临时不可用可以在读取前或读取后退回Buffer避免应用侧长期占用Buffer。第四类场景是异常路径清理。实时音视频处理代码中dequeue之后可能出现业务判断失败、格式变化、状态切换、对象销毁前保护等情况。return_buffer可以保证Buffer及时回到Stream避免Buffer池被应用侧耗尽。3.调用流程剖析3.1核心步骤1.应用创建pw_stream对象并注册process事件回调。2.应用调用pw_stream_connect连接Stream完成格式协商和Buffer协商。3.PipeWire通过add_buffer事件把Buffer加入Stream内部管理。4.PipeWire图调度触发process回调。5.应用调用pw_stream_dequeue_buffer取出一个pw_buffer。6.应用检查Buffer状态、业务状态、数据源状态或格式状态。7.如果Buffer可以正常处理则进入常规数据路径处理完成后调用pw_stream_queue_buffer。8.如果Buffer不适合提交有效数据则进入退回路径。9.应用调用pw_stream_return_buffer把Buffer退回Stream。10.Buffer重新回到Stream内部可用队列等待后续调度周期再次使用。3.2调用流程图3.3生命周期图4.实战应用案例下面以“播放流中数据不足时退回Buffer”为例说明pw_stream_return_buffer的典型用法。播放流正常情况下应该取出Buffer、填充PCM、设置chunk、queue提交。但如果当前业务侧没有可用PCM数据并且不希望填充静音就可以把Buffer退回给Stream。structapp_data{structpw_stream*stream;uint32_tframe_size;};staticuint32_tread_pcm_from_ringbuffer(void*dst,uint32_tmax_bytes){/* * 实际项目中这里通常从解码器、网络流、 * 环形缓冲区或算法输出队列中读取PCM数据。 */return0;}staticvoidon_process(void*userdata){structapp_data*appuserdata;structpw_buffer*b;structspa_buffer*buf;structspa_data*data;uint32_tn_bytes;intret;bpw_stream_dequeue_buffer(app-stream);if(bNULL)return;bufb-buffer;databuf-datas[0];if(data-dataNULL||data-chunkNULL){retpw_stream_return_buffer(app-stream,b);(void)ret;return;}n_bytesread_pcm_from_ringbuffer(data-data,data-maxsize);if(n_bytes0){retpw_stream_return_buffer(app-stream,b);(void)ret;return;}data-chunk-offset0;data-chunk-sizen_bytes;data-chunk-strideapp-frame_size;pw_stream_queue_buffer(app-stream,b);}这个案例中return_buffer只出现在放弃路径。当Buffer不可写或者没有有效PCM数据时应用不把Buffer提交给正常播放链路而是退回Stream。这样可以避免把无效数据、脏数据或未初始化数据送入PipeWire图。采集流中也可以使用return_buffer。例如应用取到采集Buffer后发现当前录音已经暂停或者上层算法暂时不需要数据就可以退回Buffer。structcapture_data{structpw_stream*stream;bool capture_enabled;};staticvoidon_capture_process(void*userdata){structcapture_data*appuserdata;structpw_buffer*b;structspa_buffer*buf;structspa_data*data;constuint8_t*src;uint32_tsize;bpw_stream_dequeue_buffer(app-stream);if(bNULL)return;if(!app-capture_enabled){pw_stream_return_buffer(app-stream,b);return;}bufb-buffer;databuf-datas[0];if(data-dataNULL||data-chunkNULL){pw_stream_return_buffer(app-stream,b);return;}srcSPA_PTROFF(data-data,data-chunk-offset,uint8_t);sizedata-chunk-size;/* * 正常采集处理 * 可以送入录音文件、编码器、语音前处理、 * 回声消除模块或网络发送模块。 */(void)src;(void)size;pw_stream_queue_buffer(app-stream,b);}工程开发中使用pw_stream_return_buffer要注意四点。第一return_buffer只能用于已经dequeue出来的Buffer。没有dequeue就return或者重复return同一个Buffer都会破坏Stream内部Buffer状态。第二return_buffer不是正常提交路径。如果Buffer已经填充了有效音频或视频数据并且希望PipeWire继续处理应使用pw_stream_queue_buffer而不是return_buffer。第三return之后不要继续访问Buffer。return之后Buffer所有权已经回到PipeWire应用继续读写会造成数据竞争、状态错乱或难以复现的实时问题。第四异常路径也必须归还Buffer。只要dequeue成功无论后续成功、失败、丢弃还是暂停都必须通过queue_buffer或return_buffer结束本次Buffer持有周期。5.一句话总结pw_stream_return_buffer是PipeWireStream数据路径中的Buffer退回接口当应用已经dequeue到Buffer但不准备提交有效媒体数据时用它把Buffer使用权还给Stream避免Buffer长期占用并保持图调度链路稳定。
返回列表