Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103

Синхронизация потоков

04.04.2016, 11:29. Показов 5408. Ответов 39
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть класс

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
class CFrameBufferObserver
 : public VsCoreLib::IFrameBufferObserver
{
  VsCoreLib::IFrameBuffer* m_frame_buffer;
public:
  explicit CFrameBufferObserver(VsCoreLib::IFrameBuffer* frame_buffer)
    : m_frame_buffer(frame_buffer)
  {
  }
 
public:   
  virtual void __stdcall NewFrame(unsigned int frameNumber)
  {
    if (VsCoreLib::IFrame* frame = m_frame_buffer->GetNextFrame()) {   
      LONG w, h, bps;
      frame->GetDimensions(&w, &h, &bps); 
      const char* p_buf = frame->GetFrameBuffer(); 
 
          char * buf = new char[453960];
          for (int i = 0; i < 907920; i++)
          {
           if (i%2==true)
                buf[i/2]=p_buf[i];
          }
 
          HBITMAP bitmap = CreateCompatibleBitmap(Form1->Image1->Canvas->Handle, w, h);
          SetDIBits(Form1->Image1->Canvas->Handle, bitmap, 0, h, buf, info, DIB_RGB_COLORS);
 
          Form1->Image1->Picture->Bitmap->Handle = bitmap;
 
          delete buf;
          delete p_buf;
 
      frame->SetFree();
    }
  }
};
Так же создан поток

C++
1
2
3
4
5
6
7
8
class VideoThread : public TThread
{
private:
protected:
        void __fastcall Execute();
public:
        __fastcall VideoThread(bool CreateSuspended);
};
В методе Execute происходит вызов функции NewFrame из класса CFrameBufferObserver.
Но как видно из функции NewFrame - она работает с основным потоком.

Как в данном случае правильно использовать метод Synchronize?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.04.2016, 11:29
Ответы с готовыми решениями:

Синхронизация потоков
В общем проблема состоит в том, что у меня не получается синхронизировать потоки. Предисловие: есть класс Parsing, созданный мной, а...

Синхронизация потоков: семафоры
Всем доброго времени суток. Друзья есть простое приложение которое выводит 2 последовательности: #include &lt;iostream.h&gt; #include...

Синхронизация потоков. Семафоры
Приветствую. Как синхронизировать 3 потока относительно одного? т.е. когда работает один поток - три другие ждут. Когда...

39
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
05.04.2016, 15:31  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Avazart Посмотреть сообщение
Через метод Syncronize() класса потока
Как использовать этот метод в описании другого класса?
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
05.04.2016, 15:58
Цитата Сообщение от slovnosvoboda Посмотреть сообщение
Как использовать этот метод в описании другого класса?
Никак.
0
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
05.04.2016, 16:07  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Никак.
В общем создал в потоке 2 новых метода:

C++
1
2
3
4
5
6
7
8
9
void __fastcall VideoThread::synfunc()
{
Synchronize(func);
}
 
void __fastcall VideoThread::func()
{
Form1->Image1->Picture->Bitmap->Handle = bitmap;
}
А в описании класса использую:

C++
1
VideoThread::synfunc;
Но изображение не отрисовывается. Что делаю не так?
0
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
05.04.2016, 16:20
Цитата Сообщение от slovnosvoboda Посмотреть сообщение
Synchronize(&func);
а так?
0
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
05.04.2016, 16:23  [ТС]
Цитата Сообщение от Selot Посмотреть сообщение
а так?
Всё равно не отрисовывается..
0
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
05.04.2016, 16:27
ну. код кидай снова)
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
05.04.2016, 16:27
Цитата Сообщение от slovnosvoboda Посмотреть сообщение
Но изображение не отрисовывается. Что делаю не так?
А нам откуда знать код так не весь приведен, очевидно что делаете то и получаете.
0
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
06.04.2016, 07:25  [ТС]
Selot, Avazart,
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
//---------------------------------------------------------------------------
#include <Windows.h>
#include "InterfacesCore\IEnvironment.h"
#include "InterfacesCore\Identificator.h"
#include <iostream>
#include <tchar.h>
#include <vcl.h>
#pragma hdrstop
 
