MJPG-Streamer, Rapbberry, CSI Camera. Стриминг как клиент

Тема в разделе "Raspberry Pi", создана пользователем Sanchez5890, 31 июл 2019.

  1. Sanchez5890

    Sanchez5890 Нерд

    Я имел немного другое в виду... Не получается. Вот моя последовательность действий
    1. Код (Bash):
      socat \
          -v \
          TCP-LISTEN:10500,crlf,reuseaddr,fork \
          SYSTEM:"
              echo HTTP/1.1 200 OK;
              echo Content-Type\: text/plain;
              echo;
              echo \"Server: \$SOCAT_SOCKADDR:\$SOCAT_SOCKPORT\";
              echo \"Client: \$SOCAT_PEERADDR:\$SOCAT_PEERPORT\";
          "
    2. Теперь пишу в малине
      Код (Bash):
      socat - TCP4:<белый ip>:10500
    3. Теперь есть ip малины 85.26.234.88
    4. Теперь запускаю mjpg-streamer с портом 8080 (по умолчанию)
    5. Теперь запускаю вилку на пк
      Код (Bash):
      socat tcp-listen:10300,fork tcp-connect:85.26.234.88:8080
    6. Запускаю mplayer с ip пк и портом 10300
      Ничего не происходит... Что опять не так-то?
     
  2. Igor68

    Igor68 Гуру

    У вас сервер на малине, который отдаёт видео имеет порт 8080?
     
    Последнее редактирование: 2 авг 2019
  3. Sanchez5890

    Sanchez5890 Нерд

    Да да на малине запускаем сервер mjpg-streamer, он сервер, висит на 8080 порту
     
  4. Sanchez5890

    Sanchez5890 Нерд

     
  5. Igor68

    Igor68 Гуру

    Надо подумать....
     
  6. Sanchez5890

    Sanchez5890 Нерд

    А почему вариант с вилкой на малине плохой?
     
  7. Sanchez5890

    Sanchez5890 Нерд

    Она считывает данные с mjpg-streamer-сервера и отсылает на медиаплеер?
    Как такой вариант?
     
  8. Sanchez5890

    Sanchez5890 Нерд

    Я пробовал также, организовать вилку на малине, но вот сделал её на питоне и сокетах. Не знаю как на socat:(
    Вот задержки, жуткие задержки и артефакты при использовании такой вилки и udp.
    Кстати про модем. Я пока не покупал сим-карту для него, тк цены приличные на нынешние интернет тарифы, поэтому использую смартфон как модем. Может из-за этого задержки? Возможно да, так как, когда я тестировал на локалке, то с udp внизу просто появляется артефактная полоска, задержки нет. Вот кстати вилочка:
    Код (Python):
    import urllib.request
    import socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    stream=urllib.request.urlopen('http://localhost:8080/?action=stream')
    data = bytes()
    while True:
        data=stream.read(1024)
        sock.sendto(data, ('белый ip', 11000))
    Проигрываю я всё это чудо через mjpg плеер написанный с помощью opencv. Почему? Нету всяких кеширований. На локалке показал себя намного лучше чем mplayer и vlc. Плюс он гибок в подключениях (можно использовать сокеты) + его можно впихнуть в PyQt.
    Код (Python):
    import cv2
    import numpy as np
    import socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('', 11000))
    data = bytes()
    while True:
        data += conn.recv(1024)
        a = data.find(b'\xff\xd8')
        b = data.find(b'\xff\xd9')
        if a != -1 and b != -1:
            jpg = data[a:b+2]
            data = data[b+2:]
            i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
            cv2.imshow('i', i)
            if cv2.waitKey(1) == 27:
                exit(0)
     
     
    Igor68 нравится это.
  9. Igor68

    Igor68 Гуру

    Если всё работает, то что надо?
    Тормоза? Так ведь питон интерпретатор. Ведь в цикле while он (питон) интерпретирует каждую строчку каждый раз. Либо избавляетесь от цикла, либо компилируете. Про компиляцию питоновских программ Вам надо почитать. Причём по другому у Вас не выйдет. Время на разбор (анализ содержимого) каждой строки программы каков? В своих программах на Си я делаю специальную задержку в микросекундах.
    Код (C++):
    //рабочий процесс камеры
    void* CamLoop(void * pr)
    {
            cv::Mat src;
            //
            ap1 = 3;
            ap2 = 1;
            //
            tmark = 0;
            //
            printf("start cam loop...\n");
            //
            while(1)
            {
                    src = cvQueryFrame(capture);
                    pthread_mutex_lock(&CamMutex);
                    cv::cvtColor(src, gray, CV_BGR2GRAY);
                    pthread_mutex_unlock(&CamMutex);
                    usleep(_wait_cam);
            }
            //
            pthread_exit(0);
    }
    Тут я делаю задержку для другого потока. А в общем каждый кадр сохраняю в /dev/shm. Там каждый раз новый свежий кадр. И другие программы/потоки имеют к ним доступ. Пусть будет это сервер, клиент и др. Там размер фиксирован согласно кадру. А тормоза у меня так же есть, но только в режиме работы через прокси на другой малине по одному и тому же wifi (к одному wifi обе малины и ПК). Стоит ПК подключить к малине по второму wifi то тормоза исчезают. Вторая малина у меня с внутренним wifi и с 2-м USB-wifi. В моём случае 5-10 кадров/сек достаточно. Хотя когда отключаю другие программы на первой малине спокойно работает и 10-20 кадров/сек.
     
    Sanchez5890 нравится это.
  10. Igor68

    Igor68 Гуру

    А вообще превращаю кадр в BMP формат в другом потоке:
    Код (C++):
    void dataToBMP(void)
    {
            U32             cntx, cnty, cntbyte;
            U32             y;
            uint32_t        addr;
            //
            cnty    = 0;
            cntbyte = 0;
            //
            pthread_mutex_lock(&CamMutex);
            //
            while(cnty < height)
            {
                    y = height - cnty;
                    cntx = 0;
                    while(cntx < width)
                    {
                            BMP_SetPixel(cntx, y, gray.at<char>(cnty,cntx), 0, 0);
                            cntx++;
                    }
                    cnty++;
            }
            pthread_mutex_unlock(&CamMutex);
    }
     
    Есть и третий поток, но уже в сервере, который конвертирует BMP в PNG для уменьшения трафика при передаче.
     
    Sanchez5890 нравится это.
  11. Igor68

    Igor68 Гуру

    Тут на форуме рассматривался вопрос про Web Socket.
     
    Sanchez5890 нравится это.
  12. Sanchez5890

    Sanchez5890 Нерд

    Добрый день! Вот ситуация складывается вот так вот. Если всё запустить на локалке, то тормозов нету. Есть только из-за udp внизу "артефактная полоска". Как только подключаю малину к wifi от смартфона, меняю подключение на белый ip пк, то даже с udp картинка становится невыносимой. Тормоза и артефакты.
    Учитывая ситуацию с локалкой, смею ли я предположить, что со временем выполнения кода всё ок? Я поискал методы компиляции для линукса (я использую Ubuntu), но всё только под винду:(.

    Может также стоит увеличивать скорость соединения? Из ходя из этого я сегодня буду пробовать ставить модем с симкой на малину. Я даже антену к модему прикупил.
    Может ли быть такая ситуация что во время переадресации на роутере, данные теряются?
    Кстати попробую webSocket, хотя скажется ли это как-то на скорости или потере данных при использовании udp?

    Я стремлюсь получить картинку с частотой ну кадров 20 в секунду, можно с артефактами, но не очень много.
     
  13. Igor68

    Igor68 Гуру

    Не могу сказать.... только если сам не стану решать тему... но... Но у меня возможность только в локальной сети.
     
  14. Sanchez5890

    Sanchez5890 Нерд

    Значит буду экспериментировать, отпишусь как будут положительные или отрицательные результаты. В любом случае огромное вам человеческое спасибо!
     
  15. Igor68

    Igor68 Гуру

    Питоном не интересуюсь, но слышал, что код уже отлаженный можно откомпилировать. Попробуйте. Думаю, что у Вас всё получится.
     
  16. Sanchez5890

    Sanchez5890 Нерд

    Добрый вечер, да можно откомпилировать под винду через pyinstaller и cx_Freeze. Но вот под убунту или другой линукс все на форумах пишут "Зачем тебе нужна компиляция, если на линуксе и так у всех питон стоит". Но я продолжу поиски как можно преобразовать питон в машинный код. Кстати если на винде это exe, то на линуксе это deb как я понинимаю?

    Ещё одна новость немного плохая для меня (а может не совсем). Вот на малинке с модемом и моим " UDP питон прокси" перегонял видеотрансляцию на мой пк с белым ip. Условия сети хорошие (на модеме антенна, оператор "яйцо", LTE), но прилетают ВСЕ битые кадры. пробовать tcp даже не буду. И что я теперь думаю. Вот на локалке хорошо всё работает без компиляции. Но глобально как видно всё просто ужасно, видеопоток проходя через сотовые вышки, маршрутизаторы, фаерволлы просто рассыпается. Вот я думаю (но может я не прав), что компиляция здесь будет как вишенка на торте. Возможно таким методом получится немного убрать задержку, но "спасти" изображение от разрушения думаю не выйдет.

    Я внимательно прочитал вот эту статью на хабре (https://habr.com/ru/company/oleg-bunin/blog/413479/), где рассказывают как создавали OKLive. Сложные стриминг сервисы, написание собственного модифицированного udp - имея такие знания можно делать замечательные и прибыльные вещи. Давайте из этого сделаем вывод - нужно избавится от любых прокси, всё только напрямую плеер и сервер, никаких посредников. Изходя из этого я провёл эксперемент.

    Я сменил роли - теперь пк с модемом, а малина с белым ip. Но подключим малину через wifi, чтобы сэмитировать похожие условия с модемом. Подключаюсь к серверу трансляции и вижу вполне интересную картину: Нет артефактов вообще, задержка пару секунд, нет нарастающей tcp задержки, fps невелик и даже немного плохой, но хватает. Думаю снижая качество картинки можно добиться баланса (качество очень хорошее).

    Вот что я теперь думаю, может мне стоит искать способ запуска mjpg-streamer как клиента? На прокси можно ставить огромный жирный крест... Что Вы думаете? Вы согласны со мной?
     
  17. Sanchez5890

    Sanchez5890 Нерд

    Вот я залез в плагины mjpg-streamer на github и нашел параметр неописанный в мане.
    Вот плагин который выводит стрим на http: https://github.com/jacksonliam/mjpg...xperimental/plugins/output_http/output_http.c
    Строка 110-111
    Код (C++):
    {"l", required_argument , 0, 0},
    {"listen", required_argument, 0, 0},
    Строка 191
    Код (C++):
     OPRINT("HTTP Listen Address..: %s\n", hostname);
    Наверное он даёт слушать какой-нибудь адрес. Но что ему делать в output. Вопрос риторический...
     
  18. Igor68

    Igor68 Гуру

    Прокси как собак, и ни куда Вы не уйдёте от них... Вы же не в локалке. Но есть proxychains, который это решает. С его помощью можете хоть через америку делать соединения.
     
  19. Sanchez5890

    Sanchez5890 Нерд

    proxychains интересно, что это. Гугл как говориться мне в помощь
     
  20. Igor68

    Igor68 Гуру

    да поставьте через apt-get он в стандарте... даже через несколько прокси пробросит Ваше соединение. Только надо настроить в /etc/proxychains.cfg так как мне помнится. По порядку укажете путь через толпу прокси. Интересно тем, что как параметр указывается Ваша программа и её ввод-вывод будет работать уже через толпу прокси.
     
    Sanchez5890 нравится это.