我想利用硬件加速来解码h264编码的MP4文件。
我的计算环境:
Hardware: MacPro (2015 model)
Software: FFmpeg (installed by brew)
这是
FFmpeg
命令的输出:$ffmpeg -hwaccels
Hardware acceleration methods:
vda
videotoolbox
根据this document的说法,我的环境有两种选择,即
VDA
和VideoToolBox
。我在C++中尝试了VDA
:Codec = avcodec_find_decoder_by_name("h264_vda");
有点用,但是像素格式的输出是
UYVY422
,我很难处理(关于如何在UYVY422
中呈现C++
的任何建议?理想的格式是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
解码后直接执行渲染。