Не удалось выполнить: 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 раз.

Другие вопросы по тегам