2016-01-05 13 views
7

Pomyślnie zaimplementowałem odtwarzacz wideo za pomocą ffmpeg. Próbuję teraz użyć dekodowania sprzętowego, ale mam kilka problemów. Znalazłem wpis, który podążyłem jako punkt wyjścia tutaj: http://comments.gmane.org/gmane.comp.video.ffmpeg.libav.user/13523Nie można wykonać: 0x80070057, dekodować wideo za pomocą ffmpeg z dxva2

Zaktualizowałem kod, który ustawi niezbędne elementy dekodera. Zaktualizowany kod jest dostępny tutaj: https://drive.google.com/file/d/0B5ufHdoDzA4ieVk5UVpxcDNzRHc/view?usp=sharing

I tak używam go zainicjować dekodera:

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

A oto definicja GetHwFormat mowa powyżej:

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

Kiedy otworzę wideo MP4 (zakodowane w h264) o rozdzielczości HD lub mniejszej, wszystko wydaje się działać dobrze. Jednakże, jak tylko spróbować wyższe filmów rozdzielczości, takich jak 3840x2160, pojawia się następujący wielokrotnie błędy:

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

ja też zaczynam się następujące błędy po kilku sekundach:

co located POCs unavailable 

A wideo niepoprawnie wyświetlane: dostaję dużo artefaktów na całym wideo i jest opóźniony. Sprawdziłem pierwszy błąd w kodzie źródłowym ffmpeg. Wygląda na to, że IDirectXVideoDecoder_Execute nie powiedzie się z powodu niepoprawnego parametru. Skoro dzieje się tak z ffmpeg, musi być coś, czego mi brakuje, ale nie wiem, co. Jedyny istotny wpis, który znalazłem z tym błędem, był spowodowany wielowątkowością, ale ustawiłem wartość thread_count na 1 przed otwarciem kodeka.

Ten problem dzieje się na moim głównym komputerze, który ma następujące specyfikacje:

  • i7-4790 CPU @ 3.6GHz
  • RAM 16 GB
  • Intel HD Graphics 4600
  • systemu Windows 8.1

Ten sam problem nie występuje na moim drugim komputerze, który ma następujące dane techniczne:

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

Jeśli używam DXVAChecker na mojego głównego komputera, to mówi, że moja karta graficzna obsługuje DXVA2 dla H264_VLD_ * i widzę, że podczas odtwarzania mojego wideo są tworzone wywołania do API Microsoft (DXVA2_DecodeDeviceCreated, DXVA2_DecodeDeviceBeginFrame, DXVA2_DecodeDeviceGetBuffer, DXVA2_DecodeDeviceExecute, DXVA2_DecodeDeviceEndFrame).

Nie widzę też żadnego zwiększenia wykorzystania GPU (na żadnym komputerze) między wersją z dekodowaniem sprzętowym a wersją bez; jednak widzę zmniejszenie użycia procesora (nie tak dużo, jak się spodziewałem). Jest to również bardzo dziwne.

Zauważ, że wypróbowałem zarówno wersję systemu Windows dostępną na stronie FFmpeg, jak i wersję, którą skompilowałem z opcją --enable-dxva2. Wiele już przeszukałem, ale nie mogłem znaleźć tego, co robię źle.

Mam nadzieję, że ktoś może mi pomóc, a może wskazać lepszy przykład?

+0

Właśnie przetestowałem na Surface Pro 3 z i5 4300U @ 1,9 GHz (4 procesory), 8 GB pamięci RAM, Intel HD Graphics 4400, Windows 10 i wideo wygląda dobrze. Brak komunikatów o błędach. Użycie protokołu CPU jest o 40% mniejsze niż bez dekodowania sprzętowego, tak jak wspomniany jest wyżej wymieniony komputer.GPU ma tylko 1% lub może 2% więcej (tak samo jak w przypadku pozostałych 2 komputerów wymienionych powyżej) testowanie tego samego wideo przy 3840 x 2160 . – CD83

Odpowiedz

5

W końcu dowiedziałem się, jaki był mój problem. Po wywołaniu avcodec_decode_video2, nie było aktualizacji i rozmiar danych wskaźnik pakietu tak:

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

Teraz film jest prawidłowo dekodowane i nie mam żadnych artefaktów więcej.

Co do opóźnienia, uważam, że był to osobny problem, niezwiązany z komunikatami o błędach, oraz ze względu na czas potrzebny do skopiowania obrazu z powrotem do pamięci procesora. Jeśli chcesz to zrobić, zamiast używać av_image_copy_plane, tak jak w kodzie, który opublikowałem z powyższym pytaniem, możesz sprawdzić, co robi VLC, lub pod tym linkiem: https://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers. Zrobiłem szybki test na moim komputerze i zmniejszyło to czas o współczynnik 7 lub 8.

Powiązane problemy