什么是Avhwaccel,我该如何使用它
What is AVHWAccel, and how can I use it?
我想利用硬件加速器来解码H264编码的MP4文件。
我的计算环境:
Hardware: MacPro (2015 model)
Software: FFmpeg (installed by brew)
这是FFmpeg
命令的输出:
$ffmpeg -hwaccels
Hardware acceleration methods:
vda
videotoolbox
根据此文档,我的环境有两个选项,即VDA
和VideoToolBox
。我尝试了C 中的VDA
:
Codec = avcodec_find_decoder_by_name("h264_vda");
它有点有效,但是像素格式的输出是我难以处理的UYVY422
(有关如何在C++
中渲染UYVY422
的任何建议?理想的格式是yuv420p
)
所以我想尝试VideotoolBox
,但是没有这样的简单的事情(虽然在编码的情况下可能起作用)
Codec = avcodec_find_decoder_by_name("h264_videotoolbox");
看来我应该使用AVHWAccel
,但是AVHWAccel
是什么?
我的C 代码的一部分:
for( unsigned int i = 0; i < pFormatCtx->nb_streams; i++ ){
if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
pCodecCtx = pFormatCtx->streams[i]->codec;
video_stream = pFormatCtx->streams[i];
if( pCodecCtx->codec_id == AV_CODEC_ID_H264 ){
//pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
pCodec = avcodec_find_decoder_by_name("h264_vda");
break;
}
}
}
// open codec
if( pCodec ){
if((ret=avcodec_open2(pCodecCtx, pCodec, NULL)) < 0) {
....
这与要选择的pix格式的解码器无关。
您的视频pix格式为 UYVY422
,因此在解码帧后获得了此格式。
就像提到的答案@halfelf一样,您可以在解码框架后执行SWSCALE,将PIX格式转换为理想格式yuv420p
,然后进行渲染。
同时,如果您确定它是格式UYVY422
,SDL2
可以直接为您处理渲染。
在下面的示例中,我的格式是yuv420p
,我使用SWSCALE转换为UYVY422
,以渲染到SDL2
// prepare swscale context, AV_PIX_FMT_UYVY422 is my destination pix format
SwsContext *swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
codecCtx->width, codecCtx->height, AV_PIX_FMT_UYVY422,
SWS_FAST_BILINEAR, NULL, NULL, NULL);
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window;
SDL_Renderer *render;
SDL_Texture *texture;
SDL_CreateWindowAndRenderer(codecCtx->width,
codecCtx->height, SDL_WINDOW_OPENGL, &window, &render);
texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_UYVY, SDL_TEXTUREACCESS_STREAMING,
codecCtx->width, codecCtx->height);
// ......
// decode the frame
// ......
AVFrame *frameUYVY = av_frame_alloc();
av_image_alloc(frameUYVY->data, frameUYVY->linesize, codecCtx->width, codecCtx->height, AV_PIX_FMT_UYVY422, 32);
SDL_LockTexture(texture, NULL, (void **)frameUYVY->data, frameUYVY->linesize);
// convert the decoded frame to destination frameUYVY (yuv420p -> uyvy422)
sws_scale(swsCtx, frame->data, frame->linesize, 0, frame->height,
frameUYVY->data, frameUYVY->linesize);
SDL_UnlockTexture(texture);
// performa render
SDL_RenderClear(render);
SDL_RenderCopy(render, texture, NULL, NULL);
SDL_RenderPresent(render);
在您的示例中,如果您的pix格式为 uyvy422
,则可以跳过swscale零件,并在从 ffmpeg
解码后直接执行渲染。
解码器不会选择输出是哪种像素格式,它取决于视频本身。swscale
LIB用于将一种像素格式转换为另一种像素格式。
auto sws_ctx = sws_getContext(src_width, src_height, AV_PIX_FMT_UYUV422, dst_width, dst_height, AV_PIX_FMT_YUV420P, 0,0,0,0);
av_image_alloc(new_data, new_linesize, dst_width, dst_height, AV_PIX_FMT_BGR24, FRAME_ALIGN);
sws_scale(sws_ctx, frame->data, frame->linesize, 0, src_height, new_data, new_linesize);
并且没有h264_videotoolbox
解码器,只有编码器。列出可用的解码器/编码器:
ffmpeg -encoders
ffmpeg -decoders
解码器/编码器名称写在源中,例如在libavcodec/vda_h264_dec.c
和libavcodec/videotoolboxenc.c
的末尾。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- C++:TypeDef使用元组
- 使用std::multimap迭代器创建std::list
- 从不同线程使用int64的不同字节安全吗
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么在全局范围内使用"extern int a"似乎不行?
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用Google Mock来模拟gettimeofday()
- 如何使用默认参数等选择模板专业化
- 为什么使用 "this" 指针调用派生成员函数?
- 使用新行和不使用新行读取文件
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 如何确定我已使用非编码文件到达 EOF?
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 什么是Avhwaccel,我该如何使用它
- 使用 LLVM 的 libc++ 时,__1 符号从何而来?
- 在std::cout之后使用std::cin时,换行符从何而来
- 为什么以及在何处在C++中使用引用和指针
- 基例如何影响使用递归函数的哪些行