#include "Unit2.h"
#include "Unit1.h"
 
#pragma package(smart_init)
 
int startend;
 
BITMAPINFO* info;
 
int r[256]=
        {
        0, 0, 4, 4, 8, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48,
        48, 52, 52, 52, 56, 60, 60, 64, 68, 72, 72, 76, 76, 76, 80, 84, 84, 88,
        88, 96, 92, 88, 88, 84, 84, 84, 80, 80, 76, 72, 68, 68, 64, 64, 60, 60,
        56, 56, 52, 52, 48, 44, 40, 40, 36, 36, 36, 32, 32, 28, 24, 24, 20, 16,
        16, 12, 8, 8, 8, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 4, 8, 16, 20, 28, 28, 32, 40, 44, 52, 56, 68, 76, 80, 84,
        92, 92, 96, 104, 108, 116, 120, 132, 140, 144, 152, 156, 156, 164, 168,
        172, 180, 184, 196, 204, 208, 216, 220, 220, 228, 232, 240, 244, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 252, 252
        };
 
int g[256]=
        {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 20, 24, 32, 36, 36, 40, 48, 52,
        60, 64, 76, 80, 84, 92, 96, 96, 104, 108, 112, 120, 124, 136, 140, 144,
        152, 156, 156, 164, 168, 172, 180, 184, 196, 200, 208, 212, 216, 216,
        224, 228, 232, 240, 244, 244, 240, 232, 228, 220, 220, 216, 208, 204,
        196, 192, 180, 172, 168, 164, 156, 156, 152, 144, 140, 132, 128, 116,
        108, 104, 96, 92, 92, 84, 80, 76, 68, 64, 52, 44, 40, 32, 28, 28, 20, 16,
        8, 4, 0, 4, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 56, 60, 64, 68,
        72, 72, 76, 80, 84, 88, 92, 100, 104, 108, 112, 116, 116, 120, 124, 128,
        132, 136, 144, 148, 152, 156, 160, 160, 164, 168, 172, 176, 180, 188,
        192, 196, 200, 204, 204, 208, 212, 216, 220, 224, 232, 236, 240, 244,
        248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
        248, 248, 248, 248, 248, 248, 248, 248, 252, 252
        };
 
int b[256]=
        {
        0, 0, 4, 4, 8, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48,
        48, 52, 52, 52, 56, 60, 60, 64, 68, 72, 72, 76, 76, 76, 80, 84, 84, 88, 88,
        96, 96, 100, 104, 108, 108, 112, 116, 120, 124, 128, 136, 140, 144, 144,
        148, 148, 152, 156, 160, 164, 168, 176, 180, 184, 188, 192, 192, 196, 196,
        200, 204, 208, 216, 220, 224, 228, 232, 232, 236, 240, 244, 248, 248, 240,
        232, 228, 224, 216, 212, 212, 208, 200, 196, 188, 184, 172, 168, 164, 156,
        152, 152, 144, 140, 136, 128, 124, 112, 108, 104, 96, 92, 92, 84, 80, 76,
        68, 64, 52, 48, 40, 36, 32, 32, 24, 20, 16, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 32,
        44, 56, 80, 88, 100, 112, 124, 124, 136, 148, 160, 168, 180, 204, 216, 228,
        240, 248, 248
        };
 
char* p_buf;
char * buf;
HBITMAP bitmap;
//---------------------------------------------------------------------------
 
__fastcall VideoThread::VideoThread(bool CreateSuspended)
        : TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
 
typedef VsCoreLib::IEnvironment* (*GetEnvInstanceProc)(void);
 
