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。

相关推荐
正在走向自律4 分钟前
第二章-AIGC入门-开启AIGC音频探索之旅:从入门到实践(6/36)
人工智能·aigc·音视频·语音识别·ai音乐·ai 音频·智能语音助手
移动开发者1号3 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号3 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best7 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk8 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
melonbo11 小时前
使用FFmpeg将H.264码流封装为MP4
ffmpeg·音视频·h.264
恋猫de小郭12 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi0013 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体
androidwork15 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
慢行的骑兵15 小时前
Android音视频探索之旅 | CMake基础语法 && 创建支持Ffmpeg的Android项目
ffmpeg·音视频