Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
24 декабря 2018 г. 13:25

Переинициализация cv::VideoWriter

OpenCV

Все привет! Имею два компа, на которых подняты два сетевых интерфейса: локалку и LTE-модем (со статичными адресами). Нужно перегонять видео с одного компа на другой, но при этом должна быть возможность смены канала передачи: т.е., если была трансляция по локалке, и скомандовали перейти на модем, то видео должно перейти на модем. Для передачи использую связку cv::VideoWriter+GStreamer.

void Video_sender::onConnected(const std::string & ip)
{
    std::string gst = "appsrc ! videoconvert ! video/x-raw,format=YV12,width=";
    gst+=std::to_string(WIDTH)+",height="+std::to_string(HEIGHT)+" ! jpegenc ! rtpjpegpay ! udpsink host=";
    _ip = ip;
    gst += _ip + " port="+std::to_string(PORT_NUM);
    changeBroadcastingPath(gst);
}

void Video_sender::changeBroadcastingPath(const std::string &gstr_string)
{
    std::lock_guard<std::mutex> lock(mut_write_to_rmo);
    _gst = gstr_string;
    std::cout << "GSTREAMER STRING: " << _gst << std::endl;
    if(write_to_RMO!=nullptr)
    {
        write_to_RMO->release();
        bool res=write_to_RMO->open(_gst,  cv::CAP_GSTREAMER, 0, FPS, cv::Size(WIDTH,HEIGHT), true);
        std::cout << "write_to_RMO reinitialized: " << std::boolalpha << res << std::endl;
    }
    else
    {
        write_to_RMO = std::make_unique<cv::VideoWriter>(_gst, cv::CAP_GSTREAMER, 0, FPS, cv::Size(WIDTH,HEIGHT), true);
    }
}




Само считывание кадра из камеры и передача на второй комп происходит в отдельном потоке.

