Android Media Framework(十八)ACodec - Ⅵ

news2024/11/15 17:28:58

ACodec之所以复杂,主要是因为状态太多。在上一篇文章中,我们学习了在ExecutingState下对buffer的处理。ExecutingState可能会切换到OutputPortSettingsChangedState、FlushingState,或者当组件被释放时,进入UninitializedState。接下来,我们将探讨这些情况下的buffer处理流程。

1、OMX_EventPortSettingsChanged

之前我们提到解码器支持Adaptive Playback的方式有两种,一种是分配足够的大的output buffer,另一种是发送Event给上层重新分配output buffer,这一节我们来讲一讲第二种方式。

当码流的分辨率发生变化时,解码器会发送OMX_EventPortSettingsChanged Event给上层,ACodec在Executing状态下会做如下处理:

    case OMX_EventPortSettingsChanged:
    {
        CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
        // 获取output format
        mCodec->onOutputFormatChanged();

        if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
            mCodec->mMetadataBuffersToSubmit = 0;
            // 禁用output port
            CHECK_EQ(mCodec->mOMXNode->sendCommand(
                        OMX_CommandPortDisable, kPortIndexOutput),
                        (status_t)OK);
            // 释放不属于组件的output buffer
            mCodec->freeOutputBuffersNotOwnedByComponent();
            // 切换到OutputPortSettingsChangedState
            mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
        }

        return true;
    }
  1. 调用onOutputFormatChanged获取输出端口的format信息;
  2. 发送命令禁用组件的输出端口;
  3. 调用freeOutputBuffersNotOwnedByComponent释放部分output buffer;
  4. 切换状态到OutputPortSettingsChangedState。

想要了解这段代码的含义,首先我们要搞清楚此时各个模块持有output buffer的情况:

请添加图片描述

从上图我们可以知道,可能有三个模块持有buffer:

  • MediaCodec:它指代的是整个上层应用,持有output buffer一般是在做Avsync;
  • ACodec:在正常工作过程中,ACodec是不会持有input/output buffer的,所以触发OMX_EventPortSettingsChanged事件时不会有buffer被ACodec持有;
  • NativeWindow:表示buffer已经被送去渲染了;
  • OMX Component:output buffer正在组件中等待填充;

发送命令禁用组件的输出端口,命令是非阻塞执行的,禁用组件输出端口需要将组件持有的buffer送还给ACodec,当所有buffer被送回并且组件持有的所有引用被释放,命令才算执行完成。

status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
    status_t err = OK;
    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
        i--;
        BufferInfo *info =
            &mBuffers[kPortIndexOutput].editItemAt(i);

        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
            status_t err2 = freeBuffer(kPortIndexOutput, i);
            if (err == OK) {
                err = err2;
            }
        }
    }

    return err;
}

freeOutputBuffersNotOwnedByComponent翻译过来是释放没有被组件持有的buffer,但是从方法实现来看,除了被组件持有的buffer不会被释放,被上层持有的buffer也不会被释放。

事件触发时,OWNED_BY_DOWNSTREAM状态的buffer是上一个视频序列的最后几帧,我们要等渲染完成才能释放它们,否则画面分辨率变化时可能会有跳帧的情况。

status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
    status_t err = OK;

    switch (info->mStatus) {
        case BufferInfo::OWNED_BY_US:
            if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
                (void)cancelBufferToNativeWindow(info);
            }
            FALLTHROUGH_INTENDED;

        case BufferInfo::OWNED_BY_NATIVE_WINDOW:
            err = mOMXNode->freeBuffer(portIndex, info->mBufferID);
            break;
    }

    mBuffers[portIndex].removeAt(i);
    return err;
}

调用ACodec::freeBuffer时首先会检查BufferInfo记录的buffer状态,此处调用时buffer状态为OWNED_BY_NATIVE_WINDOW,因此直接调用OMXNode的freeBuffer方法释放output buffer。

