SR2D и веб-камера (VB6). Удалось!

Работа с 2D и 3D графикой, видео, звуком.

Модератор: Mikle

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 27.07.2025 (Вс) 16:33

С.Т. писал(а):1 - это просто обязательный параметр nResrv, который может быть любым и ни на что не влияет.
Влияет единица при ОТКРЫТИИ камеры: OpenCapDev(1) - открытие в другом потоке асинхронно и вывод кадров по событию (но в VB падает при закрытии камеры), а OpenCapDev(0) - синхронное открытие без создания потока, кадры снимаются только через SnapOne(любое_число).
Этот OCX во всех моих вложениях в этой теме (например, в первом посте).

Ваш проект скачал, огромное спасибо, сейчас изучу...

Как раз он влияет на формат вывода. В твоём случае на выходе BMP картинка в формате MEDIASUBTYPE_RGB24:

Код: Выделить всё
Option Explicit

Private Type BITMAPINFO
    biSize          As Long
    biWidth         As Long
    biHeight        As Long
    biPlanes        As Integer
    biBitCount      As Integer
    biCompression   As Long
    biSizeImage     As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed       As Long
    biClrImportant  As Long
End Type

Private Declare Function SetDIBitsToDevice Lib "gdi32" ( _
                         ByVal hdc As Long, _
                         ByVal x As Long, _
                         ByVal y As Long, _
                         ByVal dx As Long, _
                         ByVal dy As Long, _
                         ByVal SrcX As Long, _
                         ByVal SrcY As Long, _
                         ByVal Scan As Long, _
                         ByVal NumScans As Long, _
                         ByRef Bits As Any, _
                         ByRef BitsInfo As BITMAPINFO, _
                         ByVal wUsage As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef pSrc As Any, _
                         ByRef pDst As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
                    Alias "RtlMoveMemory" ( _
                    ByRef Destination As Any, _
                    ByRef Source As Any, _
                    ByVal Length As Long)
                         
Private Sub Form_Load()

    TesoSeeu1.OpenCapDev 0, 0

End Sub

Private Sub Timer1_Timer()
    Dim p As Long, o As Long
    Dim b As BITMAPINFO
   
    p = TesoSeeu1.SnapOne(1)
   
    CopyMemory b, ByVal p + 14, Len(b)
    GetMem4 ByVal p + 10, o

    SetDIBitsToDevice Me.hdc, 0, 0, b.biWidth, b.biHeight, 0, 0, 0, b.biHeight, ByVal p + o, b, 0
   
End Sub


По факту этот контрол просто обертка над Sample Grabber фильтром из DirectShow.
UA6527P

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 27.07.2025 (Вс) 16:34

С.Т. писал(а):1 - это просто обязательный параметр nResrv, который может быть любым и ни на что не влияет.
Влияет единица при ОТКРЫТИИ камеры: OpenCapDev(1) - открытие в другом потоке асинхронно и вывод кадров по событию (но в VB падает при закрытии камеры), а OpenCapDev(0) - синхронное открытие без создания потока, кадры снимаются только через SnapOne(любое_число).
Этот OCX во всех моих вложениях в этой теме (например, в первом посте).

Ваш проект скачал, огромное спасибо, сейчас изучу...

Как раз он влияет на формат вывода. В твоём случае на выходе BMP картинка в формате MEDIASUBTYPE_RGB24:

Код: Выделить всё
Option Explicit

Private Type BITMAPINFO
    biSize          As Long
    biWidth         As Long
    biHeight        As Long
    biPlanes        As Integer
    biBitCount      As Integer
    biCompression   As Long
    biSizeImage     As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed       As Long
    biClrImportant  As Long
End Type

Private Declare Function SetDIBitsToDevice Lib "gdi32" ( _
                         ByVal hdc As Long, _
                         ByVal x As Long, _
                         ByVal y As Long, _
                         ByVal dx As Long, _
                         ByVal dy As Long, _
                         ByVal SrcX As Long, _
                         ByVal SrcY As Long, _
                         ByVal Scan As Long, _
                         ByVal NumScans As Long, _
                         ByRef Bits As Any, _
                         ByRef BitsInfo As BITMAPINFO, _
                         ByVal wUsage As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef pSrc As Any, _
                         ByRef pDst As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
                    Alias "RtlMoveMemory" ( _
                    ByRef Destination As Any, _
                    ByRef Source As Any, _
                    ByVal Length As Long)
                         
Private Sub Form_Load()

    TesoSeeu1.OpenCapDev 0, 0

End Sub

Private Sub Timer1_Timer()
    Dim p As Long, o As Long
    Dim b As BITMAPINFO
   
    p = TesoSeeu1.SnapOne(1)
   
    CopyMemory b, ByVal p + 14, Len(b)
    GetMem4 ByVal p + 10, o

    SetDIBitsToDevice Me.hdc, 0, 0, b.biWidth, b.biHeight, 0, 0, 0, b.biHeight, ByVal p + o, b, 0
   
End Sub


По факту этот контрол просто обертка над Sample Grabber фильтром из DirectShow.
UA6527P

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 27.07.2025 (Вс) 16:35

С.Т. писал(а):SetDIBitsToDevice

Ну используй SetDiBits тогда если куда-то в промежуточный буфер нужно, либо банальный CopyMemory.
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 28.07.2025 (Пн) 0:54

Ча-во? Так просто?! СПАСИБИЩЕ! Это чудо!!! Сейчас попробую вложить этот кадр в ARGB спрайта...

А с указателем - Во я дурило, не сообразил: просто заранее создаю буфер и указатель на него, и передаю этот указатель в новый поток, в него-то и вписываем там кадры, а из нашего потока читаем. Простой пример работает как ожидалось. Теперь в ActiveX Multi НЕТ задержек в поставке материала из другого потока, это проверяется кнопкой "Заморозить форму":
У вас нет доступа для просмотра вложений в этом сообщении.

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 28.07.2025 (Пн) 1:13

А вот передача кадров камеры (заранее увеличенных, что тоже занимает время) в другой поток штатным способом ActiveX, но БЕЗ ЗАДЕРЖКИ потоков, по общему указателю. Основной поток можно искусственно задерживать флажком "Циклическая задержка формы" и указать величину задержки; кадры продолжают поставляться, не ожидая завершения основного потока:
(Съём кадров пока по-старому, завтра постараюсь упростить)
У вас нет доступа для просмотра вложений в этом сообщении.

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 28.07.2025 (Пн) 1:49

Поправил первый пример (в главном потоке CopyMemory вообще не нужна, общая переменная сама обновится, когда готова):
У вас нет доступа для просмотра вложений в этом сообщении.

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 28.07.2025 (Пн) 12:28

Вчерашние сообщения здесь не отобразились, копирую их сюда:

The Trick 27.07.2025 (Вс) 16:33 писал(а):Как раз он влияет на формат вывода. В твоём случае на выходе BMP картинка в формате MEDIASUBTYPE_RGB24:
Код: Выделить всё
Option Explicit

Private Type BITMAPINFO
    biSize          As Long
    biWidth         As Long
    biHeight        As Long
    biPlanes        As Integer
    biBitCount      As Integer
    biCompression   As Long
    biSizeImage     As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed       As Long
    biClrImportant  As Long
End Type

Private Declare Function SetDIBitsToDevice Lib "gdi32" ( _
                         ByVal hdc As Long, _
                         ByVal x As Long, _
                         ByVal y As Long, _
                         ByVal dx As Long, _
                         ByVal dy As Long, _
                         ByVal SrcX As Long, _
                         ByVal SrcY As Long, _
                         ByVal Scan As Long, _
                         ByVal NumScans As Long, _
                         ByRef Bits As Any, _
                         ByRef BitsInfo As BITMAPINFO, _
                         ByVal wUsage As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef pSrc As Any, _
                         ByRef pDst As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
                    Alias "RtlMoveMemory" ( _
                    ByRef Destination As Any, _
                    ByRef Source As Any, _
                    ByVal Length As Long)
                         
Private Sub Form_Load()

    TesoSeeu1.OpenCapDev 0, 0

End Sub

Private Sub Timer1_Timer()
    Dim p As Long, o As Long
    Dim b As BITMAPINFO
   
    p = TesoSeeu1.SnapOne(1)
   
    CopyMemory b, ByVal p + 14, Len(b)
    GetMem4 ByVal p + 10, o

    SetDIBitsToDevice Me.hdc, 0, 0, b.biWidth, b.biHeight, 0, 0, 0, b.biHeight, ByVal p + o, b, 0
   
End Sub



По факту этот контрол просто обертка над Sample Grabber фильтром из DirectShow.


The Trick писал(а):
С.Т. писал(а):SetDIBitsToDevice


Ну используй SetDiBits тогда если куда-то в промежуточный буфер нужно, либо банальный CopyMemory.


С.Т. 28.07.2025 (Пн) 0:54 писал(а):Ча-во? Так просто?! СПАСИБИЩЕ! Это чудо!!! Сейчас попробую вложить этот кадр в ARGB спрайта...

А с указателем - Во я дурило, не сообразил: просто заранее создаю буфер и указатель на него, и передаю этот указатель в новый поток, в него-то и вписываем там кадры, а из нашего потока читаем. Простой пример работает как ожидалось. Теперь в ActiveX Multi НЕТ задержек в поставке материала из другого потока, это проверяется кнопкой "Заморозить форму":
ВЛОЖЕНИЯ
1) Один побочный поток - по указателю БЕЗ ЗАМОРОЗКИ.zip
(17.37 Кб) Скачиваний: 0

А вот передача кадров камеры (заранее увеличенных, что тоже занимает время) в другой поток штатным способом ActiveX, но БЕЗ ЗАДЕРЖКИ потоков, по общему указателю. Основной поток можно искусственно задерживать флажком "Циклическая задержка формы" и указать величину задержки; кадры продолжают поставляться, не ожидая завершения основного потока:
ВЛОЖЕНИЯ
5) Веб-камера, увеличение, по указателю.zip
(74.21 Кб) Скачиваний: 0
(там злосчастная процедура НовыйКадр, тормозившая поток, должна быть удалена вовсе, она не используется: кадр обновляется в обоих потоках одновременно, хоть формально это и противоречит политике ActiveX.)



А сейчас я поправил первый простой пример и вообще убрал CopyMemory и сделал структуру Действительно Глобальных переменных, которые можно читать и писать в любом потоке в штатном режиме ActiveX EXE Multi без вызова методов и, как следствие, БЕЗ задержки потоков. Для этого использован несложный трюк подмены указателя от Хакера.
Программировать стало гораздо удобнее, не думаешь о переносе материала вообще, и по быстродействию чуть-чуть лучше прошлой версии: одномерный массив успевает обновиться по всем потокам примерно 1600 раз в секунду, а по CopyMemory без общей структуры было 1500 раз. Вывод: обращение из потоков к UDT в необъявленном GlobalMultiUse-классе происходит БЫСТРО, и нужно отдать предпочтение именно такому подходу.

Прилагаю именно такой пример (см, вложение), где можно менять мерность общего массива от огромной (с обработкой во втором потоке и выдачей результата примерно раз в секунду) до нулевой (мгновенная выдача результата в главный поток) и следить за изменением поведения.

При Мерности = 0 и обновлении формы по Циклу (это всё указывается прямо на форме) второй поток успевает выдать примерно 1600 обновлений в секунду (на моём компе), просто увеличивая число и "передавая" его в главный поток (хотя момента передачи не существует, массив обновляется одновременно для всех потоков).

Если же увеличивать Мерность, нагрузка на второй поток возрастает, но он продолжает работать и передавать результаты в главный поток и продолжать работать, даже когда главный поток занят (это проверяется кнопкой "Заморозить форму" - числа продолжают увеличиваться, хоть в это время и не отображаются).

Этот пример работает без нареканий; вопрос: может ли он иметь при определённых конфигурациях подводные камни?
У вас нет доступа для просмотра вложений в этом сообщении.

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 28.07.2025 (Пн) 20:12

А зачем ExitProcess? Извини, но от оформления кода у меня болят глаза, что отступы что имена переменных.
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 28.07.2025 (Пн) 21:42

ExitProcess - для закрытия сразу всех потоков, созданных по CreateObject. Иначе они останутся, с невидимыми формами, для убийства в Диспетчере.
Имена - гораздо лучше понимаю код по-русски, однако могу всё перевести по Ctrl+H.
Отступы - объявления и рутинные команды откидываю вправо, чтобы не отвлекали от сути алгоритма (привычка за 20 лет). Тоже буду стандартизировать впредь, прошу прощения.
Но суть: ведь все говорят, что ActiveX Multi нецелесообразна, т.к. ждёт при межпоточных вызовах, а оказывается (помимо того что на практике это не мешает) хитрый указатель обходит эту неловкость с ожиданиями и к тому же делает нужные переменные сверхглобальными, что очень удобно, а их обновление - мгновенным, независимо от объёма. Не слишком ли прост наивный обход? Но ведь работает и не глючит.

Я не для себя спрашиваю. А для сообщества: не ещё один ли это подход к многопоточности?
(Продолжил над этим работу ещё и из-за Bass.dll, который довольно ненадёжен в vb6, плохо уживается с многопоточными контролами и с modMultiThreading.Initialize, а по ActiveX с разведением на потоки всё хорошо дружит и просто так ещё не слетало.)
Последний раз редактировалось С.Т. 28.07.2025 (Пн) 22:00, всего редактировалось 3 раз(а).

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 28.07.2025 (Пн) 21:48

Ещё раз благодарю за кадры с камеры! Долго думал, как перевести из RGB-24 в ARGB-32, сделал по-простому:
Код: Выделить всё
'Красивый алгоритм съёма кадра предложил The Trick:
    pSnap = Cam.SnapOne(1&)  'При SnapOne(1) - BMP  MEDIASUBTYPE_RGB24
    If Cam.GetImgLen(1) = 0 Then Exit Sub
    CopyMemory BitMapInfo, ByVal pSnap + 14, 40 '40 - это Len(BitMapInfo)
    GetMem4 ByVal pSnap + 10, o
'Дальше мой произвол - использую контрол Picture1 как посредника для перевода кадра в формат ARGB: 
    SetDIBits Me.hDC, Picture1.Image.Handle, 0, BitMapInfo.biHeight, ByVal pSnap + o, BitMapInfo, 0
    sprCam.LoadFromIPicture Picture1.Image, Picture1.hDC 'там GetDiBits в новый формат
'Спрайт кадра готов!

Такой код работает в 10 раз быстрее прежнего (проверил таймером) и не использует ссылок.

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 29.07.2025 (Вт) 0:05

С.Т. писал(а):ExitProcess - для закрытия сразу всех потоков, созданных по CreateObject. Иначе они останутся, с невидимыми формами, для убийства в Диспетчере.

Не, так не стоит делать. Нужно убивать все экземпляры объектов в главном потоке.

С.Т. писал(а):Но суть: ведь все говорят, что ActiveX Multi нецелесообразна, т.к. ждёт при межпоточных вызовах, а оказывается (помимо того что на практике это не мешает) хитрый указатель обходит эту неловкость с ожиданиями и к тому же делает нужные переменные сверхглобальными, что очень удобно, а их обновление - мгновенным, независимо от объёма. Не слишком ли прост наивный обход? Но ведь работает и не глючит.

Да нет. Она на самом дела ждет в межпоточных вызовах если их делать, а если не делать - то не ждет. В твоем примере ты используешь общую память через указатель, а межпоточных вызовов почти нет. С одной стороны - это опасно, т.к. если главный поток очистит общую переменную - то в другом потоке будет AV. Но если ты следишь за этим - то все будет нормально. Я не люблю AxEXE из-за требования установки (с REG-Free манифестом они не работают), для меня проще AxDLL использовать которая не требует установки в этом случае (если нужна отладка в IDE).

С.Т. писал(а):Продолжил над этим работу ещё и из-за Bass.dll, который довольно ненадёжен в vb6, плохо уживается с многопоточными контролами и с modMultiThreading.Initialize

Ну скинь пример, я уверен там просто ошибка, а модуль никак не влияет.

С.Т. писал(а):Ещё раз благодарю за кадры с камеры! Долго думал, как перевести из RGB-24 в ARGB-32, сделал по-простому:

Пожалуйста. А преобразовывать так не стоит. Нужно создать DIB секцию с нужным форматом 32bpp - она даст указатель на пиксели, в нее уже делать SetDiBits из 24bpp изображения камеры и сразу получать пиксели в нужном формате. Альфы там не будет т.к. GDI игнорит ее почти всегда.
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 29.07.2025 (Вт) 18:13

The trick писал(а): Нужно убивать все экземпляры объектов в главном потоке.

Да, конечно, сделал так:
Код: Выделить всё
If Not ThreadClass Is Nothing Then
    SharedUDT.DoLoop = False
    Unload ThreadF
    Set ThreadClass = Nothing
    End
End If

Работает. Закрывается чисто и в IDE, и в EXE, в диспетчере не висит. Благодарствую!

За анализ AX Multi по указателю спасибо! Придало уверенности. Просто моя программа всё равно будет требовать установки, там уйма зависимостей. К тому же, на виндах левых сборок часто нет msvbvm60.dll, сталкиваюсь постоянно, так что установка всё равно нужна.

Ну скинь пример, я уверен там просто ошибка, а модуль никак не влияет.

Ну, в таком стерильном примере всё гораздо лучше. Достаточно запустить СНАЧАЛА MultiThreading, а потом тотчас же запустить BASS, и всё будет в порядке. Но если запустить сначала BASS, а потом Threading, при закрытии слёт. Если запустить сначала Threading, а потом НЕ СРАЗУ, а из него по Form_Resize запустить BASS, тоже слёт при закрытии. Но это ещё хорошо. В моём основном проекте всё гораздо сложнее, и вариантов слёта гораздо больше. В том числе в середине программы, например при закрытии камеры (работающей ведь в другом потоке) или смены миди-устройства. И уж тем более - неожиданное отсоединение камеры или миди-устройства - всё это, несмотря на алгоритмические проверки, аппаратно приводит к аварийному слёту, а без потоков или по ActiveX, кажется, было заметно надёжнее. Впрочем, точных исследований проблемы еще не проводил.

Прилагаю стерильный проект, где Threading и Bass никак не связаны, а просто запускается исходная форма Ваша - и исходный тестовый пример BASS от его создателей. Ни в одном проекте я не менял ни одной буквы. Там варианты EXE со слётом и без:
У вас нет доступа для просмотра вложений в этом сообщении.
Последний раз редактировалось С.Т. 30.07.2025 (Ср) 14:58, всего редактировалось 3 раз(а).

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 29.07.2025 (Вт) 22:58

Дорогой The Trick! А всё-таки Вы правы насчёт ActiveX Exe. Проверил сейчас на разных компьютерах (без VB). ActiveX Exe вызывает подозрения у антивирусов. "Изменение реестра", "создание СОМ-компонента", видите ли, не нравится... Только из-под установщика, и на тебе. Установщик - Actual Installer, вроде популярный и как следствие подозрений у них не вызывает (хотя установщик-то тоже в реестр лазил, но ему можно!).
А Standard EXE устанавливается и запускается без проблем и без срабатываний. Хотя голый запуск (без установки) всякий раз вызывает истерику "Создание процесса!" у поганого 360 Total Security, а он о-оочень распространённый, хоть сам вирус ещё тот. Но установщику он доверяет и тогда помалкивает.

Кстати!!! Благодаря Вашему коду съёма кадра нашлась причина слётов при асинхронном открытии камеры! Это действительно было из-за памяти!
Последний раз редактировалось С.Т. 30.07.2025 (Ср) 0:39, всего редактировалось 2 раз(а).

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 30.07.2025 (Ср) 0:28

С.Т. писал(а):
The trick писал(а):Прилагаю стерильный проект, где Threading и Bass никак не связаны, а просто запускается исходная форма Ваша - и исходный тестовый пример BASS от его создателей. Ни в одном проекте я не менял ни одной буквы. Там варианты EXE со слётом и без:

Короче глянул я проект. Это проблема bass.dll - она сама там меняет (причем неправильно) внутренние структуры рантайма. Видимо разработчики как-то хотели сделать чтобы bass.dll делала колбеки в VB6 код из других потоков, но сделали это очень криво. Суть в том что потокоспецифичные данные рантайма хранятся в TLS и у каждого потока они свои. Что делает bass.dll - берет эти данные из главного потока и тупо копирует во все потоки - возникают конфликты при многопоточном коде. Сам понимаешь когда рантайм ожидает для каждого потока увидеть свои данные, а ему подсовывают от главного - будет беда. Тут так и происходит. Когда первым загружается мой модуль - он правильно инициализирует потокоспецифичные данные рантайма т.к. там по умолчанию 0. После выгрузки потока - данные только для данного потока уничтожаются. Когда первым загружается bass.dll - он тупо копирует из главного потока в TLS данные и мой модуль когда пытается инициализировать потокоспецифичные данные видит что там уже есть данные и думает что инициализация уже была. Это вызывает конфликт. В любом случае работа bass.dll вызывает некорректную работу рантайма, так что тут я могу посоветовать только не использовать кривую либу, либо запатчить то место где происходит модификация внутренних структур в рантайме.
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 30.07.2025 (Ср) 1:03

Ух ты!!! Ну Вы волшебник!
Да, Bass присылает коллбеки при воспроизведении миди (а воспроизведение - ясное дело - другой поток). Но как это можно было увидеть?.. (понимаю, что есть декомпиляторы и пр., но не до такой же степени! Магия!)
Но интересно, что когда Bass загружаешь последним, но не тут же, а по Form_Resize, он опять начинает слетать. Более того: если через большой период времени - опять НЕ слетает!

Ну, а если просто Bass загружать сразу после modMultiThreading (и следить при выгрузке как-то таймером я делал, чтобы не одновременно, вроде не слетало), это может быть выходом, или всё равно кривой это выход? (Bass менять не вариант, там всё на нём)

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 30.07.2025 (Ср) 10:07

С.Т. писал(а):Ух ты!!! Ну Вы волшебник!
Да, Bass присылает коллбеки при воспроизведении миди (а воспроизведение - ясное дело - другой поток). Но как это можно было увидеть?.. (понимаю, что есть декомпиляторы и пр., но не до такой же степени! Магия!)

Это все легко смотрится в отладчике типа OllyDbg.

С.Т. писал(а):Но интересно, что когда Bass загружаешь последним, но не тут же, а по Form_Resize, он опять начинает слетать. Более того: если через большой период времени - опять НЕ слетает!

Ну, а если просто Bass загружать сразу после modMultiThreading (и следить при выгрузке как-то таймером я делал, чтобы не одновременно, вроде не слетало), это может быть выходом, или всё равно кривой это выход? (Bass менять не вариант, там всё на нём)

Ну я бы вообще не использовал bass, т.к. все тоже самое можно на WINAPI сделать, т.к. он в любом случае ломает внутренние структуры рантайма. Обойти можно пропатчив саму bass.dll так:
Код: Выделить всё
Private Declare Function WriteProcessMemory Lib "kernel32" ( _
                         ByVal hProcess As Long, _
                         ByVal lpBaseAddress As Long, _
                         ByRef lpBuffer As Any, _
                         ByVal nSize As Long, _
                         ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long


. . .

    Call BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10) ' 10ms update period
   
    ' // Patch
    WriteProcessMemory -1, GetModuleHandle(StrPtr("bass")) + &H1F13, &HC3, 1, 0
   
    ' initialize default output device (and measure latency)
    If (BASS_Init(-1, 44100, BASS_DEVICE_LATENCY, 0, 0) = 0) Then
        Call Error_("Can't initialize output device")
        End
    End If

. . .
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 30.07.2025 (Ср) 14:54

Ни-че-гошеньки себе!!!
Вот это преспасибище!
Работает!!!
Нет, Вы всё-таки великий человек.

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 31.07.2025 (Чт) 16:37

А насчёт асинхронного открытия камеры опять рано обрадовался. В тот раз всё работало хорошо, а теперь слетает при закрытии камер, даже если ничего с ними не делать. Там всё же сильный глюк в TesoSeeu.ocx применительно к потокам vb6. Работать с камерой - только по SnapOne и со своей многопоточностью.

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 31.07.2025 (Чт) 16:39

С.Т. писал(а):А насчёт асинхронного открытия камеры опять рано обрадовался. В тот раз всё работало хорошо, а теперь слетает при закрытии камер, даже если ничего с ними не делать. Там всё же сильный глюк в TesoSeeu.ocx применительно к потокам vb6. Работать с камерой - только по SnapOne и со своей многопоточностью.

Как делаешь?
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 31.07.2025 (Чт) 16:57

Теоретически, правомерен и такой проект, с собственной многопоточностью TesoSeeu.ocx, т.е. без нужды в CreateThread'ах вообще, но работает он через день, а на другой день начинает слетать при закрытии камеры (что только ни делал, вплоть до того что комментил весь код преобразования кадра и его рендера, оставлял пустышку - и даже она порой слетает):
У вас нет доступа для просмотра вложений в этом сообщении.

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 31.07.2025 (Чт) 17:05

Да, так и есть. (По-видимому, остановлюсь на vbCreateThread с Вашим патчем Bass'a!.) Вот проект в несколько строк: открыть - закрыть. Как только открываем с параметром 1, т.е. с приёмом событий, на второй или третий раз слетает (а в иные дни нормально открывает-закрывает хоть сто раз), CloseCapDev 0 - те же слёты, но в другие разы:
У вас нет доступа для просмотра вложений в этом сообщении.

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 31.07.2025 (Чт) 19:31

У меня не вылетает.
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 31.07.2025 (Чт) 22:27

А... я имел в виду - слетает, когда жмешь то "Открыть", то "Закрыть" несколько раз (даже не подряд, а с паузами). Хотя иные дни и у меня не слетает, я даже на радостях вписываю это в программу... а назавтра всё рушится, включая и пустышку. А с открытием как 0 (без Events) ни разу не слетало без причины.

The trick
Постоялец
Постоялец
 
Сообщения: 804
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 31.07.2025 (Чт) 22:32

С.Т. писал(а):А... я имел в виду - слетает, когда жмешь то "Открыть", то "Закрыть" несколько раз (даже не подряд, а с паузами). Хотя иные дни и у меня не слетает, я даже на радостях вписываю это в программу... а назавтра всё рушится, включая и пустышку. А с открытием как 0 (без Events) ни разу не слетало без причины.

Да как я только не пытался - ничего не падает.
UA6527P

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 01.08.2025 (Пт) 11:43

Странно… Основательно перепроверю (с перезагрузками и т.д.)
Но увеличение/обработка спрайта желательна в другом потоке, иначе всё равно ступенчатое движение. Так что всё актуально.

Сделал всё по-новому, на основе AsyncDraw.
Да, когда передаёшь структуру в vbCreateThread параметром, там в этой структуре может быть даже и объект класса (SR2D спрайт), и он не бьёт электросваркой и не падает, и не нужно никакого "экранирования" ключом от одновременного доступа (как было в прямом обращении из другого потока к глобальному объекту класса, что разумеется недопустимо).

Второй вариант - поместить в общих данных не класс, а указатель на массив картинки в этом классе. Это опаснее для программиста, но вроде как правильнее с точки зрения потоков? Или можно законно помещать объект класса в структуру, передаваемую в lpParameter потока?

В обоих вариантах видно, как кадры обновляются сверху вниз, т.е. на экран новый кадр переносится моментально, даже наполовину сделанный:

(Спрайт принимает массив в формате исключительно в формате ARGB, наличие альфы необходимо, поэтому перевожу через Picture1)
У вас нет доступа для просмотра вложений в этом сообщении.
Последний раз редактировалось С.Т. 05.08.2025 (Вт) 12:58, всего редактировалось 2 раз(а).

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 01.08.2025 (Пт) 12:58

А с OpenCapDev(0, 1) и EventOfCamera - не могу выявить закономерности. Иногда хоть весь день смыкай - всё работает,а иногда с первого-второго CloseCapDev'a виснет даже без кода (так что алгоритмическая ошибка исключена). Ну его. Ваш движок многопоточности показывает себя куда как более надёжным... чем эти китайцы.Тем более что преобразования кадра всё равно лучше делать в отдельном потоке. Вам - от всей души - необъятное Спасибо!

P.S. Вот тут видно, что даже если бы нормально закрывался, то увеличение кадра на весь экран в общем потоке всё равно вызывает задержку рендеринга, да и виснет так гораздо чаще:
У вас нет доступа для просмотра вложений в этом сообщении.

С.Т.
Новичок
Новичок
 
Сообщения: 45
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 09.08.2025 (Сб) 15:17

The trick писал(а):Ну я бы вообще не использовал bass, т.к. все тоже самое можно на WINAPI сделать, т.к. он в любом случае ломает внутренние структуры рантайма. Обойти можно пропатчив саму bass.dll так:

The Trick, представляете, вопрос таки актуален! Bass.dll с подключённой миди-клавиатурой иногда рушит программу в произвольные моменты времени. Даже голый сам по себе (безо всяких потоков). Это я заметил ещё много лет назад, но списывал на несовершенство своих алгоритмов. Ан нет! В разных программах он падает одинаково. Не по нажатию клавиши, не по воспроизведению, а ПРОСТО ТАК. Вдруг. Может никогда, а может через минуту.

Патч "WriteProcessMemory -1, GetModuleHandle(StrPtr("bass")) + &H1F13, &HC3, 1, 0" приводит к вылету при первой же нажатой миди-клавише (уже на стадии ReDim буфера клавишной команды), так что проблема Bass'a гораздо глубже.

По этой причине мне пришлось сделать отдельный ПРОЦЕСС для Басса, а главный процесс следит и при вылете перезапускает, убивая окно ошибки. Такой тандем работает. Но в момент падения сбрасываются все звучащие ноты, да и вообще это слишком грубая латка.

Я не нашёл другой библиотеки, способной загрузить SoundFont (*.SF2), воспроизводить её сэмплы и реагировать на нажатия миди-клавиатуры, а также воспроизводить MP3 в режиме сэмплирования (т.е. загрузить один раз и включать многократно с наложениями). Может, Вы знаете такой движок?

Давно подключал OCX MidiIn и MidiOut от Marby, они тоже слетали при неясных обстоятельствах. Хотя ничего потенциально опасного я не делал (ни потоков, ни CopyMemory).

Разрабатывать всё это с нуля на API... включая имена подключённых Миди-устройств, их корректное открытие-закрытие, сэмплирование MP3-данных... не с моими знаниями, да и где гарантия, что не произойдёт того же самого - случайных слётов. Хотя, я думаю, они просто не разобрались со спецификой многопоточности в VB6. У нас ТЕПЕРЬ, с появлением Ваших открытий, такой проблемы нет, так что движок можно в принципе и разработать заново. Но может, есть более-менее готовые модули для MIDI-сэмплирования?

Или, может, одеть Bass в ActiveX DLL, или в OCX, или ещё как-то, там он может вести себя иначе, не взламывая рантайм? Или во всех случаях структуры рантайма в принципе одинаковы?

Пред.

Вернуться в Мультимедиа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

    TopList  
cron