ffmpeg-nvenc
来源:互联网 发布:图片去码软件 编辑:程序博客网 时间:2024/04/30 15:34
nvenc.c是一个用nvidia来执行的代码,下面简单分析nvenc编码的基本流程,
主要关注与nvenc底层相关的接口调用,nvenc底层代码的关键调用如下图所示的8个步骤
AVCodec ff_nvenc_h264_encoder = { .name = "nvenc_h264", .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, /*关键的三个接口函数*/ .init = nvenc_old_init, .encode2 = ff_nvenc_encode_frame, .close = ff_nvenc_encode_close, .priv_data_size = sizeof(NvencContext), .priv_class = &nvenc_h264_class, .defaults = defaults, .capabilities = AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts,};#endif
主要是分析 ff_nvenc_encode_frame和ff_nvenc_encode_init
ff_nvenc_encode_init关键部分
/*加载函数库 *关键err = nvenc_create_instance(&dl_fn->nvenc_funcs); */ if ((ret = nvenc_load_libraries(avctx)) < 0) return ret; if ((ret = nvenc_setup_device(avctx)) < 0) return ret; if ((ret = nvenc_setup_encoder(avctx)) < 0) return ret; if ((ret = nvenc_setup_surfaces(avctx)) < 0) return ret;
1.nvenc_load_libraries
加载函数库,经过这样的处理后就可以使用nvenc底层的函数接口
err = nvenc_create_instance(&dl_fn->nvenc_funcs);//关键调用
2.nvenc_setup_device
获取GPU使用资源(可以理解成要想使用nvidia,需要获取GPU的使用权限),打开段,检测设备兼容性等性能
这个函数的流程会有两个分支,一个是从显卡(显存)传来的数据,另一个是从CPU传来的数据(内存)。这两个流程的区别就是
假设数据从内存传来,为了开启显卡,需要获取显卡的相关资源,因此需要调用一系列获取显卡信息资源的接口,这类接口主要有:
(dl_fn->cu_init(0)) dl_fn->cu_device_get_count(&nb_devices) //获取设备数量 cu_res =dl_fn->cu_device_get(&cu_device, idx);//获取idx指定的设备入口 cu_res =dl_fn->cu_ctx_create(&ctx->cu_context_internal, 0, cu_device);//在这个设备创建相关资源 ctx->cu_context =ctx->cu_context_internal; //ctx->cu_context会在被open_session使用
假设数据是从显存传过来,代表之前已经用显卡做了解码相关的操作,显卡相关的信息资源就可以直接获取到了
frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; device_hwctx = frames_ctx->device_ctx->hwctx; ctx->cu_context = device_hwctx->cuda_ctx;
这个函数里面有两个重要的接口调用nvenc_open_session和nvenc_check_capabilities
`nvenc_open_session` ---------必须有这个操作,后续的接口调用操作才能成功
ret = p_nvenc->nvEncOpenEncodeSessionEx(¶ms, &ctx->nvencoder); //关键调用
nvenc_check_capabilities
————-支持的编码参数检测
3.nvenc_setup_encoder—-设置编码参数
摘取与nvenc底层相关的关键代码:static av_cold int nvenc_setup_encoder(AVCodecContext *avctx){ .... /*这里涉及到-preset的设置*/ nvenc_map_preset(ctx); nv_status = nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, ctx->init_encode_params.encodeGUID, ctx->init_encode_params.presetGUID, &preset_config);.... /*码率控制设置,大多数nvenc的参数的设置都和码率控制相关*/ nvenc_setup_rate_control(avctx);........... /*设置h264和hevc的编码参数,level等级*/ res = nvenc_setup_codec_config(avctx);..... /*初始化编码器*/ nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);}
4.nvenc_setup_surfaces ——–分配必要显存的地方
底层库关键调用 nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf); -----分配输入 nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut); -----分配输出
ff_nvenc_encode_frame的简单分析:
{ .... inSurf = get_free_frame(ctx);//从获取空余空间 if (!inSurf) { av_log(avctx, AV_LOG_ERROR, "No free surfaces\n"); return AVERROR_BUG; } /* 把解码之后的数据加载进来 *nvenc_upload_frame两个分支 */ res = nvenc_upload_frame(avctx, frame, inSurf); if (res) { inSurf->lockCount = 0; return res; } ....... nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);//开始编码 ..... /*接下来就是编码数据的读写操作 *数据放到surface --fifo *读写fifo *av_fifo_generic_read *av_fifo_generic_write *处理数据,变成pkt---process_output_surface */ ...... }
nvenc_upload_frame两个分支:
如果数据是从显存传来
ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, ®); nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &nvenc_frame->in_map);
如果数据从内存传过来
v_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams); nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, nvenc_frame->input_surface);
- ffmpeg-nvenc
- ffmpeg nvenc编码
- 编译 FFMPEG with nvenc enabled
- ffmpeg h264 硬编码 nvenc
- 【视频开发】【CUDA开发】ffmpeg nvenc编码
- nvenc使用
- FFmpeg
- FFMPEG
- ffmpeg
- ffmpeg
- ffmpeg
- FFmpeg
- ffmpeg
- ffmpeg
- ffmpeg
- ffmpeg
- FFmpeg
- ffmpeg
- 基于【pandas】的数据预处理(含定制【OneHotEncoder】方法)
- Android实现夜间模式
- Android RILD运行机制详解
- ORACLE多表关联UPDATE 语句
- 字母图形
- ffmpeg-nvenc
- 队列的链表实现
- syscall error number : errno
- day01总结
- [linux] c 实现简单的web服务器
- 【框架基础】:Java反射机制详解(一)
- 电影《肖申克的救赎》给你最深的感受是什么?
- Oracle数据库视图
- Jquery Datatables 1.10兼容1.9 的错误解决