С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/22: Рейтинг темы: голосов - 22, средняя оценка - 4.91
0 / 0 / 0
Регистрация: 05.01.2015
Сообщений: 3
1

UDP видео поток через сокеты, MFC VC++

05.01.2015, 13:42. Показов 4524. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всех приветствую!
Пытаюсь написать диалоговое приложение на MFC, Visual Studio, C++, которое читает UDP пакеты через socket-ы, собирает из этих пакетов видео-кадры, строит bmp-файлы (640х480х8bit, grayscale) и рисует их на экране.
Сделал 2 потока, один для чтения socket-ов, другой для распаковки строки, построения BMP файла и для вывода его на экран, всё работает, но какие-то потери пакетов наблюдаются.
В первом потоке я считываю UDP пакет (строку) с помощью recvfrom (в блокирующем режиме, то есть поток ждет получения пакета), проверяю в пакете, флаг начала кадра, если "true", то считываю еще 479 строк, а по факту получаю не всегда 480, иногда на 10-15 строк меньше.

if ((recv_len = recvfrom(s, (char *)raw_frame[0], BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)

В каждом пакете (L = 1032 byte) одна строка кадра, упакованная (в каждых восьми байтах лежит 5 шт, 12-битных значений), плюс 4 бита флаги - начало кадра, начало строки, начало 8-ми байтового фрагмента в строке.
Не знаю пока как оптимизировать проект, чтобы не терять пакеты. Пока что скорость небольшая, 4 кадра в секунду и те с пропусками проходят.
Поток: 640x480x12x4 = 14.7 Mbit/sec на 100 Mbit канале.
Я сначала сделал всё тоже самое в матлабе, увидел на такой маленькой скорости потерю пакетов, начал переделывать в Visual Studio, и получил почти тоже самое... В чём дело пока не разобрался.
UDP пакеты кидает железка на FPGA, Virtex (ML507). Посылает 480 пакетов по 1032 байта (1 пакет = 1 строка), ждет, 250 ms, повторяет всё заново.

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//Длина  UDP пакета 1032 байта.
//Длина буфера сокета 1032 байта.
 
#define BUFLEN 1032 //Max length of buffer
unsigned char raw_frame[num_lines_of_frame][num_bytes_of_packet] ;// 480x640 кадр 
...
 // функция потока №1 // чтение UDP пакетов, (пакет - строка кадра), поиск начала кадра компоновка строк в кадр.
 
 
  while(1) // potok
 {
 
    // memset(buf,'\0', BUFLEN);
 
    while(1) // поиск старта пакета
    {
     if ((recv_len = recvfrom(s, (char *)raw_frame[0], BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
            {
                                exit(EXIT_FAILURE);
            } //recvfrom -  в блокирующем режиме, поток ждет, прихода пакета
            
            if (( raw_frame[0][0] & mask3) == mask3 )// маска, определяющая начало кадра по флагам в первом байте UDP-пакета  
                 {
                        Line_count = 1; //  // счетчик количества строк
                 break;
                 }
                   
    }
 
        while(1) // сбор пакетов в кадр
        {
            if (Line_count < (num_lines_of_frame )) // пока не получено 480 строк
                    {
             if ((recv_len = recvfrom(s, (char*)raw_frame[Line_count], BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
                            {
                                        exit(EXIT_FAILURE);
                            }
                    Line_count++; // счетчик количества строк
                    }
            else  // получено 480 UDP-пакетов, (480 строк кадра) 
            {
        frame_read = 1; //глобальная переменная, которую в бесконечном цикле проверяет второй поток, прежде чем строить bmp структуру из raw_frame[][]
                        // там же она сбрасывается в "0".  
            break;
            }
        } // end of  Frame  
 
   } // while(1) PotoK
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
05.01.2015, 13:42
Ответы с готовыми решениями:

UDP сокеты
Всем привет. Такой вопрос. Вот у меня есть приложение, которое отправляет используя UDP сокеты...

сокеты udp
Всем доброго времени суток. Написал простенькое приложение на скоетах, все работает, решил...

UDP через отдельный поток и JavaFx
Добрый день, форумчане! Имеется UDP соединение в отдельном потоке, которое получает массив байт с...

Является ли поток через TCP и UDP непрерывным?
Извиняйте меня если этот вопрос глупый, но он мне поможет расставить точки над или, в моем...

4
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
05.01.2015, 15:20 2
Цитата Сообщение от Arkhan Посмотреть сообщение
Не знаю пока как оптимизировать проект, чтобы не терять пакеты.
Используйте TCP и не будете ничего терять.

Цитата Сообщение от Arkhan Посмотреть сообщение
Поток: 640x480x12x4 = 14.7 Mbit/sec на 100 Mbit канале.
Это такие-то ужасы. FullHD = 1920x1080x4bpp = ~8 мегабайт.
И вообще, в таких задачах надо применять сжатие, манипуляции с качеством/глубоной цвета,
отслеживание измененных областей экрана, оптимизация бэкграунда и прочие хитрости.
0
0 / 0 / 0
Регистрация: 05.01.2015
Сообщений: 3
05.01.2015, 16:16  [ТС] 3
Цитата Сообщение от Убежденный Посмотреть сообщение
Используйте TCP и не будете ничего терять.
Спасибо, предполагаю, что до сжатия еще доберусь, в следующих задачах.
TCP тоже интересно, но сейчас хотелось бы понять, проблемы с приёмом UDP пакетов.
В идеале, хочется получить поток порядка 500 Mbit/sec на гигабитном канале.

Я новичок в VC++, пытаюсь понять концепцию построения приложения высокоскоростной передачи данных.
Правильно ли выбран размер буфера сокета, равный размеру UDP пакетов?
Корректно ли, в цикле приёма пакетов, тратить время на поиск начала кадра?
Не влияет ли обработка во втором потоке (преобразования матричные) на цикл первого потока (чтение UDP пакетов)?
Есть ли альтернатива сокетам, и MFC? (попадалась информация про WinPCAP)
Корректно ли через глобальную переменную передавать флаг во второй поток, о заполненности массива raw_frame[][]?
Сколько времени может занимать операция копирования?
C++
1
memcpy(raw_frame, raw_frame_1, 480 * 640);
Стоит ли её ввести в цикл приёма пакетов в первом потоке, а во втором потоке уже работать с копией полученного кадра, чтобы избежать одновременного считывания и записи в этот массив из разных потоков?

Может быть построчно копировать принятый UDP пакет в массив в цикле приёма пакетов?
C++
1
2
3
4
     if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
            {       exit(EXIT_FAILURE);         }
            
    memcpy(raw_frame[0], buf, num_bytes_of_packet);
Спасибо.
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
05.01.2015, 16:37 4
Цитата Сообщение от Arkhan Посмотреть сообщение
TCP тоже интересно, но сейчас хотелось бы понять, проблемы с приёмом UDP пакетов.
Причина проблем с патерей пакетов в UDP лежит в самой природе этого протокола.
Здесь вы ничего не сделаете. Ну разве что не напишете свой протокол поверх UDP,
который будет следить за доставкой данных, их порядком и целостностью.
Но зачем, если это уже есть в TCP ?

Цитата Сообщение от Arkhan Посмотреть сообщение
Правильно ли выбран размер буфера сокета, равный размеру UDP пакетов?
UDP-пакет может иметь размер ~64 килобайта.

Цитата Сообщение от Arkhan Посмотреть сообщение
Корректно ли, в цикле приёма пакетов, тратить время на поиск начала кадра?
А почему бы и нет ?

Цитата Сообщение от Arkhan Посмотреть сообщение
Не влияет ли обработка во втором потоке (преобразования матричные) на цикл первого потока (чтение UDP пакетов)?
Неизвестно. Ведь исходного кода второго потока нет.
Но в любом случае, бесконечный цикл чтения frame_read - не очень-то хорошая идея.

Цитата Сообщение от Arkhan Посмотреть сообщение
Есть ли альтернатива сокетам, и MFC? (попадалась информация про WinPCAP)
Альтернативы всегда есть.
Вместо "ручной" работы с сокетами можно использовать библиотеки,
не только MFC. Лично мне в этом плане больше всего нравится Boost.Asio.
Ну а WinPcap - это инструмент для перехвата, здесь он не нужен.

Цитата Сообщение от Arkhan Посмотреть сообщение
Корректно ли через глобальную переменную передавать флаг во второй поток, о заполненности массива raw_frame[][]?
Корректно. Но не эффективно, если второй поток крутится в цикле.

Цитата Сообщение от Arkhan Посмотреть сообщение
Сколько времени может занимать операция копирования?
Memcpy хорошо оптимизирована. И если речь идет о нескольких мегабайтах
или даже десятках мегабайт в секунду - волноваться точно не стоит.

Цитата Сообщение от Arkhan Посмотреть сообщение
Стоит ли её ввести в цикл приёма пакетов в первом потоке, а во втором потоке уже работать с копией полученного кадра, чтобы избежать одновременного считывания и записи в этот массив из разных потоков?
Устранить одновременный доступ на чтение-запись в массив из разных
потоков стоит в любом случае.

Цитата Сообщение от Arkhan Посмотреть сообщение
Может быть построчно копировать принятый UDP пакет в массив в цикле приёма пакетов?
Это все (включая написанное выше) - "экономия на спичках".
В таких задачах прежде всего следует думать о том, как снизить трафик и
сохранить приемлемый FPS без заметной потери качества картинки и
большой нагрузки на CPU. А уже после заниматься деталями.
0
0 / 0 / 0
Регистрация: 05.01.2015
Сообщений: 3
05.01.2015, 22:40  [ТС] 5
Цитата Сообщение от Убежденный Посмотреть сообщение
Неизвестно. Ведь исходного кода второго потока нет.
Но в любом случае, бесконечный цикл чтения frame_read - не очень-то хорошая идея.
Так и есть, бесконечный цикл во втором потоке, проверка глобальной переменной
C++
1
2
3
4
5
while(1)
{
if (frame_read ==1)
...
}
Насколько я понял, это не лучший вариант, попробую CreateEvent() прикрутить.

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

Добавлено через 1 час 37 минут
Цитата Сообщение от Arkhan Посмотреть сообщение
Насколько я понял, это не лучший вариант, попробую CreateEvent() прикрутить.
Сделал Setevent() и WaitForSingleObject(event,INFINITE) вместо бесконечного цикла ожидания флага глобальной переменной, ошибок стало на порядок меньше!

Спасибо.
0
05.01.2015, 22:40
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.01.2015, 22:40
Помогаю со студенческими работами здесь

Передача видео через сокеты
Подскажите пожалуйста, как передать видео через сокеты. Сейчас имеется код: ...

Передача видео/аудио информации через сокеты
Доброго всем времени суток. Возникло желание научится передавать по сети видео и аудио сигнал. С...

Udp сокеты
Можно ли как-то гарантировано отправить все данные по udp сокетам? Ну или хотя бы с минимальными...

Сокеты TCP и UDP
Здравствуйте. Есть задание: написать программу на любом из языков. Опытные товарищи подсказали, что...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Как проводить научные вычисления на Python
InfoMaster 15.01.2025
Python стал одним из наиболее востребованных языков программирования в области научных вычислений благодаря своей простоте, гибкости и обширной экосистеме специализированных библиотек. Научные. . .
Создание игры типа Minecraft на PyGame/Python: пошаговое руководство
InfoMaster 15.01.2025
В данном руководстве мы рассмотрим процесс создания игры в стиле Minecraft с использованием библиотеки PyGame на языке программирования Python. Этот проект идеально подходит как для начинающих. . .
Как создать свою первую игру в стиле Doom на Unreal Engine
InfoMaster 15.01.2025
Разработка шутера от первого лица в стиле классического Doom представляет собой увлекательное путешествие в мир игрового программирования, где сочетаются творческий подход и технические навыки. . . .
Параллельное программировани­е: основные технологии и принципы
InfoMaster 15.01.2025
Введение в параллельное программирование Параллельное программирование представляет собой фундаментальный подход к разработке программного обеспечения, который позволяет одновременно выполнять. . .
Как написать микросервис на C# с Kafka, MediatR, Redis и GitLab CI/CD
InfoMaster 15.01.2025
В современной разработке программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот подход позволяет разделить сложную систему. . .
Что такое CQRS и как это реализовать на C# с MediatR
InfoMaster 15.01.2025
Концепция CQRS и её роль в современной разработке В современном мире разработки программного обеспечения архитектурные паттерны играют ключевую роль в создании масштабируемых и поддерживаемых. . .
Как настроить CI/CD с Azure DevOps
InfoMaster 15.01.2025
CI/ CD, или непрерывная интеграция и непрерывное развертывание, представляет собой современный подход к разработке программного обеспечения, который позволяет автоматизировать и оптимизировать процесс. . .
Как настроить CI/CD с помощью Jenkins
InfoMaster 15.01.2025
Введение в CI/ CD и Jenkins В современной разработке программного обеспечения непрерывная интеграция (CI) и непрерывная доставка (CD) стали неотъемлемыми элементами процесса создания качественных. . .
Как написать микросервис на Go/Golang с Kafka, REST и GitHub CI/CD
InfoMaster 14.01.2025
Определение микросервиса, преимущества использования Go/ Golang Микросервис – это архитектурный подход к разработке программного обеспечения, при котором приложение состоит из небольших, независимо. . .
Как написать микросервис с нуля на C# с RabbitMQ, CQRS, Swagger и CI/CD
InfoMaster 14.01.2025
В современном мире разработки программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот архитектурный подход предполагает. . .
Как создать интернет-магазин на PHP и JavaScript
InfoMaster 14.01.2025
В современном мире электронная коммерция стала неотъемлемой частью бизнеса. Создание собственного интернет-магазина открывает широкие возможности для предпринимателей, позволяя достичь большей. . .
Как написать Тетрис на Ассемблере
InfoMaster 14.01.2025
Тетрис – одна из самых узнаваемых и популярных компьютерных игр, созданная в 1984 году советским программистом Алексеем Пажитновым. За прошедшие десятилетия она завоевала симпатии миллионы людей по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru