2011-05-12 15 views
12

ffmpeg를 사용하여 하드웨어 가속을 사용하여 파일을 디코딩하는 방법은 무엇입니까?Cf ++에서 ffmpeg hwaccel 사용

저는 ffmpeg를 사용하는 작동하는 비디오 플레이어를 작성했습니다. "av_hwaccel_next"을 사용하여 지원을 확인했으며 mpeg2_dxva을 발견했습니다.

그러나 일반적으로 mpeg2 파일을로드 할 때 하드웨어 가속을 얻지 못합니다. AVCodecContext->hwaccelAVCodecContext->hwaccelcontext은 모두 null입니다.

hw 가속을 사용하려면 어딘가에 플래그를 전달해야합니까?

나는 이것에 관한 어떤 정보도 찾을 수 없었습니다. 누구든지 좋은 소식을 알고 있습니까?

답변

15
시작 읽기는 FFmpeg 문서에서

: https://trac.ffmpeg.org/wiki/HWAccelIntro 더 나은 대답 How to use hardware acceleration with ffmpeg (그리고 리눅스 체크 페이지 https://wiki.archlinux.org/index.php/Hardware_video_acceleration에 대한)

도구를는 FFmpeg를 사용하여, HW 보조 식 디코딩은 수 있도록하는 -hwaccel 옵션을 사용하여 사용 가능 특정 디코더. 각 디코더에는 특정 제한이있을 수 있습니다 (예 : H.264 디코더는 기본 프로필 만 지원할 수 있음). HW 지원 인코딩은 특정 인코더 (예 : h264_nvenc)를 사용하여 활성화됩니다. HW 지원 처리 필터링은 몇 가지 필터에서만 지원됩니다. 일부 하드웨어 가속 표준 API 중 일부는 FFmpeg로 어느 정도을 지원합니다.

hwaccel 활성화를 위해 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 검사 코덱 pixelformat에서 (2013 https://github.com/FFmpeg/FFmpeg/commit/08303d774132775d49d4ba767092de5d426f089d 후 포맷 비트) 예를 들면

avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt); 

, 같은 코드에 의해 제어 된 한 쌍의 이미지와 모든 가능한 hwaccelerators. 예를 들어

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; 
} 

, dxva2 ( https://en.wikipedia.org/wiki/DirectX_Video_Acceleration)를 가지고

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), 
}; 

그리고 libavutil/pixfmt.h리스트 지원되는 모든 HW 디코더/촉진제들은 픽셀 포맷으로 픽셀 포맷 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. 

실제 선택이다 ff_find_hwaccel 전에 호출 된 함수에서 은 libavcodec/mpeg12dec.c (mpeg1/2)입니다. 이전 버전의 ffmpeg/libavcodec에서는 avctx->xvmc_acceleration 및/또는 avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU을 확인하거나 경우에 따라 hw 디코딩을 사용하기 위해 avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420);을 호출합니다.

최신 버전 (2017)에서와 그것과 몇 개의 가까운 기능이 hw 코더 https://github.com/FFmpeg/FFmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#L1189을 선택합니다.

기본적으로 : 하드웨어 디코더와 API (구식 XVMC, VDPAU, VA API, MS DXVA 또는 MS Direct3D11, 또는 videotoolbox가) 당신는 FFmpeg의 빌드 및 supported by your hardware과 드라이버/라이브러리 (많은 사람들이 소유하고 있어야한다 활성화한다 별도로 다운로드). 때로는 -hwaccel 옵션을 ffmpeg 또는 Plugin에 제공해야합니다. 리눅스에서는 가장 인기있는 표준 비디오 hw 디코딩 API로 가용성 및 지원 프로파일을 테스트 할 때 vainfovdpauinfo 명령을 사용할 수 있습니다. 2 : (MPEG1/2가)하지 회색조이어야

입력 파일, 그것은 2 (4 s->chroma_format 덜 있어야 ISO/IEC MPEG 및 ITU-T VCEG하여 H.26x위한 통상 0 Chroma subsampling, 있지만 H.264/MPEG-4 AVC의 4 : 4 : 4 변종이 아닌 일부 MPEG-4 Part 2는 제외).

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

그래서 avxx의 pix_fmt를 수동으로 PIX_FMT_DXVA2_VLD로 대체해야합니까? ffmpeg 코드를 살펴보면이 값은 읽히지 않고 설정되지 않습니다. – ronag

+0

파일 형식은 PIX_FMT_DXVA2_VLD 형식이 아닙니다. FFmpeg hwaccel에 아무 문서도 존재하지 않는 것 같습니다. – Maypeur

+0

@Maypeur, 문서는 현재 공식 문서입니다 : https://trac.ffmpeg.org/wiki/HWAccelIntro, https://wiki.archlinux.org/index.php도 확인하십시오./Hardware_video_acceleration. 귀하의 질문에 필요한 세부 정보가 필요하지 않습니다 (ffmpeg, OS Linux/Windows/Other 버전, hw 디코더는 무엇이며 설치되어 있습니까, API는 무엇입니까, 파일은 무엇입니까, 어떻게 ffmpeg를 시작 했습니까? hw 디코딩은 시작시 작동합니까? 명령 행에서'ffmpeg ') 대답 할 수 없습니다. 그러나 원래의 대답은 정확하지 않았습니다. ("아무 것도 해결하지 못함"(http://stackoverflow.com/questions/23289157/#comment35652265_23289157)), 그래서 조금 업데이트했습니다. – osgx