nvdec - utilizando ffmpeg hwaccel desde C++
nvidia nvenc descargar (1)
Comience por leer la documentación de ffmpeg: https://trac.ffmpeg.org/wiki/HWAccelIntro y responda mejor Cómo usar la aceleración de hardware con ffmpeg (y para la página de verificación de Linux https://wiki.archlinux.org/index.php/Hardware_video_acceleration )
Al utilizar FFmpeg la herramienta, la decodificación asistida por HW se habilita mediante la opción
-hwaccel
, que habilita un decodificador específico. Cada decodificador puede tener limitaciones específicas (por ejemplo, un decodificador H.264 solo admite el perfil de línea de base). La codificación asistida por HW se habilita mediante el uso de un codificador específico (por ejemplo, h264_nvenc). El filtrado del procesamiento asistido por hardware solo se admite en algunos filtros. Existen varios estándares API de aceleración de hardware, algunos de los cuales son compatibles hasta cierto punto con FFmpeg.
La activación de hwaccel fue controlada por un código similar (cambio de formato después de 2013 https://github.com/FFmpeg/FFmpeg/commit/08303d774132775d49d4ba767092de5d426f089d )
avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt);
Por ejemplo, en libavcodec / mpeg12dec.c https://github.com/FFmpeg/FFmpeg/blob/6c7254722ad43712db5686feee8bf75c74d8635b/libavcodec/mpeg12dec.c
avctx->pix_fmt = mpeg_get_pixelformat(avctx);
avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt);
ff_find_hwaccel
verifica el par de imágenes de códec y pixelformat y de todos los hwaccelerators disponibles.
AVHWAccel *ff_find_hwaccel(enum CodecID codec_id, enum PixelFormat pix_fmt)
{
AVHWAccel *hwaccel=NULL;
while((hwaccel= av_hwaccel_next(hwaccel))){
if ( hwaccel->id == codec_id
&& hwaccel->pix_fmt == pix_fmt)
return hwaccel;
}
return NULL;
}
Por ejemplo, dxva2 ( https://en.wikipedia.org/wiki/DirectX_Video_Acceleration ) tiene:
AVHWAccel mpeg2_dxva2_hwaccel = {
.name = "mpeg2_dxva2",
.type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_MPEG2VIDEO,
.pix_fmt = PIX_FMT_DXVA2_VLD,
.capabilities = 0,
.start_frame = start_frame,
.decode_slice = decode_slice,
.end_frame = end_frame,
.priv_data_size = sizeof(struct dxva2_picture_context),
};
Y libavutil/pixfmt.h
enumera todos los decodificadores / aceleradores hw admitidos por sus formatos de píxeles https://ffmpeg.org/doxygen/3.2/pixfmt_8h.html
AV_PIX_FMT_XVMC_MPEG2_MC - XVideo Motion Acceleration via common packet passing.
AV_PIX_FMT_XVMC_MPEG2_IDCT - undocumented
AV_PIX_FMT_XVMC - undocumented
AV_PIX_FMT_VDPAU_H264 - H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_MPEG1 - MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_MPEG2 - MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_WMV3 - WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_VC1 - VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VAAPI_MOCO - HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers.
AV_PIX_FMT_VAAPI_IDCT - HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers.
AV_PIX_FMT_VAAPI_VLD - HW decoding through VA API, Picture.data[3] contains a VASurfaceID.
AV_PIX_FMT_VDPAU_MPEG4 - MPEG-4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_DXVA2_VLD - HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
AV_PIX_FMT_VDPAU - HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface.
AV_PIX_FMT_VDA - HW acceleration through VDA, data[3] contains a CVPixelBufferRef.
AV_PIX_FMT_QSV - HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
AV_PIX_FMT_MMAL - HW acceleration though MMAL, data[3] contains a pointer to the MMAL_BUFFER_HEADER_T structure.
AV_PIX_FMT_D3D11VA_VLD - HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer.
AV_PIX_FMT_CUDA - HW acceleration through CUDA. data[i] contain CUdeviceptr pointers exactly as for system memory frames.
La selección real de formatos de píxeles está en la función llamada antes de ff_find_hwaccel
, la static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)
de libavcodec/mpeg12dec.c
para mpeg1 / 2. En versiones anteriores de ffmpeg / libavcodec verifica avctx->xvmc_acceleration
y / o avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU
o llama a avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420);
para habilitar la decodificación de hw en algunos casos.
En la versión reciente (2017), él y varias funciones cercanas realizan la selección del codificador hw https://github.com/FFmpeg/FFmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#L1189 .
Básicamente: el decodificador de hardware y su api ( XVMC , VDPAU , VA API , MS https://en.wikipedia.org/wiki/DirectX_Video_Acceleration o MS Direct3D11 obsoletos, o videotoolbox) deben estar habilitados en su compilación de ffmpeg y https://wiki.archlinux.org/index.php/Hardware_video_acceleration y sus controladores / bibliotecas (muchos de ellos son propietarios y deben estar descargado por separado). A veces, la opción -hwaccel
debe dar a ffmpeg, o el complemento cargado. En Linux, puede usar los comandos vainfo
y vdpauinfo
para probar la disponibilidad y los perfiles compatibles con las API de descodificación de video estándar más populares.
El archivo de entrada (para mpeg1 / 2) no debe ser en escala de grises, debe tener s->chroma_format
menos de 2 (4: 2: 0 submuestreo de croma , que es habitual en ISO / IEC MPEG y ITU-T VCEG H.26x; pero no para algunos MPEG-4 Parte 2 y no para altas 4: 4: 4 variantes de H.264 / MPEG-4 AVC).
static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
#if CONFIG_MPEG2_XVMC_HWACCEL
AV_PIX_FMT_XVMC,
#endif
#if CONFIG_MPEG_VDPAU_DECODER && FF_API_VDPAU
AV_PIX_FMT_VDPAU_MPEG2,
#endif
#if CONFIG_MPEG2_VDPAU_HWACCEL
AV_PIX_FMT_VDPAU,
#endif
#if CONFIG_MPEG2_DXVA2_HWACCEL
AV_PIX_FMT_DXVA2_VLD,
#endif
#if CONFIG_MPEG2_D3D11VA_HWACCEL
AV_PIX_FMT_D3D11VA_VLD,
#endif
#if CONFIG_MPEG2_VAAPI_HWACCEL
AV_PIX_FMT_VAAPI,
#endif
#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
AV_PIX_FMT_VIDEOTOOLBOX,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat mpeg12_pixfmt_list_422[] = {
AV_PIX_FMT_YUV422P,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat mpeg12_pixfmt_list_444[] = {
AV_PIX_FMT_YUV444P,
AV_PIX_FMT_NONE
};
#if FF_API_VDPAU
static inline int uses_vdpau(AVCodecContext *avctx) {
return avctx->pix_fmt == AV_PIX_FMT_VDPAU_MPEG1 || avctx->pix_fmt == AV_PIX_FMT_VDPAU_MPEG2;
}
#endif
static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)
{
Mpeg1Context *s1 = avctx->priv_data;
MpegEncContext *s = &s1->mpeg_enc_ctx;
const enum AVPixelFormat *pix_fmts;
if (CONFIG_GRAY && (avctx->flags & AV_CODEC_FLAG_GRAY))
return AV_PIX_FMT_GRAY8;
if (s->chroma_format < 2)
pix_fmts = avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO ?
mpeg1_hwaccel_pixfmt_list_420 :
mpeg2_hwaccel_pixfmt_list_420;
else if (s->chroma_format == 2)
pix_fmts = mpeg12_pixfmt_list_422;
else
pix_fmts = mpeg12_pixfmt_list_444;
return ff_thread_get_format(avctx, pix_fmts);
}
static void setup_hwaccel_for_pixfmt(AVCodecContext *avctx)
{
// until then pix_fmt may be changed right after codec init
if (avctx->hwaccel
#if FF_API_VDPAU
|| uses_vdpau(avctx)
#endif
)
if (avctx->idct_algo == FF_IDCT_AUTO)
avctx->idct_algo = FF_IDCT_SIMPLE;
if (avctx->hwaccel && avctx->pix_fmt == AV_PIX_FMT_XVMC) {
Mpeg1Context *s1 = avctx->priv_data;
MpegEncContext *s = &s1->mpeg_enc_ctx;
s->pack_pblocks = 1;
#if FF_API_XVMC
FF_DISABLE_DEPRECATION_WARNINGS
avctx->xvmc_acceleration = 2;
FF_ENABLE_DEPRECATION_WARNINGS
#endif /* FF_API_XVMC */
}
}
¿Cómo decodifico un archivo con aceleración de hardware con ffmpeg?
He escrito un reproductor de video que usa ffmpeg. He comprobado la compatibilidad con "av_hwaccel_next"
y encontré mpeg2_dxva
.
Sin embargo, cuando cargo un archivo mpeg2 (como es habitual) no obtengo ninguna aceleración de hardware. AVCodecContext->hwaccel
y AVCodecContext->hwaccelcontext
son ambos nulos.
¿Debo pasar alguna bandera en algún lugar para habilitar la aceleración de hw?
No he podido encontrar ninguna información sobre esto, ¿alguien sabe de una buena fuente?