-
ffmpeg编译开启videotoolbox的支持。
./configure --enable-videotoolbox --enable-hwaccels
-
stream_component_open方法中开启硬件解码器。
cpp
int FSPlay::stream_component_open(VideoState *is, int stream_index)
{
//...
codec = avcodec_find_decoder(avctx->codec_id);
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
//通过videotoolbox找到对应的deviceType。
enum AVHWDeviceType type = av_hwdevice_find_type_by_name("videotoolbox");
//遍历编码器中的HWConfig,找到deviceType为videotoolbox的像素格式,保存到hw_pix_fmt中
for (int i = 0;; i++) {
const AVCodecHWConfig *config = avcodec_get_hw_config(codec, i);
if (!config) {
return -1;
}
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
config->device_type == type) {
hw_pix_fmt = config->pix_fmt;
break;
}
}
//设置编码器上下文avctx的get_format为get_hw_format
avctx->get_format = get_hw_format;
//初始化硬件解码器ctx->hw_device_ctx
if (hw_decoder_init(avctx, type) < 0)
return -1;
}
switch(avctx->codec_type){
case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
}
//...
}
- video_image_display方法中奖GPU data转换到CPU data,然后传入sws_getContext统一转换为RGB24格式传入OpenGLES显示。
cpp
void FSPlay::video_image_display(VideoState *is)
{
//...
AVFrame *tmpFrame = av_frame_alloc();
if (vp->frame->format == hw_pix_fmt) {
/* retrieve data from GPU to CPU */
if ((av_hwframe_transfer_data(tmpFrame, vp->frame, 0)) < 0) {
fprintf(stderr, "Error transferring the data to system memory\n");
}
} else
tmpFrame = vp->frame;
//sws_getContext需要传入原像素格式(enum AVPixelFormat)tmpFrame->format
swsContext = sws_getContext(vp->width, vp->height, (enum AVPixelFormat)tmpFrame->format, vp->width, vp->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
//...
}
- 可以看到虽然硬解码是在GPU里进行解码,会降低CPU使用率,但是最终显示的时候还需要调用av_hwframe_transfer_data方法将数据拷贝到CPU中(NV12格式),拷贝后它的格式在转换为RGB24时也需要占用CPU资源,所以对CPU资源占用率的降低并不大,如果能将GPU数据直接传递到OpenGLES中显示应该可以降低CPU使用率。
5,后续有时间会继续优化,将av_hwframe_transfer_data改为av_hwframe_map,能优化1/3的CPU时间,然后不在CPU中做NV12到RGB24的转换,而是通过OpenGLES在片源着色器中进行转换,预计会大大降低CPU占用率。参考文章