powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Проблема с DSPACK при использовании TSampleGrabber
9 сообщений из 9, страница 1 из 1
Проблема с DSPACK при использовании TSampleGrabber
    #39844845
LeoAm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, коллеги!

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

Использую компоненты DSPACK234
В их поставке есть демо пример PlayVideoCap - получение видеопотока с камеры и покадровая обработка с событии OnBuffer. Он работает без проблем. Я несколько видоизменил его, добавив изменение получаемого битмапа. Программа перестает работать с ошибкой "Неверный дескриптор"

Ниже привожу фрагмент кода.

Код: pascal
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.
procedure TVideoForm.SampleGrabberBuffer(sender: TObject;
  SampleTime: Double; pBuffer: Pointer; BufferLen: Integer);
var
r: TRect;
begin
  if CallBack.Checked then
  begin

    //Image.Canvas.Lock;
    try
      SampleGrabber.GetBitmap(bmp , pBuffer, BufferLen);

      //Image.Picture.Assign(bmp);

      try
        BmpPreview.Width := 1000;
        BmpPreview.Height := 1000;

        r.Left := 0;
        r.Top := 0;
        r.Right := 1000;
        r.Bottom := 1000;

        BmpPreview.Canvas.StretchDraw(r, bmp);

        Image.Picture.Assign(BmpPreview);
      except
        on e: Exception do
          Caption := e.Message;
      end;

    finally
      //Image.Canvas.Unlock;
    end;
  end;
end;



Если раскоментировать строку //Image.Picture.Assign(bmp); и закоментировать блок try ... except все работает без проблем

Подскажите в чем моя ошибка, которая приводит к тому, что портится дескриптор BmpPreview.Handle.
Заранее благодарен.

Исходники проекта прилагаю. Если нужен комплект DSPACK тоже могу приложить
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39844850
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeoAm, выложи код TSampleGrabber.GetBitmap();
Сдается мне, он не делает копию, а просто юзает буфер в качестве источника. А буфер в DS - сущность временная, ее грохнули и вуаля.

Вообще, много лишний действий.
Просто создай битмап, эквивалентный грабу, и копируй в него буфер при получении.
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39844896
LeoAm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Соколинский Борис,
Спасибо за отзыв. Ниже код функции GetBitmap и функции где происходит генерация событии о получении нового буфера от DS.

Код: pascal
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.
function TSampleGrabber.GetBitmap(Bitmap: TBitmap; Buffer: Pointer; BufferLen: Integer): Boolean;
  var
    hr: HRESULT;
    BIHeaderPtr: PBitmapInfoHeader;
    MediaType: TAMMediaType;
    BitmapHandle: HBitmap;
    DIBPtr: Pointer;
    DIBSize: LongInt;
  begin
    Result := False;
    if not Assigned(Bitmap) then
      Exit;
    if Assigned(Buffer) and (BufferLen = 0) then
      Exit;
    hr := SampleGrabber.GetConnectedMediaType(MediaType);
    if hr <> S_OK then
      Exit;
    try
      if IsEqualGUID(MediaType.majortype, MEDIATYPE_Video) then
      begin
        BIHeaderPtr := Nil;
        if IsEqualGUID(MediaType.formattype, FORMAT_VideoInfo) then
        begin
          if MediaType.cbFormat = SizeOf(TVideoInfoHeader) then  // check size
            BIHeaderPtr := @(PVideoInfoHeader(MediaType.pbFormat)^.bmiHeader);
        end
        else if IsEqualGUID(MediaType.formattype, FORMAT_VideoInfo2) then
        begin
          if MediaType.cbFormat = SizeOf(TVideoInfoHeader2) then  // check size
            BIHeaderPtr := @(PVideoInfoHeader2(MediaType.pbFormat)^.bmiHeader);
        end;
        // check, whether format is supported by TSampleGrabber
        if not Assigned(BIHeaderPtr) then
          Exit;
        BitmapHandle := CreateDIBSection(0, PBitmapInfo(BIHeaderPtr)^,
                                         DIB_RGB_COLORS, DIBPtr, 0, 0);
        if BitmapHandle <> 0 then
        begin
          try
            if DIBPtr = Nil then
              Exit;
            // get DIB size
            DIBSize := BIHeaderPtr^.biSizeImage;
            if DIBSize = 0 then
            begin
              with BIHeaderPtr^ do
                DIBSize := GetDIBLineSize(biBitCount, biWidth) * biHeight * biPlanes;
            end;
            // copy DIB
            if not Assigned(Buffer) then
            begin
              // get buffer size
              BufferLen := 0;
              hr := SampleGrabber.GetCurrentBuffer(BufferLen, Nil);
              if (hr <> S_OK) or (BufferLen <= 0) then
                Exit;
              // copy buffer to DIB
              if BufferLen > DIBSize then  // copy Min(BufferLen, DIBSize)
                BufferLen := DIBSize;
              hr := SampleGrabber.GetCurrentBuffer(BufferLen, DIBPtr);
              if hr <> S_OK then
                Exit;
            end
            else
            begin
              if BufferLen > DIBSize then  // copy Min(BufferLen, DIBSize)
                BufferLen := DIBSize;
              Move(Buffer^, DIBPtr^, BufferLen);
            end;
            Bitmap.Handle := BitmapHandle;
            Result := True;
          finally
            if Bitmap.Handle <> BitmapHandle then  // preserve for any changes in Graphics.pas
              DeleteObject(BitmapHandle);
          end;
        end;
      end;
    finally
      FreeMediaType(@MediaType);
    end;
  end;