2、OutputPortSettingsChangedState

3、FlushingState

4、signalResume

5、initiateShutdown

5、其他

我们在文章一开始说到,“ACodec之所以复杂,主要是因为状态太多”,上面我们只分析了Executing状态时组件的停止过程,实际上可能会在flush状态下调用initiateShutdown,也有可能在Loaded状态下调用initiateShutdown。类似的,也可能可能在OutputPortSettingsChangedState调用flush方法。ACodec对所有可能的情况都做了处理,所以代码看起来会显得复杂,但是实际上只要理清不同状态切换时需要如何处理buffer就可以了。

这是OpenMAX框架的最后一篇分析,后续将会开始全新的Codec2框架解析,以及Player和MediaExtractor分析,写作顺序如何安排还需要再做考虑。

关注公众号《青山渺渺》阅读全文
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2050168.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

泛微云桥前台文件上传漏洞-202408

漏洞简介 2024 年 8 月份新出漏洞,泛微云桥任意文件上传漏洞,详情如图所示。 环境搭建 1、下载漏洞环境。 https://wx.weaver.com.cn/download 2、运行install64.bat,安装环境。 3、安装成功界面。 未安装补丁,系统不能使用…

Java方法01:什么是方法

本节视频链接:Java方法01:什么是方法?_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p45&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 Java中的‌方法‌是一段执行特定任务的代码片段,‌它是程序的基本构…

Keepalived:不只是心跳检测,更是高可用性的秘密武器

keepalived博客(Keepalived:不只是心跳检测,更是高可用性的秘密武器) 文章目录 keepalived博客(**Keepalived:不只是心跳检测,更是高可用性的秘密武器**)keepalived介绍概述工作原理核心模块应用场景配置与安装总结 keepalived基本…

工 厂设计模式

