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

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

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

Студворк — интернет-сервис помощи студентам
Всех приветствую!
Пытаюсь написать диалоговое приложение на 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 соединение в отдельном потоке, которое получает массив байт с UDP сервера, и затем нужно этот массив...

4
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
05.01.2015, 15:20
Цитата Сообщение от 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  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Используйте 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
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
05.01.2015, 16:37
Цитата Сообщение от 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  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Неизвестно. Ведь исходного кода второго потока нет.
Но в любом случае, бесконечный цикл чтения frame_read - не очень-то хорошая идея.
Так и есть, бесконечный цикл во втором потоке, проверка глобальной переменной
C++
1
2
3
4
5
while(1)
{
if (frame_read ==1)
...
}
Насколько я понял, это не лучший вариант, попробую CreateEvent() прикрутить.

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

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

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

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru