Android codec2 视频框架 之应用

news2024/11/27 16:58:57

文章目录

      • 应用流程
        • 外部主动获取输入和输出buffer
        • 外部设置回调
      • 内部流程

应用流程

在这里插入图片描述

外部主动获取输入和输出buffer

解码的调用流程,以android原生的一个bin来说明
android 原生代码位置: frameworks/av/cmds/stagefright/codec.cpp
frameworks/av/cmds/stagefright/SimplePlayer.cpp

编译出来的是codec的bin,使用bin播放mp4, 可以使用如下的命令进行调试。

screenrecord /sdcard/test.mp4
codec -pSR /sdcard/test.mp4
  • prepare: 跟编码同样的流程

    createByType: 根据MIME创建解码器。

    configure:配置视频宽高、fromat信息到解码器。

    start:启动解码器进行解码。
    获取输入和输出的buffer 队列:先dequeue有效的输入buffer,然后将extract到的csd数据放入到这块buffer 中, 将这块buffer在queue到codec中(作用是 将解码所需要的额外的数据 给到解码器,类似于ffmpeg中的extradata)。

  • start: dequeue所有可用的input 和output buffer。然后解析封装读取数据 将数据拷贝到dequeue出来的input buffer 中, 拷贝完成后 queue到解码器, 同时从解码器中尽可能多的取输出的buffer, 对每个输出buffer 获取显示的时间戳。跟现有的时间比较,到显示时间的范围内则调用renderOutputBufferAndRelease将buffer 显示出去。

        state->mCodec = MediaCodec::CreateByType(
                looper, mime.c_str(), false /* encoder */);
        CHECK(state->mCodec != NULL);
        err = state->mCodec->configure(
                format, isVideo ? surface : NULL,
                NULL /* crypto */,
                0 /* flags */);

        CHECK_EQ((status_t)OK, codec->start());
        CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers));
        CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers))

         err = state->mCodec->queueInputBuffer(
                            index,
                            0 /* offset */,
                            buffer->size(),
                            timeUs,
                            bufferFlags);


外部设置回调

大部分应用都不会主动去获取解码输入和输出buffer。 类似NuPlayer是通过外部设置回调。MediaCodec内部有输出或者输入buffer的时候 回调到应用层。