简单工厂模式 基本介绍 1) 简单工厂模式是属于创建型模式,是工厂模式的一种。 简单工厂模式是由一个工厂对象决定创建出哪一 种产品类 的实例。简单工厂模式是工厂模式家族中最简单实用的模式 2) 简单工厂模式:定义了一个创建对象的类,由这个类来 封装实例化对象的行为 (代…

从零开始学cv-6:图像的灰度变换

文章目录 一,简介:二、图像的线性变换三、分段线性变换四,非线性变换4.1 对数变换4.2 Gamma变换 五,效果: 一,简介: 图像灰度变换涉及对图像中每个像素的灰度值执行数学运算,进而调整图像的视觉…

Python基础和变量使用

1. 基础了解 1.1 运行方式 Python有多种运行方式,以下是几种常见的执行Python代码的方法: 交互式解释器: 打开终端或命令提示符,输入python或python3(取决于你的系统配置),即可进入Python交互…

HelpLook AI 知识库:为企业提供高效智能的知识管理解决方案

“管理就是把复杂的问题简单化,混乱的事情规范化。” 在当今竞争激烈的商业环境中,企业面临着快速变化的市场需求和日益复杂的业务流程。为了保持竞争力并提升运营效率,选择一款合适的知识管理系统至关重要。在众多选项中,HelpLoo…

day05--Vue

一、Vue入门 1.1入门案例 1.在页面中引入vue.js框架 2.定义vue对象 let app new Vue({ el:"#vue作用域的div标签id", data:{ //所有数据模型 }, methods:{ //页面中所有触发的js方法 }, created(){ //页面初始化,准备调用方法 } …

MODELSIM仿真报错解决记录

目录 问题:Modelsim报错:Error (10228): Verilog HDL error at Line_Shift_RAM_1Bit.v(39): module “Line_Shift_RAM_1 原因:创建的IP核放到了别的位置 解决方法:删掉IP核以及QIP等文件,将IP核创建到工程目录下 问…

vue3旋转木马型轮播图,环型滚动

<template><div><div class"content"><div class"but1" click"rotateLeft">--向左</div><div class"ccc"><main id"main"><div class"haha" ref"haha"&g…

垂直电商的兴衰与开源AI智能名片S2B2C商城系统的崛起:一场商业模式的革新

摘要&#xff1a;随着互联网技术的飞速发展&#xff0c;电子商务行业经历了从萌芽到繁荣再到精细化分化的历程。垂直电商作为电商领域的一个重要分支&#xff0c;曾因其聚焦细分市场、满足特定用户需求、产品标准化及快速整合供应链等优势&#xff0c;吸引了大量资本的关注。然…

Ubuntu上安装Redis的详细教程

1、安装redis 首先&#xff0c;访问Redis官网&#xff0c;点击首页的【Get Started】&#xff0c;然后点击Install Redis on Linux 安装 终端依次输入以下命令&#xff0c;如果过程中没有错误提示&#xff0c;则redis安装完成。 sudo apt install lsb-release curl gpg cu…

【前端】NodeJS:会话控制

文章目录 1 介绍2 cookie2.1 cookie是什么2.2 cookie的特点2.3 cookie的运行流程2.4 浏览器操作cookie2.5 cookie的代码操作 3 session3.1 session是什么3.2 session的作用3.3 session运行流程3.4 session的代码操作 4 session和cookie的区别5 token5.1 token是什么5.2 token的…

网络安全之xss靶场练习

目录 一、xss靶场练习 1、Ma Spaghet! 2、Jefff 第一个方法 第二个方法 3、Ugandan Knuckles 4、Ricardo Milos 5、Ah Thats Hawt 6、Ligma 7、Mafia​编辑 8、Ok, Boomer 一、xss靶场练习 靶场地址 https://xss.pwnfunction.com/ 页面显示如下 1、Ma Spaghet! 分析…

旧版Pycharm支持的python版本记录

版权声明&#xff1a;本文为博主原创文章&#xff0c;如需转载请贴上原博文链接&#xff1a;旧版Pycharm支持的python版本记录-CSDN博客 前言&#xff1a;近期由于打算研究GitHub上一个开源量化交易平台开发框架&#xff0c;但是该框架是基于python3.10的版本开发&#xff0c;所…

海康VisionMaster使用学习笔记5-开机自启动

开机自启动 在实际应用中&#xff0c;用户会希望机台上电开机后&#xff0c;软件能自启动避免现场人员误操作&#xff0c;减少机台重新上电时的操作步骤以提升效率。 设置 打开VM,点击设置,软件设置->开机自启动->勾选开机自启动->确定 默认运行界面 启动时以设定的…

MapReduce原理和操作

目录 一、MapReduce开发1. 数据处理的过程&#xff08;MapReduce&#xff09;2. 入门案例 二、MapReduce的高级特性1. 序列化2. 排序3. 分区4. Combiner——合并5. Shuffle——洗牌 一、MapReduce开发 1. 数据处理的过程&#xff08;MapReduce&#xff09; 注意 JobMapReduce&…

不同操作系统中如何搭建RabbitMQ开发环境?

大家好&#xff0c;我是袁庭新。今天介绍在不同操作系统中如何搭建RabbitMQ开发环境&#xff1f; 在使用RabbitMQ之前必须预先安装配置&#xff0c;参考RabbitMQ官网说明&#xff0c;RabbitMQ支持多平台安装&#xff0c;例如Linux、Windows、macOS、Docker等。不同架构的芯片对…

通过电影之镜,探索美的无限可能

通过电影之镜&#xff0c;探索美的无限可能&#xff1a;以《至爱梵高星空之谜》、《阳光灿烂的日子》与《这个杀手不太冷》为例 在光影交错的世界里&#xff0c;电影不仅是故事的讲述者&#xff0c;更是审美的引领者。三部风格迥异却同样引人入胜的电影——《至爱梵高星空之谜…

SSM学生社团管理系统—计算机毕业设计源码无偿分享20360

目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 学生社团管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系…