-
Notifications
You must be signed in to change notification settings - Fork 6
encoder
SDK提供了通用音视频编码器的基类实现(VideoBufEncoderBase, AudioEncoderBase),开发者可以通过扩展这些基类, 实现几个基础接口,即可将自己的编码器接入到SDK中。
具体应用示例可参考 x264encoder 和 fdkaacencoder.
-
开启编码器
视频编码器实现
int doStart(VideoEncodeConfig config)接口, 音频编码器实现int doStart(AudioEncodeConfig config)接口。
在该接口实现中,需要根据输入的config参数来配置并打开编码器。 -
停止编码器
实现
void doStop()接口,关闭编码器。 -
动态码率调整
视频编码器需实现
void doAdjustBitrate(int bitrate)接口, 在编码过程中动态调整视频码率以实现码率自适应的特性。 -
Flush编码器数据
实现
doFlush()接口,清空当前编码器中的残留的已编码数据。 -
送入原始音视频数据
视频编码器实现
int doEncode (ImgBufFrame frame)接口,音频编码器实现int doEncode (AudioBufFrame frame)接口。
在该接口实现中,需要将参数中传递的原始音视频帧数据送给编码器。 -
发送编码后的音视频数据
编码器获取到一帧编码后的数据后,需要调用
sendEncodedPacket(ByteBuffer data, long dts, long pts, int flags)接口来将其发送至下一级模块。
-
需要实现的各个抽象方法均在基类创建的单一编码线程中被调用,基类已实现对外接口的异步化处理。
-
AAC音频编码器打开后输出的第一帧必须是flag中带有AVConst.FLAG_CODEC_CONFIG标记的AAC header信息。
-
H264/265视频编码器打开后输出的第一帧必须是flag中带有AVConst.FLAG_CODEC_CONFIG标记的SPS/PPS信息。
-
视频编码后的数据必须是一个完整的frame。
-
视频编码后输出的数据,关键帧必须在flag参数中有AVConst.FLAG_KEY_FRAME标记。
参考 UnionStreamer.java 中 switchVideoEncoder(), switchAudioEncoder 中的实现。
protected void switchAudioEncoder() { AudioEncodeConfig encodeConfig = null; if (mAudioEncoder != null) { encodeConfig = (AudioEncodeConfig) mAudioEncoder.getEncodeConfig(); mAudioEncoder.getSrcPin().disconnect(false); mAudioMixer.getSrcPin().disconnect(mAudioEncoder.getSinkPin(), true); } if (mAudioEncodeMethod == StreamerConstants.ENCODE_METHOD_HARDWARE) { mAudioEncoder = new MediaCodecAudioEncoder(); } else { mAudioEncoder = new FdkAACEncoder(); } // avAdaptor mAudioEncoder.getSrcPin().connect(mAVAdapter.getAudioSink()); mAudioMixer.getSrcPin().connect(mAudioEncoder.getSinkPin()); mAudioEncoder.setEncoderListener(mEncoderListener); if (encodeConfig != null) { mAudioEncoder.configure(encodeConfig); } } protected void switchVideoEncoder() { VideoEncodeConfig encodeConfig = null; if (mVideoEncoder != null) { encodeConfig = (VideoEncodeConfig) mVideoEncoder.getEncodeConfig(); mVideoEncoder.getSrcPin().disconnect(false); mImgTexMixer.getSrcPin().disconnect(true); } if (mVideoEncodeMethod == StreamerConstants.ENCODE_METHOD_HARDWARE) { mVideoEncoder = new MediaCodecSurfaceEncoder(mGLRender); mImgTexMixer.getSrcPin().connect(mVideoEncoder.getSinkPin()); } else { mImgTexToBuf = new ImgTexToBuf(mGLRender); mVideoEncoder = new X264Encoder(); mImgTexToBuf.getSrcPin().connect(mVideoEncoder.getSinkPin()); mImgTexMixer.getSrcPin().connect(mImgTexToBuf.getSinkPin()); } mVideoEncoder.getSrcPin().connect(mAVAdapter.getVideoSink()); mVideoEncoder.setEncoderListener(mEncoderListener); if (encodeConfig != null) { mVideoEncoder.configure(encodeConfig); } }