NuPlayerDecoder.cpp
void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
    sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
    mCodec->setCallback(reply);
}
void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatCodecNotify:
        {
            switch (cbID) {
                case MediaCodec::CB_INPUT_AVAILABLE:
                {
                    int32_t index;
                    CHECK(msg->findInt32("index", &index));
                    handleAnInputBuffer(index);
                    break;
                }

                case MediaCodec::CB_OUTPUT_AVAILABLE:
                {
                    CHECK(msg->findInt32("index", &index));
                    CHECK(msg->findSize("offset", &offset));
   
                    handleAnOutputBuffer(index, offset, size, timeUs, flags);
                    break;
                }
}

内部流程

  • create 和configure

create:mediacodeclist中遍历所有的解码器 然后将所有match的解码器返回。 这个里面放的是component名字如c2.android.vorbis.decoder等等。 找到之后 就用这个名字来init mediacodec。

configure: 将format 和 surface 配置到解码器当中,。

  • format的configure

其中format可以存储很多信息 比如基本的图像宽高,解码器的类型等等。
configure将编解码的一些关键信息配置到编解码器 比如宽高、MIME、bitrate、frameRate 等等。

  • surface 的configure surface
  1. 在设置surface的流程中操作为nativeWindowConnect、设置一个surface的generaration,然后又重新connect、disconnect。
  2. 调用codec的setSurface, codec直接调用的channel 的setSurface。
  3. channel的setSurface不会调用mComponent->setOutputSurface, 因为初始化的时候对应的outputPoolId为0.
  • mediacodec 的start()
  1. 调用component 的start, 调用对应的SimpleC2Component的start(), 对应的每个解码器实现的onInit(),。
  2. mChannel->start, 调用channel的start
    这里有一个问题,如何决定要申请的buffer 是graphic 还是liner类型的。
    这在simpleC2interface中已经定义,会按照音视频的类型进行决定,视频 grahic,音频liner
    addParameter(
            DefineParam(mInputFormat, C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE)
            .withConstValue(new C2StreamBufferTypeSetting::input(
                    0u, isEncoder ? rawBufferType : codedBufferType))
            .build());

2.1 在Channel的start 中会根据是编码输入的surface 还是解码输出的surface 配置申请buffer的个数, 以及调用Component->createBlockPool,创建graphic的pool。会返回pool的allocatorID 和outputPoolId
对应于在底层的实现是在C2AllocatedGraphic。 同时为生成的pools->outputPoolId生成poolIdsTuning并将这个Tuning 设置到componet中。

2.2 调用mComponent->setOutputSurface: 设置surface到解码模块,使得后续可以从对应的nativewindow中申请buffer。

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

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

相关文章

在Windows 10中共享打印机,以便其他用户可以访问,发挥打印机的最大作用

知道如何在Windows 10中共享打印机是非常宝贵的。如果没有打印机共享&#xff0c;多个用户从单个设备进行所有打印的唯一方法就是手动连接自己的计算机。在本指南中&#xff0c;我们将向你展示一种更简单的方法。 通过网络共享打印机&#xff0c;只需连接一台PC或笔记本电脑。…

svn使用图形化界面从trunk目录下创建下的分支

1、svn目录 要从trunk目录右键创建一个新的目录出来。Branch/tag下创建&#xff1a; 然后源目录和提交目录的编写&#xff1a; 这样新的分支目录chuanqi_4就创建好了。要注意:这样创建要确保目标目录在svn目录下不存在。

ROS中MPC局部路径规划器使用方法及源码流程解读

本文主要介绍ROS中Navigation导航框架中MPC局部路径规划器mpc_local_planner的使用方法&#xff0c;并对源码进行解读&#xff0c;梳理其规划流程等&#xff0c;具体包含MPC模型预测控制算法简介、mpc_local_planner使用方法、mpc_local_planner源码解读与规划流程梳理三部分内…

微信小游戏软件开发手机微信休闲游戏

当今&#xff0c;微信已经成为了中国最受欢迎的社交媒体平台之一&#xff0c;拥有数亿活跃用户。随着微信的不断发展&#xff0c;微信小游戏成为了一个热门的应用领域&#xff0c;吸引了许多开发者和玩家。微信小游戏是一种小型游戏&#xff0c;可以直接在微信内嵌入和玩&#…

【JavaEE初阶】 TCP服务器与客户端的搭建

文章目录 &#x1f332;前言&#x1f334;ServerSocket API&#x1f384;Socket API&#x1f340;TCP中的长短连接&#x1f38d;建立TCP回显客户端与服务器&#x1f6a9;TCP搭建服务器&#x1f6a9;TCP搭建客户端&#x1f6a9;通信过程展示&#xff1a; &#x1f333;多个客户端…

offsetof宏的使用、模拟实现及 (size_t)(((struct_type*)0)->mem_name)的解释

宏原型&#xff1a;offsetof(type,member) 作用&#xff1a;返回数据结构或联合体类型中成员的偏移量&#xff0c;以字节为单位 返回值&#xff1a;size_t类型的无符号整数 使用案例&#xff1a; #include <stdio.h> #include <stddef.h> struct foo {ch…

爬取东方财富股票信息

爬取股票信息 爬虫爬取信息&#xff0c;一般有两种大的思路&#xff0c;分别是&#xff1a; 模拟header信息&#xff0c;发送请求&#xff0c;得到相应的数据&#xff08;html文件 或者 json数据&#xff09;使用selenium模拟打开浏览器&#xff0c;然后利用selenium提供的函…

高防CDN:企业网络安全的坚强后盾

随着互联网的快速发展&#xff0c;企业的网络面临着越来越多的安全威胁。在这种背景下&#xff0c;高防CDN&#xff08;Content Delivery Network&#xff09;已经成为了企业网络安全的坚强后盾。本文将理性分析高防CDN对于企业发展的影响&#xff0c;强调其在维护网络稳定性、…

内核态内存映射

内核态的内存映射机制&#xff0c;主要包含以下几个部分&#xff1a; 内核态内存映射函数 vmalloc、kmap_atomic 是如何工作的&#xff1b;内核态页表是放在哪里的&#xff0c;如何工作的&#xff1f;swapper_pg_dir 是怎么回事&#xff1b;出现了内核态缺页异常应该怎么办&am…

MySQL(10):创建和管理表

基础知识 在 MySQL 中&#xff0c;一个完整的数据存储过程总共有 4 步&#xff0c;分别是&#xff1a;创建数据库、确认字段、创建数据表、插入数据。 要先创建一个数据库&#xff0c;而不是直接创建数据表&#xff1a;从系统架构的层次上看&#xff0c;MySQL 数据库系统从大到…

Android 10.0 SystemUI启动流程

1、手机开机后&#xff0c;Android系统首先会创建一个Zygote&#xff08;核心进程&#xff09;。 2、由Zygote启动SystemServer。 3、SystemServer会启动系统运行所需的众多核心服务和普通服务、以及一些应用及数据。例如&#xff1a;SystemUI 启动就是从 SystemServer 里启动的…

浅谈前端自定义VectorGrid矢量瓦片样式

目录 前言 一、VectorGrid相关API介绍 1、VectorGrid 2、 LayerStyles样式详解 二、样式自动配置 1、页面定义 2、地图及PBF瓦片引入 3、矢量瓦片样式定义 4、鼠标事件交互 三、最终效果 1、自定义样式展示 2、鼠标交互 总结 前言 在上一篇博客中&#xff0c;详细讲…

`rest-client`库

rest-client是一个在Ruby编程语言中用于发送HTTP请求的库。它提供了简单且易于使用的接口&#xff0c;用于发送GET、POST、PUT、DELETE等各种类型的HTTP请求&#xff0c;并处理响应。 以下是rest-client库的一些常见用法示例&#xff1a; 发送GET请求&#xff1a; require ‘…

《算法通关村—轻松搞定合并二叉树》

《算法通关村—轻松搞定合并二叉树》 描述 leetcode 617 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵…

【网络知识必知必会】聊聊数据链路层以太网

文章目录 前言1. 认识以太网2. 以太网帧格式已经有了ip地址, 为什么还要有 mac 地址呢?认识MTUMTU对IP协议的影响MTU对UDP协议的影响MTU对于TCP协议的影响 总结 前言 本文继续来聊聊网络传输中数据链路层中的一个代表协议, 以太网. 以太这个词其实最早出现在物理学当中, 在早…

前端工程化(vue2)

一、环境准备 1.依赖环境&#xff1a;NodeJS 官网&#xff1a;Node.js 2.脚手架&#xff1a;Vue-cli 参考网址&#xff1a;安装 | Vue CLI 介绍&#xff1a;Vue-cli用于快速的生成一个Vue的项目模板。主要功能有&#xff1a;统一的目录结构&#xff0c;本地调试&#xff0…

麒麟系统查看磁盘UUID方法

通过查看 /dev/disk/by-uuid/ 目录下的软连接确定磁盘UUID ls -l /dev/disk/by-uuid/ 命令输出入下图所示&#xff0c;红框中即为磁盘UUID号 通过 blkid 命令查看系统中某块磁盘的uuid 号 blkid 命令输出如下图所示&#xff0c;UUID”” 中即为磁盘UUID号 开机自动…

五:ffmpe主要参数的使用

目录 一&#xff1a;回顾一下主要参数 二&#xff1a;使用主要参数操作视频 1、-i 输入流的使用 2、-i 配合 输出流-f使用 三、使用-ss开始时间进行转换 四、使用-t参数&#xff0c;设置转换的时长 一&#xff1a;回顾一下主要参数 -i 设定输入流。 支持本地和网络流 -f …

数学到底在哪里支撑着编程?

如果编程语言是血肉&#xff0c;那么数学的思想和知识就是灵魂。它可以帮助你选择合适的数据结构和算法&#xff0c;提升系统效率&#xff0c;并且赋予机器智慧。在大数据和智能化的时代更是如此。举个例子&#xff0c;我们在小学就学过的余数&#xff0c;其实在编程的世界里也…

3D 线激光相机的激光条纹中心提取方法

论文地址:Excellent-Paper-For-Daily-Reading/application/centerline at main 类别:应用——中心线 时间:2023/11/06 摘要 线激光条纹中心提取是实现线激光相机三维扫描的关键,根据激光三角测量法研制了线激光相机,基于传统 Steger 法对其进行优化并提出一种适用于提…