class CFrameBufferObserver
  : public VsCoreLib::IFrameBufferObserver
{
  VsCoreLib::IFrameBuffer* m_frame_buffer;
public:
  explicit CFrameBufferObserver(VsCoreLib::IFrameBuffer* frame_buffer)
    : m_frame_buffer(frame_buffer)
  {
  }
 
public:   // функция обратого вызова, вызывается из библиотеки при получении нового кадра.
  virtual void __stdcall NewFrame(unsigned int frameNumber)
  {
  if (VsCoreLib::IFrame* frame = m_frame_buffer->GetNextFrame()) {   // GetNextFrame() - функция получения указателя на кадр
  LONG w, h, bps;
      frame->GetDimensions(&w, &h, &bps); // получение данных о кадре: размер и кол. бит/пиксель
      p_buf = (char *)frame->GetFrameBuffer();  // p_buf - указатель на блок памяти с данными
      // здесь вставляется обработка полученных видеоданных:
 
        buf = new char[453960];
          for (int i = 0; i < 907920; i++)
           if (i%2==true)
             buf[i/2]=p_buf[i];
 
           HBITMAP bitmap = CreateCompatibleBitmap(Form1->Image1->Canvas->Handle, 780, 582);
 
          SetDIBits(Form1->Image1->Canvas->Handle, bitmap, 0, 582, buf, info, DIB_RGB_COLORS);
 
        VideoThread::synfunc;
 
        //Form1->Image1->Picture->Bitmap->Handle = bitmap;
        
        delete buf;
        delete p_buf;
        frame->SetFree();
    }
  }
};
 
void __fastcall VideoThread::synfunc()
{
Synchronize(func);
}
 
void __fastcall VideoThread::func()
{
Form1->Image1->Picture->Bitmap->Handle = bitmap;
}
 