int Video_sender::ThreadMain()
{
/*Считывание кадра в cv::Mat из videoCapture*/

if(!inMat.empty())            {
                mut_write_to_rmo.lock();
                if(write_to_RMO != nullptr) /// если нет коннекта с РМО даже пытаться не будем что то передавать
                {
                    if(write_to_RMO->isOpened())
                    {
                        if(inMat.cols!=WIDTH && inMat.rows!=HEIGHT)//if(vec_frame[(xxx%(vec_p_cap.size()*100))/100.].cols != WIDTH && vec_frame[(xxx%(vec_p_cap.size()*100))/100.].rows != HEIGHT )
                        {
                            cv::Mat out;
                            //cv::resize(vec_frame[(xxx%(vec_p_cap.size()*100))/100.],out,cv::Size(WIDTH,HEIGHT)); /// изменим размер картинки на 720х1280, если он не соответствует
                            cv::resize(inMat, out, cv::Size(WIDTH,HEIGHT)); /// изменим размер картинки на 720х1280, если он не соответствует
                            //cv::imshow(" != ",out); cv::waitKey(1); /// debug
                            //std::cout << "sending frame to rmo after resizing..." << std::endl;
                            write_to_RMO->write(out);                                               /// отправка на РМО
                        }
                        else
                        {
                            //cv::imshow("640x480",inMat); cv::waitKey(1); /// debug

                            std::cout << "sending frame to rmo... " << _gst << std::endl;
                            write_to_RMO->write(inMat);      /// отпрака на  РМО
                        }
                    }
                    else
                    {
                        GetLog().log("write_to_rmo not opened");
                    }
                }
                else
                {
                    GetLog().log("write_to_rmo == nullptr");
                }
                mut_write_to_rmo.unlock();
}

По отдельности все работает. Но при попытке переключить канал, видео перестает передаваться. Хотя кадр отсылается. Текст в коде ниже выводится

std::cout << "sending frame to rmo... " << _gst << std::endl;

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

На приемном компе создается cv::VideoCapture, в который передается строка Gstreamer:

const std::string vrstr("udpsrc port=5000 ! application/x-rtp, media=video, clock-rate=90000, encoding-name=JPEG, payload=26 ! rtpjpegdepay ! jpegdec ! videoconvert ! video/x-raw, format=BGR ! appsink sync=0");

и в потоке кадры считываются из него.

В какую сторону копать? С opencv дело практически не имел. В методе changeBroadcastingPath пробовал грохать write_to_RMO и создавать заново, но это тоже не помогло.

5

на вход videoWriter на отправляющем компе подаются строки:

appsrc ! videoconvert ! video/x-raw,format=YV12,width=640,height=480 ! jpegenc ! rtpjpegpay ! udpsink host=YYY.YYY.YYY.YYY port=5000 При смене канала:

appsrc ! videoconvert ! video/x-raw,format=YV12,width=640,height=480 ! jpegenc ! rtpjpegpay ! udpsink host=XXX.XXX.XXX.XXX port=5000

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

0
  • 24 декабря 2018 г. 14:06

Может вам стоит посмотреть в сторону QMediaPlayer с помощью него и других вспомогательных классов, вы сможете сделать трансляцию без GStreamer чисто на Qt

0

Боюсь, что он не поможет, т.к. нужно обрабатывать кадры с помощью opencv, да и на отправляющем компе проект без Qt.

0

Если не ошибаюсь, то Qt тоже использует gstreamer с той лишь разницей, что напрямую к нему не придётся обращаться, поскольку он скрыт за фасадом Qt

0
  • 25 декабря 2018 г. 8:58
  • Ответ был помечен как решение.

Проблема решилась. Сам ступил. При переключении канала отсылал видео не на тот адрес.

1

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
A
22 января 2019 г. 21:22
Allyonz

C++ - Тест 001. Первая программа и типы данных

  • Результат:40баллов,
  • Очки рейтинга-8
A
22 января 2019 г. 14:15
Alex

Qt - Тест 001. Сигналы и слоты

  • Результат:89баллов,
  • Очки рейтинга6
IO
20 января 2019 г. 18:39
Ivan Otreshko

C++ - Тест 003. Условия и циклы

  • Результат:0баллов,
  • Очки рейтинга-10
Последние комментарии
22 января 2019 г. 13:17
Евгений Легоцкой

Создайте тогда тему здесь на форуме в разделе Qt с выкладками кода и вашими попытками внедрения делегата, позже гляну или может кто-то ещё глянет из опытных пользователей.
I
22 января 2019 г. 13:13
IscanderChe

Не проще тогда использовать сразу кастомный делегат с чекбоксом? Я попробовал, но там засада в том, что чекбокс показывается только при щелчке на ячейку, а дефолтно показывается значение. Как ...
22 января 2019 г. 12:15
Евгений Легоцкой

Если будет не приемлемо потом, то тогда через кастомный Item Delegate нужно будет перерисовать ячейки в той колонке.
I
22 января 2019 г. 12:09
IscanderChe

Получилось приемлемо. Спасибо!Нюанс только в том, что поле рядом с чекбоксом не пропадает, оно просто пустое, что видно при выделении ячейки. Но этого достаточно.
22 января 2019 г. 11:50
Евгений Легоцкой

Переопределить метод data для той колонки и роли Qt::DisplayRole, чтобы в том случае возвращался QVariant() я так думаю... Но возможно, что у вас там будут нюансы, если вы туда чекбокс за...
Сейчас обсуждают на форуме
23 января 2019 г. 7:54
Михаиллл

Зарание спасибо.А еще на эту тему можно будет сделать статью. Это контент будет уникальным.
23 января 2019 г. 7:37
Евгений Легоцкой

Hello. Maybe the English will be better for you? I think russian is not native language for you, or did I mistake? Did I undesrtood rightly, that you mean this documentation ( ...
I
22 января 2019 г. 13:45
IscanderChe

Всем добрый день. Суть задачи: надо, чтобы в одной из колонок QTableView вместо хранимого в QSqlTableModel значения выводился чекбокс и при смене состояния чекбокса значения в базе тоже ...
M
22 января 2019 г. 13:15
Max-P85

Евгений, огромное спасибо, все работает!
Присоединяйтесь к нам в социальных сетях

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы