0%

android 如何实现ffmpeg 硬编码

一、背景

ffmpeg 因其丰富的格式和强大的功能而被广泛使用,是使用最为广泛的多媒体框架;基于ffmpeg来做二次开发,会节省很多开发和维护成本。
ffmpeg 自3.1 加入了mediacodec硬解码支持,但至今未支持mediacodec硬编码,需要自己实现这部分的逻辑。

二、实现

1、准备

视频:

样本地址->https://share.weiyun.com/6tNqHJic

样本信息->

测试机:锤子坚果 Pro2

2、ffmpeg编码流程

3、软编效果


avcodec_find_encoder_by_name(“libx264”)
处理完15s的视频样本,平均编码一帧耗时54ms

4、优化

添加mediacodec 硬编码逻辑

a、注册mediacodec 编码模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static const AVClass mediacodec_class = {
.class_name = "h264_mediacodec_class",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};

AVCodec ff_h264_mediacodec_encoder = {
.name = "h264_mediacodec",
.long_name = NULL_IF_CONFIG_SMALL("h264 (MediaCodec NDK)"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.priv_data_size = sizeof(MediaCodecEncContext),
.init = mediacodec_encode_init,
.send_frame = mediacodec_encode_send_frame,
.receive_packet = mediacodec_encode_receive_packet,
.close = mediacodec_encode_close,
.capabilities = AV_CODEC_CAP_DELAY,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
.priv_class = &mediacodec_class,
.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
},
};

b、实现编码逻辑

实现以下四个接口的逻辑
mediacodec_encode_init
mediacodec_encode_send_frame
mediacodec_encode_receive_packet
mediacodec_encode_close

详细实现见链接: https://github.com/hilive/ffmpeg-hardcode

优化效果


avcodec_find_encoder_by_name(“h264_mediacodec”)
处理完15s的视频样本,平均编码一帧耗时7ms

三、总结


ffmpeg 加上mediacodec硬编码能力后,编码一帧的耗时从54ms降到了7ms左右,耗时降低了8成以上,效果非常出色;

四、路径

视频样本:https://share.weiyun.com/6tNqHJic
编译脚本:https://github.com/hilive/ffmpeg-build
ffmpeg: https://github.com/hilive/ffmpeg-hardcode

用户的需求就是我的追求!