void __fastcall VideoThread::Execute()
{
startend=0;
HMODULE dll_module = ::LoadLibrary("vscorelib_v4.dll"); // Загрузка DLL в адресное пространство процесса
  if ( 1 ) {
    GetEnvInstanceProc proc =  (GetEnvInstanceProc)::GetProcAddress(dll_module,"GetEnvironment"); // попучение указателя на экспортируемую из DLL функцию по имени GetEnvironment
    if (1) {
      VsCoreLib::IEnvironment* i_env = proc(); // вызов фунции GetEnvironment и получение указателя на "окружение" камеры.
      VsCoreLib::IPairIterator* devices = i_env->GetDevicePrototypes();  // получение списка устройств IPairIterator
      devices->Reset();// приведение IPairIterator в начало списка устройств
      if (!devices->End()) {            // если какое-либо устройство есть, мы берем первое
        VsCoreLib::IPair * tmp = devices->GetCurrent(); // получаем дескриптор первого устройства из списка
        VsCoreLib::IDeviceCreator* creator = i_env->GetDeviceCreator(tmp); // получаем указатель на "фабрику" устройств
        if (creator )   // если "фабрика" найдена, то создаем устройство
        {
            VsCoreLib::IDevice* device = creator->Create();// создаем устройство
            device->Open();
            device->Run();
 
            VsCoreLib::ISettingIterator* settings = device->GetSettings(); // получаем набор параметров камеры
            for (settings->Reset(); !settings->End(); settings->Next())  // если устройств несколько - то выполняется цикл
                VsCoreLib::ISetting* setting = settings->GetCurrent();
 
                VsCoreLib::ISetting* period = device->GetSetting(SID_PERIOD); // кадровый период
                period->ScalarObj()->SetValue(StrToInt(Form1->Edit1->Text)); // устанавливаем значение
 
                VsCoreLib::ISetting* gain = device->GetSetting(SID_GAIN); // Аналоговое усиление
                                if (Form1->ComboBox1->Text=="0 дБ")
                gain->EnumObj()->SetValueID(ERID_0dB); // устанавливаем значение 0 дБ
 
                                if (Form1->ComboBox1->Text=="6 дБ")
                gain->EnumObj()->SetValueID(ERID_6dB); // устанавливаем значение 6 дБ
 
                                if (Form1->ComboBox1->Text=="12 дБ")
                gain->EnumObj()->SetValueID(ERID_12dB); // устанавливаем значение 12 дБ
 
                                if (Form1->ComboBox1->Text=="18 дБ")
                gain->EnumObj()->SetValueID(ERID_18dB); // устанавливаем значение 18 дБ
 
            settings->Free();   // освободить итератор параметров камеры
 
            VsCoreLib::IFrameBuffer* frame_buffer = device->GetFrameBuffer(); // получение указателя на очередь кадров (очередь - несколько кадров, находящиеся в памяти)
            CFrameBufferObserver frame_buffer_observer(frame_buffer); // регистрация "слушателя" события "новый кадр"
            frame_buffer->RegisterObserver(&frame_buffer_observer);
 
                        Form1->Button1->Enabled = false;
                        Form1->Button2->Enabled = true;
 
                        info = (LPBITMAPINFO) malloc(sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
 
                        for (int i = 0; i < 256; i++) // 256 что бы убрать полосность при засвете
                        {
                        info->bmiColors[i].rgbRed = (byte)r[i];
                        info->bmiColors[i].rgbGreen = (byte)g[i];
                        info->bmiColors[i].rgbBlue = (byte)b[i];
                        info->bmiColors[i].rgbReserved = 0;
                        }
 
                        info->bmiHeader.biSize = sizeof(info->bmiHeader);
                        info->bmiHeader.biWidth = 780;
                        info->bmiHeader.biHeight = -582;
                        info->bmiHeader.biPlanes = 1;
                        info->bmiHeader.biBitCount = 8;
                        info->bmiHeader.biCompression = 0;
                        info->bmiHeader.biSizeImage = 0;
                        info->bmiHeader.biClrUsed = 0;
                        info->bmiHeader.biClrImportant = 1;
 
                        while (run!=0) // зацикливаем вывод кадров
                        {
                        Sleep(1); // время за которое выведется некоторое количество кадров
                        Application->ProcessMessages();
                        }
 
                        free (info);
 
            frame_buffer->UnregisterObserver(&frame_buffer_observer);  // дерегистация "слушателя" события "новый кадр"
            device->Stop();
            device->Close();
        }
      }
           else
           {
                Form1->Memo1->Clear();
                Form1->Memo1->Lines->Add("Камера не подключена");
           }
 
      devices->Free();// освободить итератор на дескрипторы устройств
    }
 
    ::FreeLibrary(dll_module);  // конец работы
        startend = 1;
        Form1->Button1->Enabled = true;
        Form1->Button2->Enabled = false;
  }
}
//---------------------------------------------------------------------------
0
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
06.04.2016, 09:57
bitmap объявлена в коде 2 раза. 77 и 112 строки. в 112 объявляешь локальную переменную bitmap, ее видно только в пределах функции newframe, ты в нее как раз и записываешь. А функция func берет глобальный bitmap из строки 77, а он пустой.
Попробуй для начала из 112 строки убрать HBITMAP
0
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
06.04.2016, 10:18  [ТС]
Цитата Сообщение от Selot Посмотреть сообщение
bitmap объявлена в коде 2 раза. 77 и 112 строки. в 112 объявляешь локальную переменную bitmap, ее видно только в пределах функции newframe, ты в нее как раз и записываешь. А функция func берет глобальный bitmap из строки 77, а он пустой.
Попробуй для начала из 112 строки убрать HBITMAP
Я тоже это заметил, но всё равно не помогло.
Мне кажется, что проблема в строке:
C++
1
VideoThread::synfunc;
Можно ли так вызывать метод потока в описании класса CFrameBufferObserver? Если да, то почему метод не выполняется?
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.04.2016, 11:45
Теперь слишком дофига кода .
Сделай более простой тестовый пример без длл и левых классов.

Добавлено через 1 минуту
Цитата Сообщение от slovnosvoboda Посмотреть сообщение
Можно ли так вызывать метод потока в описании класса CFrameBufferObserver? Если да, то почему метод не выполняется?
Блин еще раз- нет и не нужно пытаться это делать.
0
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
06.04.2016, 12:05  [ТС]
Avazart,
В общем вычитал, что объекты Canvas могут использоваться вне Synchronize метода, необходимо только блокировать их перед применением и освобождать после, для этого используются методы Lock() и Unlock().
Это частично помогло. Осталось только как-то синхронизировать работу с основным потоком этой строчки:
C++
1
Form1->Image1->Picture->Bitmap->Handle = bitmap;
1
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.04.2016, 12:48
Цитата Сообщение от slovnosvoboda Посмотреть сообщение
В общем вычитал, что объекты Canvas могут использоваться вне Synchronize метода, необходимо только блокировать их перед применением и освобождать после, для этого используются методы Lock() и Unlock().
Естественно, но это не касается битмапа и его хендла.

Добавлено через 38 минут
C++
1
Form1->Image1->Picture->Bitmap->Handle = bitmap;
Это вообще работает без потоков?
0
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
06.04.2016, 12:50
А что если в классе CFrameBufferObserver сделать паблик-очередь std::queue<HBITMAP> queueHandle; в нее пихать хэндлы queueHandle.enqueue(bitmap); затем слать сообщение форме из потока PostMessageA(Form1->Handle, WM_UPDATE_BITMAP, NULL, NULL);, на форме ловить сообщение, лезть в очередь и извлекать свеженький хендл Image1->Picture->Bitmap->Handle = queueHandle.dequeue(); queueHandle.pop(); ?
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.04.2016, 12:53

Не по теме:

Вот лишь бы пихать ...


Еще раз говорю учите матчать.
0
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
06.04.2016, 16:13  [ТС]
Решил обойтись без потока, но история та же..

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
//---------------------------------------------------------------------------
#include <Windows.h>
#include "InterfacesCore\IEnvironment.h"
#include "InterfacesCore\Identificator.h"
#include <iostream>
#include <tchar.h>
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
 
TForm1 *Form1;
char* p_buf;
char * buf;
HBITMAP bitmap;
BITMAPINFO* info;
 
//---------------------------------------------------------------------------
 
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
 
typedef VsCoreLib::IEnvironment* (*GetEnvInstanceProc)(void);
 
class CFrameBufferObserver
  : public VsCoreLib::IFrameBufferObserver
{
  VsCoreLib::IFrameBuffer* m_frame_buffer;
public:
  explicit CFrameBufferObserver(VsCoreLib::IFrameBuffer* frame_buffer)
    : m_frame_buffer(frame_buffer)
  {
  }
 
public:   // функция обратого вызова, вызывается из библиотеки при получении нового кадра.
  virtual void __stdcall NewFrame(unsigned int frameNumber)
  {
  if (VsCoreLib::IFrame* frame = m_frame_buffer->GetNextFrame()) {   // GetNextFrame() - функция получения указателя на кадр
  LONG w, h, bps;
      frame->GetDimensions(&w, &h, &bps); // получение данных о кадре: размер и кол. бит/пиксель
      p_buf = (char *)frame->GetFrameBuffer();  // p_buf - указатель на блок памяти с данными
      // здесь вставляется обработка полученных видеоданных:
 
        buf = new char[453960];
        for (int i = 0; i < 907920; i++)
           if (i%2==true)
                buf[i/2]=p_buf[i];
 
        HBITMAP bitmap = CreateCompatibleBitmap(Form1->Image1->Canvas->Handle, 780, 582);
        SetDIBits(Form1->Image1->Canvas->Handle, bitmap, 0, 582, buf, info, DIB_RGB_COLORS);
        Form1->Image1->Picture->Bitmap->Handle = bitmap;
 
        delete buf;
        delete p_buf;
        frame->SetFree();
    }
  }
};
 
//---------------------------------------------------------------------------
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HMODULE dll_module = ::LoadLibrary("vscorelib_v4.dll"); // Загрузка DLL в адресное пространство процесса
  if ( 1 ) {
    GetEnvInstanceProc proc =  (GetEnvInstanceProc)::GetProcAddress(dll_module,"GetEnvironment"); // попучение указателя на экспортируемую из DLL функцию по имени GetEnvironment
    if (1) {
      VsCoreLib::IEnvironment* i_env = proc(); // вызов фунции GetEnvironment и получение указателя на "окружение" камеры.
      VsCoreLib::IPairIterator* devices = i_env->GetDevicePrototypes();  // получение списка устройств IPairIterator
      devices->Reset();// приведение IPairIterator в начало списка устройств
      if (!devices->End()) { // если какое-либо устройство есть, мы берем первое
        VsCoreLib::IPair * tmp = devices->GetCurrent(); // получаем дескриптор первого устройства из списка
        VsCoreLib::IDeviceCreator* creator = i_env->GetDeviceCreator(tmp); // получаем указатель на "фабрику" устройств
        if (creator )   // если "фабрика" найдена, то создаем устройство
        {
            VsCoreLib::IDevice* device = creator->Create();// создаем устройство
            device->Open();
            device->Run();
 
            VsCoreLib::ISettingIterator* settings = device->GetSettings(); // получаем набор параметров камеры
            for (settings->Reset(); !settings->End(); settings->Next())  // если устройств несколько - то выполняется цикл
                VsCoreLib::ISetting* setting = settings->GetCurrent();
 
                VsCoreLib::ISetting* period = device->GetSetting(SID_PERIOD); // кадровый период
                period->ScalarObj()->SetValue(30); // устанавливаем значение
 
                VsCoreLib::ISetting* gain = device->GetSetting(SID_GAIN); // Аналоговое усиление
                gain->EnumObj()->SetValueID(ERID_18dB); // устанавливаем значение 18 дБ
 
            settings->Free();   // освободить итератор параметров камеры
 
            VsCoreLib::IFrameBuffer* frame_buffer = device->GetFrameBuffer(); // получение указателя на очередь кадров (очередь - несколько кадров, находящиеся в памяти)
            CFrameBufferObserver frame_buffer_observer(frame_buffer); // регистрация "слушателя" события "новый кадр"
            frame_buffer->RegisterObserver(&frame_buffer_observer);
 
            info = (LPBITMAPINFO) malloc(sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
 
            for (int i = 0; i < 256; i++) // 256 что бы убрать полосность при засвете
            {
            info->bmiColors[i].rgbRed = (byte)i;
            info->bmiColors[i].rgbGreen = (byte)i;
            info->bmiColors[i].rgbBlue = (byte)i;
            info->bmiColors[i].rgbReserved = 0;
            }
 
            info->bmiHeader.biSize = sizeof(info->bmiHeader);
            info->bmiHeader.biWidth = 780;
            info->bmiHeader.biHeight = -582;
            info->bmiHeader.biPlanes = 1;
            info->bmiHeader.biBitCount = 8;
            info->bmiHeader.biCompression = 0;
            info->bmiHeader.biSizeImage = 0;
            info->bmiHeader.biClrUsed = 0;
            info->bmiHeader.biClrImportant = 1;
 
            while (true)
            {
            Sleep(1);
            Application->ProcessMessages();
            }
 
            free (info);
 
            frame_buffer->UnregisterObserver(&frame_buffer_observer);  // дерегистация "слушателя" события "новый кадр"
            device->Stop();
            device->Close();
        }
      }
      devices->Free();// освободить итератор на дескрипторы устройств
    }
    ::FreeLibrary(dll_module);  // конец работы
  }        
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
for (int i=0; i<10000; i++)
{
Label1->Caption=IntToStr(i);
Application->ProcessMessages();
}
}
//---------------------------------------------------------------------------
Добавлено через 3 часа 9 минут
Суть в том, что по нажатию кнопки происходит ожидание получения нового кадра, которое выполнено в виде бесконечного цикла. А получение нового кадра осуществляется с помощью метода класса CFrameBufferObserver.
Если же выполнять ещё какие-либо действия на основной форме - появляется ошибка, поскольку цикл не был закончен.
Заканчивать цикл ожидания получения нового кадра, после этого совершать какие-либо действия, а потом запускать цикл вновь - такой вариант не подходит, поскольку до начала выполнения цикла выполняются ещё некоторые действия, которые занимают значительное время.

Как лучше поступить?
0
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
06.04.2016, 17:40
Сначала отладить рисование картинки без всяких доп.потоков и лишних действий. Потом вечный цикл вынести в отдельный поток, вместе с классом CFrameBufferObserver. Сделать чтоб этот класс возвращал в поток "HBITMAP bitmap" и из потока вызывать Synchronize. Вроде логично
1
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.04.2016, 19:20
C++
1
2
3
4
buf = new char[453960];
        for (int i = 0; i < 907920; i++)
           if (i%2==true)
                buf[i/2]=p_buf[i];
Вероятно стоит копировать сразу в TBitmap то есть как то так
C++
1
Form1->Image1->Picture->Bitmap->Canvas->Pixel[x][y]] =  p_buf[i];
Ясное дело что битмап надо подогнать и синхронизировать если есть поток.

