Android codec2 视频框架 之应用

文章目录

应用流程

外部主动获取输入和输出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。

相关推荐
电鱼智能的电小鱼9 分钟前
基于电鱼 AI 工控机的智慧工地视频智能分析方案——边缘端AI检测,实现无人值守下的实时安全预警
网络·人工智能·嵌入式硬件·算法·安全·音视频
音视频牛哥3 小时前
从协议规范和使用场景探讨为什么SmartMediaKit没有支持DASH
人工智能·音视频·大牛直播sdk·dash·dash还是rtmp·dash还是rtsp·dash还是hls
音视频牛哥3 小时前
SmartMediaKit:如何让智能系统早人一步“跟上现实”的时间架构--从实时流媒体到系统智能的演进
人工智能·计算机视觉·音视频·音视频开发·具身智能·十五五规划具身智能·smartmediakit
Digitally4 小时前
如何用5种实用方法将电脑上的音乐传输到安卓手机
android·智能手机·电脑
音视频牛哥4 小时前
超清≠清晰:视频系统里的分辨率陷阱与秩序真相
人工智能·机器学习·计算机视觉·音视频·大牛直播sdk·rtsp播放器rtmp播放器·smartmediakit
johnny2334 小时前
AI视频创作工具汇总:MoneyPrinterTurbo、KrillinAI、NarratoAI、ViMax
人工智能·音视频
HahaGiver6665 小时前
Unity与Android原生交互开发入门篇 - 打开Unity游戏的设置
android·unity·交互
2501_915909065 小时前
WebView 调试工具全解析,解决“看不见的移动端问题”
android·ios·小程序·https·uni-app·iphone·webview
IT乐手6 小时前
android 下载管理工具类
android
2501_915106327 小时前
App 怎么上架 iOS?从准备资料到开心上架(Appuploader)免 Mac 上传的完整实战流程指南
android·macos·ios·小程序·uni-app·iphone·webview