ffplay支持mac/iOS硬解码实践

  1. ffmpeg编译开启videotoolbox的支持。

    ./configure --enable-videotoolbox --enable-hwaccels

  2. 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;
    }

    //...
}
  1. 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);
    
    //...
}
  1. 可以看到虽然硬解码是在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占用率。参考文章

相关推荐
l***77523 小时前
从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
ffmpeg
ZouZou老师9 小时前
FFmpeg性能优化经典案例
性能优化·ffmpeg
极智-99610 小时前
视频文件格式?【图文详解】视频文件后缀名?视频文件格式转换?
音视频·视频文件格式·视频文件后缀名·视频文件格式转换
Android系统攻城狮10 小时前
Android16音频之设置HDMI音频setHdmiSystemAudioSupported:用法实例(一百一十六)
音视频·android16·音频进阶·hdmi音频
aqi0012 小时前
FFmpeg开发笔记(九十)采用FFmpeg套壳的音视频转码百宝箱FFBox
ffmpeg·音视频·直播·流媒体
颜颜yan_12 小时前
基于昇腾CANN的智能视频分析系统落地实践
架构·音视频·昇腾
齐齐大魔王13 小时前
FFmpeg
ffmpeg
你好音视频15 小时前
FFmpeg RTSP拉流流程深度解析
ffmpeg
顾道长生'1 天前
(Arxiv-2025)ID-COMPOSER:具有分层身份保持的多主体视频合成
计算机视觉·音视频·composer
IFTICing1 天前
【环境配置】ffmpeg下载、安装、配置(Windows环境)
windows·ffmpeg