Кстати код УГ там явные утечки и глупости типа
C++
1
2
3
4
5
6
p_buf = (char *)frame->GetFrameBuffer();
//...
buf = new char[453960];
// ...
delete buf;
delete p_buf;
1
9 / 9 / 5
Регистрация: 21.09.2015
Сообщений: 103
07.04.2016, 11:55  [ТС]
Цитата Сообщение от Selot Посмотреть сообщение
Сделать чтоб этот класс возвращал в поток "HBITMAP bitmap
Как это сделать?

Цитата Сообщение от Avazart Посмотреть сообщение
Кстати код УГ там явные утечки и глупости типа
Пиксел представлен 12-ти разрядным числом, кот. сдвинутое влево на 4, т.е. 4 младших бита равны 0. Мне посоветовали брать старший байт из буфера, т.е. привести char* к short* и применить макрос HIBYTE, но используя данный способ, у меня изображение не получалось, поэтому и пришлось городить подобную ерунду с целью, чтобы "хоть как-то работало"..

Добавлено через 58 минут
В общем получилось обойтись без класса CFrameBufferObserver. Теперь проблем нет.
Selot, Avazart, благодарю за ответы!
0
0 / 0 / 1
Регистрация: 15.02.2013
Сообщений: 27
04.01.2017, 19:24
в потоке обсчитывал bitmap, анализировал яркость в цикле.
проблема была в том, что без потоков всё ок, а в потоке, в процессе выполнения (рандомно от раза к разу) битмап становился пустым.
помогла вставка
C++
1
2
3
Image->Canvas->Lock();
// цикл обращений к Canvas
Image->Canvas->Unlock();
мб будет полезно

