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

相关推荐
神探小白牙13 分钟前
海康视频在vue2.0中的使用
前端·音视频
AI天行健20 分钟前
文生视频与图生视频的技术区别及适用场景分析
人工智能·音视频
阿童木写作26 分钟前
跨境电商批量图片翻译与视频字幕翻译工具推荐
python·音视频
orient.lu31 分钟前
第 21 章《图像生成与音频转录》· nanobot 多模态 Provider 源码解析:11 图像 + 6 转录注册表
音视频·nanobot
Mr数据杨1 小时前
【Codex】接入音频转录服务实现课堂语音结构化处理
django·音视频·codex·项目开发
ALINX技术博客2 小时前
【黑金云课堂】FPGA技术教程FPGA 基础:HDMI视频输入与环路输出实验
fpga开发·音视频
揽秀亭长2 小时前
做视频时如何快速完成视频转文字?几种方法实测
人工智能·音视频
可乐鸡翅yeah_3 小时前
hls.js 多实例并发踩坑,多视频页面播放器内存与冲突问题解决
开发语言·前端·javascript·音视频·hls·m3u8·m3u8在线播放
AI服务老曹3 小时前
算法任务配置完整流程:明厨亮灶项目从0到1怎么做 | AI视频分析算法实践
人工智能·算法·音视频
AI创界者3 小时前
【开源实战】FaceFusionFree 5.3 部署与进阶:修复内存模式条纹 Bug 与帧率对齐逻辑解析
人工智能·aigc·音视频