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

ffmpeg работа в несколькими rtsp потоками в одной программе

02.04.2024, 09:25. Показов 7196. Ответов 2

Author24 — интернет-сервис помощи студентам
Добрый день.

Есть простая программа (C++) работы с видео (rtsp поток с нескольких камер).

Я запускаю несколько одинаковых нитей (thread) для работы с разными камерами.
Мьютексами ограничиваю доступ к функциям библиотеки - получения и анализа кадра.

Есть ли возможность внутри библиотеки ffmpeg организовать многопоточную работу с несколькими потоками rtsp видео?

Сбросьте пример пожалуйста (или какие функции посмотреть), направьте в нужную сторону.

Спасибо.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
02.04.2024, 09:25
Ответы с готовыми решениями:

Использование несколькими потоками одной функции
Есть вот такая функция для =которую выполняют рабочие потоки DWORD WINAPI ThreadFunc(void *pV) { Data* pD = (Data*)pV; int n,...

Работа с несколькими потоками
у меня вопрос, к тем кто работает с многопоточными приложениями у меня алгоритм такой: в основном потоке запускаю потоки в цикле ...

Работа с несколькими потоками при обращении к разным textbox
Доброго времени суток, по заданию необходимо чтобы по определенной простой формуле (метод CountBudget) заносилось вычисляемое значение в...

2
 Аватар для Наталья8
483 / 349 / 64
Регистрация: 09.03.2016
Сообщений: 3,470
13.05.2024, 21:41
Я делал такое на opencv. Камеры втыкал в usb.
Материнку поменял и стала работать только одна камера.
Наверное можно таким же образом вставить и ffmpeg.
На ffmpeg я только видеофайлы разбирал.
Нет у меня ни каких камер.

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//   https://web-answers.ru/c/opencv-zapisat-vyvod-veb-kamery-v-fajl-avi.html
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include <iostream>
            #include <string>
              #include <sstream>
#include <time.h>// Вывод системного времяни на кадр
//------------------
#include <vector>
#include <thread>
//------------------
#include <ctime>// Высокоточный отсчёт времяни
#include <ratio>
#include <chrono>
//------------------
#include <windows.h>
#include <conio.h>
 
#include <mmsystem.h>// Звук PlaySound
#pragma comment(lib, "winmm")// Звук
 
using namespace std;
using namespace cv;
using namespace std::chrono;
 
#define AREA_MIN_SIXE 1800
#define AREA_MAX_SIZE 100000000
//---------------
#define KEYDOWN(vk_code)\
    ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) \
    ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
 
char put_time[10];// <---- Вывод на экран часов
 
int trashHold(22), trashHold1(22), trashHold2(22);// < ------------ Чувствительность 22
//bool writeDiff = false;//<----------- Не понял зачем
 
/*=======================================
Программа делает столько потоков, обрабатывающих камеры,
сколько USB камер воткнуто в компьютер.
На каждую камеру пишет отдельный файл на диске <D:>
При обнаруженном движении перед камерой.
======================================= */
void myTrackbarCallback(int pos){
    trashHold = pos;//    Только меняет значение переменной порога intruderAlarm
}
void myTrackbarCallback1(int pos){
    trashHold1 = pos;//    Только меняет значение переменной порога intruderAlarm
}
void myTrackbarCallback2(int pos){
    trashHold2 = pos;//    Только меняет значение переменной порога intruderAlarm
}
//=======================================
//=======================================
void fork(VideoCapture cap, int number){
 
    int _frames = 15;
    //-------------------------------------------------------800/600 - 15 frames
 
    std::string str_num(""); std::stringstream ss; ss << number; str_num = "(" + ss.str() + ")";
    
        std::string name_wind = "MyVideo" + str_num;
                                  namedWindow(name_wind, CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
    double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
    double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
 
    cout << "Camera <" << number << "> Frame Size = " << dWidth << "x" << dHeight << endl;
 
    Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));
            //initialize the VideoWriter object
    VideoWriter oVideoWriter("D:\\" + name_wind + ".avi", CV_FOURCC('D', 'I', 'V', 'X'), _frames, frameSize, true);
    //  ----  Вот эта штука пишет в консоль данные видеопотока (который будет писать)
    if (!oVideoWriter.isOpened()) //if not initialize the VideoWriter successfully, exit the program
    {
        cout << "ERROR: Failed to VideoWriter" << endl;
        Sleep(700); return;
    }
 
 
 
 
 
    // **************************************************   
        
if (old.data)// --- Первый проход мимо... в old нет данных
        {
if (trashHold < 14 && number == 0){ cvSetTrackbarPos("Sensit", name_wind.c_str(), 14); trashHold = 14; }// ================== Движок ограничить
if (trashHold1 < 14 && number == 1){ cvSetTrackbarPos("Sensit", name_wind.c_str(), 14); trashHold1 = 14; }// ================== Движок ограничить       
if (trashHold2 < 14 && number == 2){ cvSetTrackbarPos("Sensit", name_wind.c_str(), 14); trashHold2 = 14; }// ================== Движок ограничить
    
    //============================================================== Конец определения движения
            t2 = high_resolution_clock::now();
            time_span = duration_cast<duration<double>>(t2 - t1);// Отрезки точного времени
            seconde = floor(time_span.count());//Счёт секунд записи     
            //-----------------------------
            if (seconde <= 10)
            {
                cv::Mat out_frame = frame.clone();
            // Переменная put_time ОБЬЯВЛЕНА ГЛОБАЛЬНО... Если здесь... то вешало при выходе из потока
                
                putText(out_frame, put_time, Point(30, 54), 2, 1.6// размер в дублях
                    , Scalar(28, 242, 52), 2); // Толщина int  
                oVideoWriter.write(out_frame); //writer the frame into the file 
                if (seconde == 10){
                    putText(out_frame, " PAUSE", Point(30, 158), 2, 2.6// размер в дублях
                        , Scalar(28, 28, 170), 2);
                } // Толщина int   Audio_playing_time -
                imshow(name_wind, out_frame); //show the frame in "MyVideo" window
            }
            waitKey(30);
            if (one){// ----------- Один раз поставить движок, после вывода картинки
                int currentPosition(22), currentPosition1(22), currentPosition2(22);//---------------------(чувств.)
                if (number == 0)cvCreateTrackbar("Sensit", name_wind.c_str(), &currentPosition, 100, myTrackbarCallback);
                if (number == 1)cvCreateTrackbar("Sensit", name_wind.c_str(), &currentPosition1, 100, myTrackbarCallback1);
                if (number == 2)cvCreateTrackbar("Sensit", name_wind.c_str(), &currentPosition2, 100, myTrackbarCallback2);
                            one = false;
                    }
                }// if (old.data)
if (counter % 3 == 0) old = frame.clone();// в old данные    
    if (KEYDOWN(VK_ESCAPE)){
            cvDestroyWindow(name_wind.c_str());
            break;
             }  //<====================================
             }          }
 
 
//=======================================
//=======================================
int main(int argc, char** argv)
{   
    //-------------------------------------------------------
    HANDLE out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD crd = { 56, 6 }; // <--- Сделаем окошко маленькое
    SMALL_RECT src = { 0, 0, crd.X - 1, crd.Y - 1 };
    SetConsoleWindowInfo(out_handle, true, &src);
    SetConsoleScreenBufferSize(out_handle, crd);
 
    // -------------      Меняем режимы камеры
    CvCapture *capture = cvCreateCameraCapture(0);// Если по дефолту 640/ 480 то 30 фреймов
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 800);// Изменение параметров камеры 1280 - 10 frames
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 600); // (разрешения)               720
    cvSetCaptureProperty(capture, CV_CAP_PROP_SATURATION, 40);
    //  CV_CAP_PROP_BRIGHTNESS
    //  CV_CAP_PROP_CONTRAST
//      capture = nullptr;//< ----------- Сначала nullptr
//  delete capture;// ------------ Потом delete
    
//========================================= 
    std::vector <std::thread> th_vec;
    int n(0);
    while (true){
    VideoCapture cap(n); // open the video camera no. 0
        if (cap.isOpened())  // if not success, exit program
            th_vec.push_back(std::thread(fork, cap, n));// Передача параметров через запятую, после fork 
        else { cout << "ERROR:  camera <"<< n <<"> not found" << endl; break; }// Если камер нет n останеться нулём
                Sleep(2000); ++n;
             }
    // while (1){ if (KEYDOWN(VK_ESCAPE))break; Sleep(50); }
    for (int i = 0; i < n; ++i){// при выходе из нулевого потока, подвешивает по очереди остальные
        th_vec.at(i).join();
            }
    //if(!th_vec.empty())   th_vec.at(0).join();
        Sleep(500);
    return 0;
}
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
4520 / 2408 / 988
Регистрация: 01.06.2021
Сообщений: 8,302
23.07.2024, 12:09
Цитата Сообщение от Наталья8 Посмотреть сообщение
trashHold
threshold звучит лучше
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.07.2024, 12:09
Помогаю со студенческими работами здесь

Чтение из файла, запись в файл и работа с TList несколькими потоками
Есть задача, основная часть работы которой сводится к алгоритму: 1. Прочитать из текстового файла 1, 2 или 4 строки 2. Выделить из...

ffmpeg rtsp, снижение нагрузки на ЦПУ
Разрабатываю приложение, которое будет отображать потоки камер видеонаблюдения на ТВ приставке с андройдом, пробую отображать 12 потоков...

Ffmpeg: потеря пакетов при ретрансляции RTSP
Мне нужно сделать ретрансляцию видео с ip камеры. Решил сделать это на ffmpeg (3.0): ffmpeg -re -i &quot;rtsp://login :...

ffmpeg получить текущий кадр с ip камеры (rtsp поток)
Добрый день. Столкнулся с несколькими проблемами. Надеюсь на вашу мудрость. Я написал код (С++) для работы с камерой (rtsp поток),...

V4l2 ffmpeg Надо как-то загнать rtsp в виртуальную камеру
Добрый день. Я создал виртуальную камеру в /dev/ sudo modprobe v4l2loopback Появилось, соответственно устройство /dev/video1...


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
Списки и кортежи в Python: различия, особенности, применение
py-thonny 13.04.2025
Python славится своей гибкостью при работе с данными. В арсенале языка есть две основные последовательные структуры данных, которые программисты используют ежедневно — списки и кортежи. Эти структуры. . .
Middleware в ASP.NET Core
UnmanagedCoder 13.04.2025
В ASP. NET Core термин "middleware" занимает особое место. Что же это такое? Middleware представляет собой программные компоненты, которые формируют конвейер обработки HTTP-запросов в приложении. . . .
Таблицы лута в Unity с MinMaxCurve и AnimationCurve
GameUnited 12.04.2025
Создание сбалансированного лута в играх — задача не из простых. Разработчики постоянно ищут способы настройки систем выпадения предметов, которые будут одновременно справедливыми для игроков и. . .
std::expected в C++: Управление ошибками
bytestream 12.04.2025
Обработка ошибок всегда была важной и одновременно сложной задачей в программировании на C++. На протяжении долгого времени разработчики использовали различные подходы: возвращаемые коды ошибок,. . .
Nullable типы и операторы объединения null в C#
UnmanagedCoder 12.04.2025
Многие шутят, что null — это миллиардная ошибка в программировании. И в этой шутке только доля шутки. Тони Хоар, создатель null-ссылки, сам назвал её своей "ошибкой на миллиард долларов". Почему?. . .
Аутентификация и авторизация JWT в микросервисах с API Gateway
stackOverflow 12.04.2025
В традиционных монолитных приложениях безопасность часто реализуется как единый защитный периметр - пользователь проходит аутентификацию один раз, после чего получает доступ ко всем функциям системы. . . .
TypeScript: Интерфейсы vs Типы
run.dev 11.04.2025
Современная разработка на JavaScript сталкивается с множеством проблем при масштабировании проектов. Типизация кода стала хорошим инструментом, помогающим избежать ошибок во время выполнения,. . .
Управление топиками и разделами Kafka
Javaican 11.04.2025
Apache Kafka — распределенная платформа потоковой передачи данных, которая стала стандартом для построения высоконагруженных систем обмена сообщениями. В современной архитектуре микросервисов,. . .
Миграция монолита в Event-Driven микросервисную архитектуру на C#
stackOverflow 11.04.2025
Монолитная архитектура – классический подход к разработке программного обеспечения. Это приложение, построенное как единое целое, где все компоненты тесно связаны между собой. Большинство проектов. . .
Go в Kubernetes: Управление ресурсами
golander 11.04.2025
Разработчики Go-приложений в Kubernetes часто сталкиваются с неожиданными проблемами производительности и даже внезапными отказами контейнеров. Причина этого кроется в особенностях взаимодействия. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер