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

相关推荐
m0_726365832 小时前
Ai漫剧系统 几分钟,让AI 把一篇小说变成了一部漫剧成片:从剧本到视频的全流程系统实现
人工智能·语言模型·ai作画·音视频
非凡ghost6 小时前
可拓浏览器:给手机浏览器装上“外挂“!2W+拓展+AI搜索,玩出无限可能!
windows·智能手机·音视频·firefox
美狐美颜SDK开放平台7 小时前
多场景美颜SDK解决方案:直播APP(iOS/安卓)开发接入详解
android·人工智能·ios·音视频·美颜sdk·第三方美颜sdk·短视频美颜sdk
ai产品老杨9 小时前
深度解析:基于国产化异构计算的 AI 视频管理平台架构——从 GB28181 接入到 NPU 边缘推流的解耦实践
人工智能·架构·音视频
watson_pillow9 小时前
音视频相关基础知识储备入门-字幕
音视频
程序员JerrySUN10 小时前
Jetson边缘嵌入式实战课程第二讲:JetPack 和 SDK Manager 是什么
c语言·开发语言·网络·udp·音视频
happybasic11 小时前
在CMD下使用FFmpeg将.wav文件转换成指定的格式~
ffmpeg
weixin_66812 小时前
NVIDIA VSSVideo Search and Summarization视频搜索与摘要蓝图详尽使用说明与技术报告版本
人工智能·音视频
jiayong2313 小时前
国内外视频/图像大模型与智能体工具平台竞品对比
ai·音视频·agent
视频技术分享14 小时前
技术赋能生态革新:音视频产业开启千亿增长新周期 视频会议成核心增长亮点
音视频