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

相关推荐
美狐美颜sdk3 小时前
视频美颜SDK中的YUV与RGBA格式有什么区别?直播APP开发解析
人工智能·计算机视觉·音视频·美颜sdk·直播美颜sdk·视频美颜sdk
音视频牛哥3 小时前
不止于超低延迟:SmartMediaKit iOS Unity3D RTSP/RTMP 播放器的核心竞争力
音视频·unity3d rtsp播放器·unity3d rtmp播放器·smartmediakit·ios unity rtsp·ios unity rtmp·unity3d ios播放器
辰辰观影6 小时前
网盘视频播放器怎么选?2026全平台推荐
经验分享·音视频
guhy fighting6 小时前
怎么去除视频的logo?现在有方法了,使用Remove Logo Now快速去除视频logo
音视频
呆呆的猫7 小时前
【视频生成】2、VDN-MiniMax-H3
音视频
沐禾安信8 小时前
MOV转MP4怎么转换?苹果视频打不开这样解决
音视频·格式转换·mov转mp4
小豆庄8 小时前
视频隐私脱敏怎么处理:识别追踪与本地方案的选型思路
密码学·音视频·视频
Android系统攻城狮9 小时前
Linux FFmpeg深度解析之av_dump_format调用流程与实战(十一)
linux·运维·服务器·ffmpeg·1024程序员节·音视频进阶
七牛云行业应用9 小时前
爆火OpenFilm 0.2.6:开源 AI 视频 Agent 的安装、编辑与渲染流程(2026 年 10 月 )
人工智能·开源·音视频
Android系统攻城狮9 小时前
Linux FFmpeg深度解析之avcodec_find_decoder调用流程与实战(十二)
linux·运维·服务器·ffmpeg·1024程序员节·音视频进阶