2016-01-05 113 views
7

我已經成功使用ffmpeg實現了一個視頻播放器。我現在試圖使用硬件解碼,但我面臨一些問題。 我發現一個帖子,我作爲一個起點在這裏:http://comments.gmane.org/gmane.comp.video.ffmpeg.libav.user/13523無法執行:0x80070057,當通過ffmpeg與dxva2解碼視頻時

我已經更新了設置解碼器必要的東西的代碼。更新後的代碼可以在這裏找到:https://drive.google.com/file/d/0B5ufHdoDzA4ieVk5UVpxcDNzRHc/view?usp=sharing

這是我如何使用它來初始化解碼器:

// Prepare the decoding context 
AVCodec *codec = nullptr; 
_codecContext = _avFormatContext->streams[_streamIndex]->codec; 
if ((codec = avcodec_find_decoder(_codecContext->codec_id)) == 0) 
{ 
    std::cout << "Unsupported video codec!" << std::endl; 
    return false; 
} 

_codecContext->thread_count = 1; // Multithreading is apparently not compatible with hardware decoding 
InputStream *ist = new InputStream(); 
ist->hwaccel_id = HWACCEL_AUTO; 
ist->hwaccel_device = "dxva2"; 
ist->dec = codec; 
ist->dec_ctx = _codecContext; 
_codecContext->coded_width = _width; 
_codecContext->coded_height = _height; 

_codecContext->opaque = ist; 
dxva2_init(_codecContext); 

_codecContext->get_buffer2 = ist->hwaccel_get_buffer; 
_codecContext->get_format = GetHwFormat; 
_codecContext->thread_safe_callbacks = 1; 

if (avcodec_open2(_codecContext, codec, nullptr) < 0) 
{ 
    std::cout << "Video codec open error" << std::endl; 
    return false; 
} 

這裏是上文提到的GetHwFormat的定義:

AVPixelFormat GetHwFormat(AVCodecContext *s, const AVPixelFormat *pix_fmts) 
{ 
    InputStream* ist = (InputStream*)s->opaque; 
    ist->active_hwaccel_id = HWACCEL_DXVA2; 
    ist->hwaccel_pix_fmt = AV_PIX_FMT_DXVA2_VLD; 
    return ist->hwaccel_pix_fmt; 
} 

當我打開HD分辨率或更低的mp4(編碼在h264)視頻時,一切似乎都正常工作。然而,當我嘗試像3840X2160分辨率更高的視頻,我收到以下錯誤反覆:

Failed to execute: 0x80070057 
Hardware accelerator failed to decode picture 

我也開始得到了幾秒鐘後,出現以下錯誤:

co located POCs unavailable 

而且視頻沒有正確顯示:我在整個視頻中看到很多文物,並且比較滯後。我檢查了ffmpeg源代碼中的第一個錯誤。由於參數無效,IDirectXVideoDecoder_Execute似乎失敗。由於這是使用ffmpeg發生的,所以我一定會丟失一些東西,但我無法弄清楚是什麼。我發現有這個錯誤的唯一相關帖子是因爲多線程,但我在打開編解碼器之前將thread_count設置爲1。

這個問題正在發生具有以下規格我的主計算機上:

  • i7-4790 CPU @ 3.6GHz的
  • RAM 16 GB
  • 英特爾高清顯卡4600
  • 的Windows 8.1

同樣的問題不會發生在我的第二臺電腦上,它有以下規格:

  • 酷睿i7 4510U @ 2GHz的
  • RAM 8 GB
  • NVIDIA的GeForce GTX 750Ti
  • 的Windows 10

如果我使用DXVAChecker我的主計算機上,它說,我的顯卡支持DXVA2對於H264_VLD_ *,我可以看到正在播放視頻時正在調用Microsoft API(DXVA2_DecodeDeviceCreated,DXVA2_DecodeDeviceBeginFrame,DXVA2_DecodeDeviceGetBuffer,DXVA2_DecodeDeviceExecute,DXVA2_DecodeDeviceEndFrame)。

在硬件解碼版本和沒有版本之間,我也看不到任何GPU使用率(在任一臺計算機上)的增加;不過,我確實看到CPU使用率下降(不像我期待的那麼多)。這也很奇怪。

請注意,我嘗試了FFmpeg網站上提供的Windows版本以及使用--enable-dxva2編譯的版本。我已經搜索了很多,但我無法找到我做錯了什麼。

希望有人能幫助我,或者讓我指出一個更好的例子?

+0

我還剛剛在Surface Pro 3上測試了i5 4300U @ 1.9GHz(4 CPU),8 GB RAM,英特爾高清顯卡4400,Windows 10和視頻看起來不錯。沒有錯誤信息.CPU的使用比沒有像上述第二臺計算機那樣的硬件解碼要少40%。在3840x2160處測試相同的視頻,GPU僅爲1%或2%多(與上述其他2臺計算機相同) 。 – CD83

回答

5

我終於知道我的問題是什麼了。調用avcodec_decode_video2後,我並沒有更新數據包的大小和數據指針這樣的:現在

int r = avcodec_decode_video2(_codecContext, frame, &frameDecoded, &pkt); 
pkt.size -= r; 
pkt.data += r; 

,視頻被正確地解碼和我沒有任何文物了。

此外,關於滯後,我認爲這是一個單獨的問題,與錯誤消息無關,並且由於將圖像複製回CPU內存需要時間。如果你需要這樣做,而不是使用av_image_copy_plane,就像我在上面的問題中發佈的代碼一樣,你可能想看看VLC做什麼,或者在這個鏈接https://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers。我在我的機器上做了一個快速測試,它將時間縮短了7或8倍。