Jump to content
Compvision.ru
mult1plexer

VideoCapture аппаратное декодирование

Recommended Posts

Здравствуйте. Столкнулся с проблемой получения кадра с веб камеры и видео. Как оказалось opencv использует программное декодирование видео потока. В результате чего не могу получить 60fps и убрать нагрузку с процессора. Через проигрыватель, который идет с K-Lite Codec Pack все воспроизводится так как надо. Кто нибудь решал такую проблему или может есть другой способ получать кадры с видео?

  • Like 1

Share this post


Link to post
Share on other sites

А что вы собираетесь делать с полученной cv::Мат картинкой?  Многие алгоритмы вообще онлайн не работают на обычном железе.

Share this post


Link to post
Share on other sites

Сам думал сделать, но руки не доходят. Вопрос важный и по делу. Так как h.264 может аппратно декодироваться. Но и для остальных кодеков аппаратные возможности лучше испоьзовать на 100 процентов.

Share this post


Link to post
Share on other sites
3 часа назад, fotomer сказал:

А что вы собираетесь делать с полученной cv::Мат картинкой?  Многие алгоритмы вообще онлайн не работают на обычном железе.

что значит не работают онлайн? не понял этот тезис

Share this post


Link to post
Share on other sites

Попробуй принудительно изменить backend у capture: CAP_FFMPEG, CAP_DSHOW или CAP_VFW. Они выбираются по очереди, какой первый подойдёт. Возможно, что у тебя первый в списке как раз не аппаратный.

Share this post


Link to post
Share on other sites
8 часов назад, Nuzhny сказал:

Попробуй принудительно изменить backend у capture: CAP_FFMPEG, CAP_DSHOW или CAP_VFW. Они выбираются по очереди, какой первый подойдёт. Возможно, что у тебя первый в списке как раз не аппаратный.

это я первым делом сделал. как я понял у меня через directshow идет, с gstreamer не удалось запустить завершается 0xc000007ошибкой

8 часов назад, Pechkin80 сказал:

Для линукса по идеи нужен GStreamer. Интересная статья по теме:

https://blog.zhaw.ch/high-performance/2017/10/24/boost-your-gstreamer-pipeline-with-the-gpu-plugin/

я пока под windows запускаю.

Share this post


Link to post
Share on other sites

Можно у Capture посмотреть свойство CAP_PROP_BACKEND.

Share this post


Link to post
Share on other sites
15 часов назад, Nuzhny сказал:

Можно у Capture посмотреть свойство CAP_PROP_BACKEND.

что это даст? камера работает только с DSHOW в opencv, в VLC тоже самое только через DSHOW

Share this post


Link to post
Share on other sites
51 минуту назад, mult1plexer сказал:

что это даст? камера работает только с DSHOW в opencv, в VLC тоже самое только через DSHOW

А что за камера ? Камера работает по протоколу обычно и не привязана к кодеку. Если только совсем какойто ширпотреб.

Share this post


Link to post
Share on other sites

Веб-камеры используются не по протоколу, а через драйвер. Может оказаться, для неё есть DirectShow драйвер и всё. Но тут ещё вопрос, используется ли DirectShow или сейчас всё  реализовано через MSMF. Всё  - это dshow и vfw.

Думаю, что плайеры работают через DXVA, которое позволяет сразу декодировать и отображать видео. Сходу даже не уверен, можно ли его использовать в OpenCV.

Share this post


Link to post
Share on other sites
20 часов назад, Pechkin80 сказал:

А что за камера ? Камера работает по протоколу обычно и не привязана к кодеку. Если только совсем какойто ширпотреб.

китайские нонейм модули без опознавательных знаков

13 часа назад, Nuzhny сказал:

Веб-камеры используются не по протоколу, а через драйвер. Может оказаться, для неё есть DirectShow драйвер и всё. Но тут ещё вопрос, используется ли DirectShow или сейчас всё  реализовано через MSMF. Всё  - это dshow и vfw.

Думаю, что плайеры работают через DXVA, которое позволяет сразу декодировать и отображать видео. Сходу даже не уверен, можно ли его использовать в OpenCV.

так в этом и суть, что MPC-HC от k-lite  захватывает нормально не через DirectShow. Значит как минимум это можно как то поменять. В opencv проблема даже в FHD сделать захват, FPS падает до 7-10. А по дефолту открывает в 640х480

Share this post


Link to post
Share on other sites

Для аппаратного декодирования h.264/h.265/mpeg4/MJPEG можно взять библиотеки из проекта ffmpeg. Там есть реализаций кодеков с использованием SDK от  NVIDIA, AMD и INTEL, также есть варианты для мобильных устройств. В ffmpeg есть свой модуль для работы с камерами. OpenCV версий 3 и 4 можно собрать с поддержкой ffmpeg для декодирования.

Применяя аппаратный декодер и OpenCV модули с поддержкой NVIDIA Cuda и/или OpenCL, есть возможность построить алгоритмы без копирования декодированного потока в хост память.  DirectX и OpenGL поверхности в памяти  GPU могут являться источником для  OpenCl/Cuda матриц в OpenCV не покидая GPU.

  • Like 1

Share this post


Link to post
Share on other sites

ffmpeg тут ничего нового не придумал, а просто предоставляет обёртку над DirectShow.

Я уже давно этой темы не касался, надеюсь, что не навру.

Веб камеры в Windows работают через DirectShow драйвер (или WMF) и тут ничего не попишешь. Я очень сомневаюсь, что у них есть что-то своё. Соответственно, при отображении видео используется DXVA - аппаратное декодирование с выводом видео на экран. При этом кадры даже не поступают в оперативную память, а отправляются сразу на аппаратный декодер, встроенный в процессор или видеокарту. Это даже не CUDA или OpenCL, а отдельные специализированные чипы внутри процессора или видеокарты: Intel Quick Sync Video, Nvidia NVENC или AMD Video Coding Engine. Ffmpeg, например, умеет декодировать сетевое видео или файлы и на CUDA - cuvid. Но это уже будет грузить видеокарту, в отличие от полностью аппаратного Nvidia NVENC. Как всё это применить к вебкамерам я, к сожалению, не в курсе.

Share this post


Link to post
Share on other sites

Полностью справедливо для камер только с DirectShow/WMF драйвером. Некоторые имеют еще собственный драйвер и SDK, особенно с вариантами для Windows и Linux. Часто, такие камеры выдают полное разрешение и частоту кадров только в сжатом видео потоке ( Mjpeg/h.264) – видел китайcкую камеру 5Mp/60Hz/h.264 120Mbit поток, подключённую по USB2… Такие случаи как раз для аппаратного декодирования. В SDK Intel Quick Sync Video, Nvidia NVENC есть примеры копирования декодированного кадра в OpenCL/Cuda память.   

Share this post


Link to post
Share on other sites
3 часа назад, Nuzhny сказал:

ffmpeg тут ничего нового не придумал, а просто предоставляет обёртку над DirectShow.

Я уже давно этой темы не касался, надеюсь, что не навру.

Веб камеры в Windows работают через DirectShow драйвер (или WMF) и тут ничего не попишешь. Я очень сомневаюсь, что у них есть что-то своё. Соответственно, при отображении видео используется DXVA - аппаратное декодирование с выводом видео на экран. При этом кадры даже не поступают в оперативную память, а отправляются сразу на аппаратный декодер, встроенный в процессор или видеокарту. Это даже не CUDA или OpenCL, а отдельные специализированные чипы внутри процессора или видеокарты: Intel Quick Sync Video, Nvidia NVENC или AMD Video Coding Engine. Ffmpeg, например, умеет декодировать сетевое видео или файлы и на CUDA - cuvid. Но это уже будет грузить видеокарту, в отличие от полностью аппаратного Nvidia NVENC. Как всё это применить к вебкамерам я, к сожалению, не в курсе.

Примение CUDA ИМХО сомнительное дело впринцепи. Если CUDA используется для задач обработки изображений, то использование CUDA ещё и для декодирования будет приводить к частостому сбросу всего кеша GPU и снижению производительности. Я вот тоже слышал что для этого специальный чип внутри процессора или карты есть + SSE/MMX, но как убедиться что FFMPRG или GSTREAMER всё сделал поуму для декодирования ?

Я может залез не в свою тему, но как там  обстоят дело с подключением камеры за 3 бакса ИМХО не самое главное. Но в любом профессиональном решении с нормальной IP камерой этот впрос не может быть обойдён стороной.

Share this post


Link to post
Share on other sites

С ip камерами  как раз всё проще. Их можно пачкой на CUDA декодировать, а потом обрабатывать изображения, не выгружая декодированные кадры из видеопамяти. Можно отдавать их, например в TensorFlow.

Share this post


Link to post
Share on other sites
1 час назад, Nuzhny сказал:

С ip камерами  как раз всё проще. Их можно пачкой на CUDA декодировать, а потом обрабатывать изображения, не выгружая декодированные кадры из видеопамяти. Можно отдавать их, например в TensorFlow.

Хм, можно попдробнее.... Это такой интерфейс есть чтоб получать данные уже загруженные в GPU , но декодированные? Для декодирования и обработки изображений разные библиотеки используются. Я не знаком с TensorFlow, но я пологаю. что могут потребоваться какието предварительные действия, до применения TensorFlow которых нет в TensorFlow. Очень подозрительно просто что TensorFlow представляется волшебной палочкой. Всё универсальное не всегда самоелучшее.

Share this post


Link to post
Share on other sites

Получать можно в том же ffmpeg:

1. Если не собран, то собрать ffmpeg с поддержкой cuvid. Проверка: ./ffmpeg -hwaccels

2. При создании AVCodec вызвать avcodec_find_decoder_by_name("h264_cuvid") или avcodec_find_decoder_by_name("mjpeg_cuvid").

3. Перед вызовом avcodec_decode_video2 устанавливать decCtx->pix_fmt = AV_PIX_FMT_CUDA

4. Тут уже нам возвращают указатель на видеопамять в AVFrame, можно копировать её к себе и обрабатывать:

4.1. Учитываем, что в данном случае у нас кадр не YUV420, а NV12: cudaMemcpy(data, picture->data[0], height * picture->linesize[0], cudaMemcpyDefault)

4.2.  Хочется RGB? Вызываем nppiNV12ToBGR_709HDTV_8u_P2C3R

4.3. Хочется засунуть в OpenCV? Вот: cv::cuda::GpuMat* gpuFrame = new cv::cuda::GpuMat(height, width, CV_8UC1, picture->data[0], picture->linesize[0])

Выгрузить из GPU memory и сохранить? Вот: cv::Mat frame; gpuFrame->download(frame);

4.4. Хочется отобразить кадр без копирования в ОЗУ? Создаём OpenGL окно: cv::namedWindow("wnd name", cv::WINDOW_OPENGL)

 

Это про декодирование на CUDA и обработку кадра средствами OpenCV без копирования в системную память.

Про TensorFlow: тут надо использовать С++ API, на Питончике такой возможности нет. Добавили такую возможность недавно в версии 1.12: вот обсуждение.

  • Like 1

Share this post


Link to post
Share on other sites
1 час назад, Nuzhny сказал:

Получать можно в том же ffmpeg:

1. Если не собран, то собрать ffmpeg с поддержкой cuvid. Проверка: ./ffmpeg -hwaccels

2. При создании AVCodec вызвать avcodec_find_decoder_by_name("h264_cuvid") или avcodec_find_decoder_by_name("mjpeg_cuvid").

3. Перед вызовом avcodec_decode_video2 устанавливать decCtx->pix_fmt = AV_PIX_FMT_CUDA

4. Тут уже нам возвращают указатель на видеопамять в AVFrame, можно копировать её к себе и обрабатывать:

4.1. Учитываем, что в данном случае у нас кадр не YUV420, а NV12: cudaMemcpy(data, picture->data[0], height * picture->linesize[0], cudaMemcpyDefault)

4.2.  Хочется RGB? Вызываем nppiNV12ToBGR_709HDTV_8u_P2C3R

4.3. Хочется засунуть в OpenCV? Вот: cv::cuda::GpuMat* gpuFrame = new cv::cuda::GpuMat(height, width, CV_8UC1, picture->data[0], picture->linesize[0])

Выгрузить из GPU memory и сохранить? Вот: cv::Mat frame; gpuFrame->download(frame);

4.4. Хочется отобразить кадр без копирования в ОЗУ? Создаём OpenGL окно: cv::namedWindow("wnd name", cv::WINDOW_OPENGL)

 

Это про декодирование на CUDA и обработку кадра средствами OpenCV без копирования в системную память.

Про TensorFlow: тут надо использовать С++ API, на Питончике такой возможности нет. Добавили такую возможность недавно в версии 1.12: вот обсуждение.

Спасибо, интересно будет поробовать. Тогда получаеться VideoCapture class из OpenCV не используем ? Он ведь вроде как сам работает с FFMPEG ?

И управление видеопотоком тоже надо будет через FFMPEG реализовывать. Или сам VideoCapture OpenCV прпатчить для более эффективной работы ?

Share this post


Link to post
Share on other sites

Пропатчить так просто не получится, там весь интерфейс придётся менять для всех бэкендов. Кажется, что надо писать самому на ffmpeg, можно взять код работы с ним из OpenCV в качестве базового.

С другой стороны есть cudacodec из opencv_contrib, который, вроде, делает как раз необходимое. Но я его не проверял, ничего не могу сказать.

Share this post


Link to post
Share on other sites

NuzhnyБольшое спасибо за ваши ответы. Но у меня так бывает что к теме я возвращаюсь через несколько месяцев.

Share this post


Link to post
Share on other sites
В 05.02.2019 at 00:32, ppop21285 сказал:

Для аппаратного декодирования h.264/h.265/mpeg4/MJPEG можно взять библиотеки из проекта ffmpeg. Там есть реализаций кодеков с использованием SDK от  NVIDIA, AMD и INTEL, также есть варианты для мобильных устройств. В ffmpeg есть свой модуль для работы с камерами. OpenCV версий 3 и 4 можно собрать с поддержкой ffmpeg для декодирования.

 

Применяя аппаратный декодер и OpenCV модули с поддержкой NVIDIA Cuda и/или OpenCL, есть возможность построить алгоритмы без копирования декодированного потока в хост память.  DirectX и OpenGL поверхности в памяти  GPU могут являться источником для  OpenCl/Cuda матриц в OpenCV не покидая GPU.

 

 

В 05.02.2019 at 12:21, Nuzhny сказал:

С ip камерами  как раз всё проще. Их можно пачкой на CUDA декодировать, а потом обрабатывать изображения, не выгружая декодированные кадры из видеопамяти. Можно отдавать их, например в TensorFlow.

 из gpu есть Mali T860 

Share this post


Link to post
Share on other sites
В 29.01.2019 at 09:25, Nuzhny сказал:

Попробуй принудительно изменить backend у capture: CAP_FFMPEG, CAP_DSHOW или CAP_VFW. Они выбираются по очереди, какой первый подойдёт. Возможно, что у тебя первый в списке как раз не аппаратный.

У меня процессор Intel Pentium n3710 с графическим ядром INTEL HD GRAPHICS. Если верить данной таблице https://www.wikizero.com/en/Intel_Graphics_Technologyто данное графическое ядро позволяет декодировать 2k 30 кадров в секунду. 

Открываю файл 1080p, кодек h264  с принудительно заданным backend ffmpeg:
cv::VideoCapture  cam( "2.mp4", cv::CAP_FFMPEG);
Загрузка процессора от 25 до 60%.
Открываю данный файл, используя Microsoft Media Foundation:
cv::VideoCapture  cam( "2.mp4", cv::CAP_MSMF);
Загрузка процессора от 10 до 25%. Почему так происходит?! Насколько я читал ffmpeg использует аппаратное декодирование.

Share this post


Link to post
Share on other sites

ffmpeg сам по себе может что-то и не уметь, если его специально не собрали с поддержкой этого аппаратного ускорения. Хотя логично было бы его включать для интеловских процессоров. Если у тебя есть просто собранный отдельно ffmpeg (или скачанный), то можешь посмотреть, что он умеет и повыбирать разные кодеки из командной строки.

Например, команда "ffmpeg -hwaccels" выведен список доступных аппаратных кодеков.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×