2011-05-12 27 views
12

¿Cómo decodifico un archivo con aceleración de hardware con ffmpeg?usando ffmpeg hwaccel de C++

He escrito un reproductor de video que usa ffmpeg. He verificado la compatibilidad con "av_hwaccel_next" y he encontrado mpeg2_dxva.

Sin embargo, cuando cargo un archivo mpeg2 (como de costumbre) no obtengo ninguna aceleración de hardware. AVCodecContext->hwaccel y AVCodecContext->hwaccelcontext son ambos nulos.

¿Tengo que pasar alguna bandera en algún lugar para habilitar la aceleración de hw?

No he podido encontrar ninguna información al respecto, ¿alguien sabe de una buena fuente?

Respuesta

15

inicio de la lectura de la documentación ffmpeg: https://trac.ffmpeg.org/wiki/HWAccelIntro y mejor respuesta How to use hardware acceleration with ffmpeg (y para Linux página de comprobación https://wiki.archlinux.org/index.php/Hardware_video_acceleration)

Cuando se utiliza FFmpeg la herramienta, la decodificación HW-asistida se habilita el uso a través de la opción de -hwaccel, lo que permite una decodificador específico. Cada decodificador puede tener limitaciones específicas (por ejemplo, un decodificador H.264 solo puede admitir el perfil de referencia). La codificación asistida por HW se habilita mediante el uso de un codificador específico (por ejemplo h264_nvenc). El filtrado del proceso asistido por HW solo se admite en algunos filtros. Existen varias API de aceleración de hardware API, , algunas de las cuales son compatibles con hasta cierto punto por FFmpeg.

activación hwaccel fue controlado por código como (bit reformateado 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); 

El códec ff_find_hwaccel cheques y PixelFormat par de imágenes 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 listas de todos los hw decodificadores/aceleradores apoyados 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 es en la función llamada antes de ff_find_hwaccel, static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) de libavcodec/mpeg12dec.c para mpeg1/2. En versiones anteriores de ffmpeg/libavcodec comprueba avctx->xvmc_acceleration y/o avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU o llama al avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420); para habilitar la decodificación hw en algunos casos.

En la versión más reciente (2017) y en varias funciones cercanas, haga la selección de hw coder https://github.com/FFmpeg/FFmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#L1189.

Básicamente: decodificador de hardware y su API (obsoleta XVMC, VDPAU, VA API, MS DXVA o MS Direct3D11 o videotoolbox) deben estar habilitadas en su acumulación de ffmpeg y supported by your hardware y su conductor/bibliotecas (muchos de ellos son de propiedad y debe haber descargado por separado). A veces, la opción -hwaccel se debe dar a ffmpeg, o al plugin cargado. En Linux, puede usar los comandos vainfo y vdpauinfo para probar la disponibilidad y los perfiles compatibles con la mayoría de las API de decodificación de video hw estándar más populares.

archivo de entrada (para MPEG1/2) no debe ser en escala de grises, debe tener s->chroma_format menos de 2 (4: 2: 0 Chroma subsampling, que es habitual para la norma ISO/IEC MPEG e ITU-T VCEG H.26x, pero no para MPEG-4 Parte 2 y no para alta 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 */ 
    } 
} 
+0

¿Debo reemplazar el pix_fmt de avctx manualmente por PIX_FMT_DXVA2_VLD? Cuando miro el código de ffmpeg, solo veo leer este valor, nunca establecerlo. – ronag

+0

Ningún archivo será formato PIX_FMT_DXVA2_VLD. Parece que no existe documentación en FFmpeg hwaccel ... – Maypeur

+0

@Maypeur, la documentación es oficial ahora: https://trac.ffmpeg.org/wiki/HWAccelIntro, también consulte https://wiki.archlinux.org/index.php/Hardware_video_acceleration. Su pregunta no tiene detalles necesarios (versión de ffmpeg, sistema operativo Linux/Windows/Otro; ¿cuál es su decodificador hw y está instalado, cuál es su API, cuál es su archivo, cómo comenzó ffmpeg, funciona hw decode al iniciar 'ffmpeg' desde la línea de comandos) y no se puede responder. Pero mi respuesta original no era muy correcta (["no resuelve nada"] (http://stackoverflow.com/questions/23289157/#comment35652265_23289157)), así que actualicé un poco. – osgx

Cuestiones relacionadas