Не по теме:

таким *** как я

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.01.2017, 19:24

Синхронизация потоков. Мьютексы
Не могу никак разобраться, почему не работает синхронизация с помощью мьютекса. Создаю мьютекс hMutex =...

Класс Thread, потоки синхронизация потоков и т.д
Имеется код: Модуль Unit1.cpp (в нем запускается поток) //------------------------------------------------------ //... ...

Синхронизация потоков с++
Реализовать модуль создающий 4 балансировочных потока обеспечивающий 100% загрузку CPU (A,B,C,D). Каждый поток должен выводить на консоль...

Мьютекс и синхронизация
Разбираюсь с мьютексами и синхронизацией приложений. Создал редактор.В нем есть диалог печати если запущены несколько копий редактора и в...

Синхронизация мюьтекса
Помогите разобратся почему не выполняется условие во втором Timer2? Принцип работы приложения такой: запускаем первое начинают работать...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу))) Критические ошибки, мешающие компиляции и. . .
сукцессия 16. Общий обзор, в основном что бы другие ии поняли
anaschu 29.06.2026
# Передаточный документ: модель микоризной сукцессии (для нового чата) Этот документ предназначен для того, чтобы новый чат Claude мог продолжить работу без необходимости заново разбираться в. . .
сукцессия 15 неявная схема
anaschu 29.06.2026
Алиса Калибровка параметров симбиотической модели: технический обзор Содержание: Введение Постановка проблемы Технические аспекты реализации Процесс внедрения изменений
сукцессия 14. Обновленная схема модели
anaschu 28.06.2026
ГЛОБАЛЬНАЯ ОПИСАТЕЛЬНАЯ СПЕЦИФИКАЦИЯ ЭКОСИСТЕМНОЙ МОДЕЛИ «SOIL CHEMISTRY & MYCORRHIZA 2. 0» https:/ / ibb. co/ NnkGpfMd Представленная интегрированная схема описывает непрерывную нелинейную. . .
сукцессия 13. Питон модель трехзонного мицелия, пока что в основном арбускулярного
anaschu 28.06.2026
## Разработка агентной модели микоризной сукцессии: от выявления артефактов к созданию комплексной системы ### Аннотация Представлено исследование по разработке агентной модели микоризной. . .
сукцессия 12. краткий список проверок модели перед запуском.
anaschu 27.06.2026
Скрытые отказы в моделях систем динамики (SD-models) экологических систем: два случая из практики Контекст Разбирался прототип модели систем динамики (SD-модели) микоризной сукцессии: пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru