-
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);
}
}
Note
|
硬编的MediaCodecSurfaceEncoder接受的输入frame类型为ImgTexFrame, 可以直接接受GPU处理后的数据,而基于VideoBufEncoderBase的视频编码实例接受的输入类型为ImgBufFrame, 需要前置一个ImgTexToBuf模块完成转换。 |