function TSampleGrabber.BufferCB(SampleTime: Double; pBuffer: PByte;
    BufferLen: Integer): HResult;
  begin
    if assigned(FOnBuffer) then
    begin
      FCriticalSection.Enter;
      try
        FOnBuffer(self, SampleTime, pBuffer, BufferLen);
      finally
        FCriticalSection.Leave;
      end;
    end;
    result := S_OK;
  end;



Относительно временности буфера - возможно, но как я понимаю функция BufferCB сделана так, что пока обработка внутри неё не пройдёт, новое событие FOnBuffer не сработает. В оригинальном примере внутри обработки я ставил sleep более секунды и это не приводило к краху.
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39844915
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeoAm
Код: pascal
1.
2.
        BitmapHandle := CreateDIBSection(0, PBitmapInfo(BIHeaderPtr)^,
                                         DIB_RGB_COLORS, DIBPtr, 0, 0);



Так я и предполагал, функция просто делает обертку для переданного буфера. Дальше код можно не смотреть - это попытка защита от какой-то очень экзотической кривизны.

LeoAmОтносительно временности буфера - возможно, но как я понимаю функция BufferCB сделана так, что пока обработка внутри неё не пройдёт, новое событие FOnBuffer не сработает. Так и есть.
Внутри функции буфер валидный, и битмап, соответственно, тоже. А какой он будет в момент отрисовки и прочих операций заранее неизвестно. В твоем случае известно - его уже грохнули, потому приходит пушной зверек.

Можно поменять схему на примерно такую:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
  if ФорматБуфераНеПоменялся then begin
    Move(pBuffer^, pMyPersistantBuffer^, bufferlen);
    Image.Invalidate;
  end
  else begin
     //Создаем pMyPersistantBuffer и его передаем на вход процедуре
  end;


и это как-то будет работать.
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39845109
LeoAm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Соколинский Борис,

Хотелось бы уточнить, что значит авторфункция просто делает обертку для переданного буфера

Как я понимаю CreateDIBSection создаёт в памяти объект и выделяет под него память, в которую собственно и копируется передаваемый в параметре GetBitmap буфер:

Код: pascal
1.
Move(Buffer^, DIBPtr^, BufferLen);



Относительного временного буфера: Вы имеете в виду необходимость копировать в него исходный буфер от DS и потом уже передача локального буфера в качестве параметра GetBitmap?
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39845123
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeoAmКак я понимаю CreateDIBSection создаёт в памяти объект и выделяет под него память Ошибаетесь.
Буфер используется тот, что передан на вход, копий не делается.

LeoAmОтносительного временного буфера: Вы имеете в виду необходимость копировать в него исходный буфер от DS и потом уже передача локального буфера в качестве параметра GetBitmap? Да.
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39845160
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeoAmВы имеете в виду необходимость копировать в него исходный буфер от DS и потом уже передача локального буфера в качестве параметра GetBitmap? Причем GetBitmap не нужно делать каждый раз (см. мой код).
Важное уточнение:
Для выделения буфера используйте только виндовый менеджер памяти (GlobalAllocPtr(GPTR, size)), иначе на больших изображениях будет черное поле.
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39845190
LeoAm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Соколинский Борис,

Спасибо за разъяснение.

С буфером понятно, а вот что касается
авторПричем GetBitmap не нужно делать каждый раз что это значит?

Событие SampleGrabberBuffer по сути это очередной кадр, соответственно pBuffer будет содержать всегда разные данные. Почему не нужно каждый раз вызывать GetBitmap?
...
Рейтинг: 0 / 0
Проблема с DSPACK при использовании TSampleGrabber
    #39845200
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeoAm,
Присвоение handle для TBitmap - достаточно медленная операция. Там приходится парсить содержимое и т.д.
Если один раз уже создали, достаточно просто содержимое буфера обновлять.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Проблема с DSPACK при использовании TSampleGrabber
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]