2expres 7 Report post Posted March 11, 2019 11 час назад, Nuzhny сказал: Например, команда "ffmpeg -hwaccels" выведен список доступных аппаратных кодеков. Мне для аппаратного декодирования нужен qsv (Intel Quick Sync Video). Но на сайте ffmpeg читаю: Ensure the target machine has a supported CPU. Current versions only support gen8/gen9 graphics on expensive CPUs ("Xeon"/"Core i" branding). The same graphics cores on cheaper CPUs ("Pentium"/"Celeron"/"Atom" branding) are explicitly disabled, presumably for commercial reasons. Т.е. для Pentium и процессоров ниже отключена аппаратная поддержка по коммерческим причинам. cv::CAP_MSMF - не работает с rtsp потоком (Хотя Microsoft Media Foundation вроде ж должна поддерживать). Что применить??? Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted March 12, 2019 Тебе в качестве декодера в ffmpeg надо указать dxva2. MSMF его и использует, поэтому получается быстрее. Кажется, что лучше используовать ffmpeg напрямую, что все и делают в критических по производительности приложениях. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 20, 2019 В 2/5/2019 at 14:14, 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: вот обсуждение. Дошли руки попробовать, но тут не сказано как это должно быть связано с загрузкой видеофайла или захвата видеопотока. Моя попытка успехом не увенчалась: static AVFormatContext *fmt_ctx = nullptr; static AVCodecContext *dec_ctx = nullptr; static int video_stream_index = -1; static int open_input_file(const char *filename = videofilename) { int ret; AVCodec *dec; if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n"); return ret; } if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n"); return ret; } /* select the video stream */ ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n"); return ret; } video_stream_index = ret; dec_ctx = fmt_ctx->streams[video_stream_index]->codec; av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0); avcodec_register_all(); AVCodec* codec = avcodec_find_decoder_by_name("h264_cuvid"); AVCodecContext * avctx = avcodec_alloc_context3(codec); dec_ctx = avctx; dec = codec; avctx->pix_fmt = AV_PIX_FMT_CUDA; //if (avcodec_open2(avctx, codec, opts) < 0) // return; /* init the video decoder */ if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n"); return ret; } return 0; } Вывод приложения: Цитата [h264_cuvid @ 0x55fefb78a440] Codec h264_cuvid is not supported. Cannot open video decoder Вывод утилиты: Цитата (base) user@aspire:/opt/ffmpeg/v345/ffmpeg-3.4.5$ ./ffmpeg -hwaccels ffmpeg version 3.4.5 Copyright (c) 2000-2018 the FFmpeg developers built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04) configuration: libavutil 55. 78.100 / 55. 78.100 libavcodec 57.107.100 / 57.107.100 libavformat 57. 83.100 / 57. 83.100 libavdevice 57. 10.100 / 57. 10.100 libavfilter 6.107.100 / 6.107.100 libswscale 4. 8.100 / 4. 8.100 libswresample 2. 9.100 / 2. 9.100 Hardware acceleration methods: cuvid Share this post Link to post Share on other sites
2expres 7 Report post Posted September 21, 2019 Я использовал dxva2. Работает и с потоком и с файлами h264. Ты сам собирал ffmpeg или брал готовую сборку? Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 21, 2019 5 минут назад, 2expres сказал: Я использовал dxva2. Работает и с потоком и с файлами h264. Ты сам собирал ffmpeg или брал готовую сборку? сам собирал. Share this post Link to post Share on other sites
2expres 7 Report post Posted September 21, 2019 Возьми сборку зераное https://ffmpeg.zeranoe.com/builds/ качаешь 2 архива shared и dev перед этим выбрав 32 или 64 бит. В архиве dev хранятся библиотеки (.lib) и include. Архив shared содержит необходимые .dll которые необходимо будет переписать в папку с вашей будущей программой - это для Windows. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted September 23, 2019 Я за точку старта брал код для работы с ffmpeg из OpenCV, потому что точно знаю, что он работает. Вариант не идеальный, но, повторюсь, рабочий. Кстати, проверь для видео стрима, который ты получил, что он правильный: std::cout << avcodec_get_name(stream->codecpar->codec_id) << ": " << stream->codecpar->codec_id << std::endl; Вообще, программировать с ffmpeg то ещё удовольствие, документация так себе, до правильного ответа приходится доходить чуть ли не методом тыка. Я не уверен, что всё делал правильно, но оно заработало. Эталонный вариант типа ffplay очень сложен: много тысяч строк в одном файле, всё смешано, куча goto. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 23, 2019 31 минуту назад, Nuzhny сказал: Я за точку старта брал код для работы с ffmpeg из OpenCV, потому что точно знаю, что он работает. Вариант не идеальный, но, повторюсь, рабочий. Кстати, проверь для видео стрима, который ты получил, что он правильный: std::cout << avcodec_get_name(stream->codecpar->codec_id) << ": " << stream->codecpar->codec_id << std::endl; Вообще, программировать с ffmpeg то ещё удовольствие, документация так себе, до правильного ответа приходится доходить чуть ли не методом тыка. Я не уверен, что всё делал правильно, но оно заработало. Эталонный вариант типа ffplay очень сложен: много тысяч строк в одном файле, всё смешано, куча goto. У меня нет переменной stream в коде. Код: std::cout << avcodec_get_name(fmt_ctx->streams[video_stream_index]->codecpar->codec_id) << ": " << fmt_ctx->streams[video_stream_index]->codecpar->codec_id << std::endl; Выдаёт: mpeg4: 13 Сама структура ...->streams[video_stream_index]->codec; определена как деприкейтед и на замену предлогают streams[video_stream_index]->codecpar Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 23, 2019 const char * imagefilename = "Image_paint.jpg"; static AVFormatContext *fmt_ctx = nullptr; static AVCodecContext *dec_ctx = nullptr; static int video_stream_index = -1; static int open_input_file(const char *filename = videofilename) { /* avcodec_register_all(); AVCodec* codec = avcodec_find_decoder_by_name("mpeg4_cuvid"); AVCodecContext * avctx = avcodec_alloc_context3(codec); avctx->pix_fmt = AV_PIX_FMT_CUDA; */ int ret; AVCodec *dec; if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n"); return ret; } if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n"); return ret; } /* select the video stream */ ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n"); return ret; } video_stream_index = ret; dec_ctx = fmt_ctx->streams[video_stream_index]->codec; av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0); std::cout << avcodec_get_name(fmt_ctx->streams[video_stream_index]->codecpar->codec_id) << ": " << fmt_ctx->streams[video_stream_index]->codecpar->codec_id << std::endl; avcodec_register_all(); AVCodec* codec = avcodec_find_decoder_by_name("mpeg4_cuvid"); if (codec != nullptr) { std::cout << "codec found" << std::endl; } fmt_ctx->streams[video_stream_index]->codecpar->codec_id = codec->id; fmt_ctx->streams[video_stream_index]->id = codec->id; fmt_ctx->streams[video_stream_index]->codecpar->codec_type = codec->type; //fmt_ctx->streams[video_stream_index]->codecpar->format = *codec->pix_fmts; fmt_ctx->streams[video_stream_index]->codec->codec_id = codec->id; fmt_ctx->streams[video_stream_index]->codec->codec_type = codec->type; fmt_ctx->streams[video_stream_index]->codecpar->format = AV_PIX_FMT_CUDA; dec_ctx = fmt_ctx->streams[video_stream_index]->codec; dec_ctx->pix_fmt = AV_PIX_FMT_CUDA; ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); std::cout << avcodec_get_name(fmt_ctx->streams[video_stream_index]->codecpar->codec_id) << ": " << fmt_ctx->streams[video_stream_index]->codecpar->codec_id << std::endl; //AVCodecContext * avctx = avcodec_alloc_context3(codec); //dec_ctx = avctx; //dec = codec; //avctx->pix_fmt = AV_PIX_FMT_CUDA; //if (avcodec_open2(avctx, codec, opts) < 0) // return; /* init the video decoder */ if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n"); return ret; } AVFrame *mpDecodedFrame = av_frame_alloc(); int got; AVPacket tsPkt; av_init_packet(&tsPkt); avcodec_decode_video2(dec_ctx, mpDecodedFrame, &got, &tsPkt); return 0; } Вот так исполняется без ошибок, но надо понять как реализовать считывание кадра за кадром, и вдобавок как сделать перемотку назад. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted September 23, 2019 3 hours ago, Pechkin80 said: std::cout << avcodec_get_name(fmt_ctx->streams[video_stream_index]->codecpar->codec_id) << ": " << fmt_ctx->streams[video_stream_index]->codecpar->codec_id << std::endl; Выдаёт: mpeg4: 13 У меня на файл со сжатием h264 пишет: h264: 27. Ну и на ip-камеру, для которой всё это и делалось, аналогично. А команда "ffmpeg -hwaccels" даёт: Quote Hardware acceleration methods: cuda opencl cuvid 3 hours ago, Pechkin80 said: Сама структура ...->streams[video_stream_index]->codec; определена как деприкейтед и на замену предлогают streams[video_stream_index]->codecpar Это да, никто codec и не предлагал использовать. Ещё раз повторюсь, что я брал за точку старта код из OpenCV, в нём реализовано всё необходимое. И уже его модифицировал под свои задачи. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 23, 2019 А видеокарта какая у тебя ? Моей (940М) тупо нет в списке https://developer.nvidia.com/video-encode-decode-gpu-support-matrix#Decoder Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted September 23, 2019 У меня их несколько и все из этого списка Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 23, 2019 6 минут назад, Nuzhny сказал: У меня их несколько и все из этого списка А на джетсоне они тоже из этого сиска ? Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted September 23, 2019 На джетсоне, если ты имеешь в виду Nano, всё должно быть иначе, потому что на нём нет выделенной видеопамяти, она общая системная. Ну и его использовать можно иначе: подключать не ip камеру, а веб или промышленную, получать с неё сразу несжатое видео. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted September 23, 2019 7 минут назад, Nuzhny сказал: На джетсоне, если ты имеешь в виду Nano, всё должно быть иначе, потому что на нём нет выделенной видеопамяти, она общая системная. Ну и его использовать можно иначе: подключать не ip камеру, а веб или промышленную, получать с неё сразу несжатое видео. Спасибо. с пайплайном почти разобрался. Еслибы ещё входной и выходной тензор у тф научился бы окунать в gpu, то былобы вообще супер. Share this post Link to post Share on other sites