论述网站建设的具体步骤有哪些,网站开发区书籍,fotor懒设计,个人主页设计图文章目录 应用流程外部主动获取输入和输出buffer外部设置回调 内部流程 应用流程 外部主动获取输入和输出buffer
解码的调用流程#xff0c;以android原生的一个bin来说明 android 原生代码位置#xff1a; frameworks/av/cmds/stagefright/codec.cpp frameworks/av/cmds/st… 文章目录 应用流程外部主动获取输入和输出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.mp4prepare 跟编码同样的流程 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 spAMessage format) {spAMessage reply new AMessage(kWhatCodecNotify, this);mCodec-setCallback(reply);
}
void NuPlayer::Decoder::onMessageReceived(const spAMessage 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
createmediacodeclist中遍历所有的解码器 然后将所有match的解码器返回。 这个里面放的是component名字如c2.android.vorbis.decoder等等。 找到之后 就用这个名字来init mediacodec。
configure 将format 和 surface 配置到解码器当中。
format的configure
其中format可以存储很多信息 比如基本的图像宽高解码器的类型等等。 configure将编解码的一些关键信息配置到编解码器 比如宽高、MIME、bitrate、frameRate 等等。
surface 的configure surface
在设置surface的流程中操作为nativeWindowConnect、设置一个surface的generaration然后又重新connect、disconnect。调用codec的setSurface, codec直接调用的channel 的setSurface。channel的setSurface不会调用mComponent-setOutputSurface 因为初始化的时候对应的outputPoolId为0.
mediacodec 的start()
调用component 的start 调用对应的SimpleC2Component的start(), 对应的每个解码器实现的onInit(),。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。