Не удалось выполнить: 0x80070057, при декодировании видео через ffmpeg с помощью dxva2
Я успешно реализовал видеоплеер с помощью ffmpeg. Я сейчас пытаюсь использовать аппаратное декодирование, но я столкнулся с парой проблем. В качестве отправной точки я нашел пост, за которым следовал: http://comments.gmane.org/gmane.comp.video.ffmpeg.libav.user/13523
Я обновил код, который устанавливает необходимые вещи для декодера. Обновленный код доступен здесь: 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;
}
Когда я открываю видео в формате mp4 (закодированное в h264) с разрешением HD или ниже, кажется, что все работает нормально. Однако, как только я пробую видео с более высоким разрешением, например, 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,6 ГГц
- RAM 16 ГБ
- Intel HD Graphics 4600
- Windows 8.1
Та же проблема не возникает на моем втором компьютере, который имеет следующие характеристики:
- i7 4510U @ 2 ГГц
- RAM 8 ГБ
- NVIDIA GeForce GTX 750Ti
- Windows 10
Если я использую DXVAChecker на своем главном компьютере, он говорит, что моя видеокарта поддерживает DXVA2 для H264_VLD_*, и я вижу, что выполняются вызовы API-интерфейса Microsoft (DXVA2_DecodeDeviceCreated, DXVA2_DecodeDeviceBeginFrame, DXVA2_DeeeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDeDe WeDeDe WeDeEeDeDeDe WeDeDe WeDeDe WeDeDe WeDeFeD) играть.
Я также не вижу увеличения использования графического процессора (на обоих компьютерах) между версией с аппаратным декодированием и версией без; Тем не менее, я вижу снижение загрузки процессора (не так сильно, как я ожидал). Это тоже очень странно.
Обратите внимание, что я попробовал как версию Windows, доступную на веб-сайте FFmpeg, так и версию, которую я скомпилировал с --enable-dxva2. Я уже много искал, но не смог найти, что я делаю не так.
Надеюсь, кто-нибудь может мне помочь или, может быть, укажет на лучший пример?
1 ответ
Я наконец узнал, в чем была моя проблема. После вызова avcodec_decode_video2 я не обновлял размер и указатель данных пакета следующим образом:
int r = avcodec_decode_video2(_codecContext, frame, &frameDecoded, &pkt);
pkt.size -= r;
pkt.data += r;
Теперь видео правильно декодировано, и у меня больше нет артефактов.
Кроме того, что касается задержки, я считаю, что это была отдельная проблема, не связанная с сообщениями об ошибках, и из-за времени, которое требуется для копирования изображения обратно в память процессора. Если вам нужно сделать это, вместо использования av_image_copy_plane, как в коде, который я разместил с моим вопросом выше, вы можете посмотреть, что делает VLC, или по этой ссылке https://software.intel.com/en-us. / article / копирование-ускорение-видео-декодирование-кадровые буферы. Я провел быстрый тест на моей машине, и он сократил время в 7 или 8 раз.