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占用率。参考文章

相关推荐
关于作业的二三事4 分钟前
图像和视频处理的核心概念(在新画布上画圆形并保存图像)
音视频
开开心心_Every11 分钟前
带OCR识别的电子发票打印工具
运维·自动化·ocr·电脑·powerpoint·音视频·lua
love530love1 小时前
AI Agent + 本地 ComfyUI 无头模式实战:关闭 IDE 后 AI 独立重启并完成图文生成
ide·人工智能·windows·python·音视频·agent·devops
西安老张(AIGC&ComfyUI)19 小时前
第021章:ComfyUI文生音频Qwen3-TTS模型数字人音色设计(一)
aigc·音视频·数字人·comfyui
小殊小殊19 小时前
一文速通GPU版FFmpeg视频转码的安装使用
ffmpeg·音视频·视频编解码
美狐美颜SDK开放平台20 小时前
直播APP平台开发如何降低成本?视频美颜SDK方案解析
人工智能·音视频·美颜sdk·直播美颜sdk·视频美颜sdk·美颜api
luoyayun36120 小时前
Qt/QML音视频文件原始十六进制查看器
qt·音视频·十六进制查看
火山引擎边缘云21 小时前
让 Agent 成为音视频工作台:AI MediaKit CLI + Skill 发布
人工智能·音视频·火山引擎
阿拉斯攀登1 天前
视频编解码(二):H.264 是怎么把 10GB 压成 100MB 的?
音视频·视频编解码·h.264
小鹿软件办公1 天前
如何利用 Mac 自带 iMovie 裁剪去除视频 Logo 或文字水印
macos·音视频·视频去水印·简鹿水印助手