Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2012.05.20;
Скачать: [xml.tar.bz2];

Вниз

Передача видео и звука с помощью Indy   Найти похожие ветки 

 
3asys ©   (2012-01-05 11:57) [160]

> DVM ©
Спасибо Большое

> Во первых ты должен где то сообщить подсистеме аудио как
> трактовать данные которые ты ей подсовываешь, т.е указать
> какая частота дискретизации у тебя, сколько каналов, сколько
> разрядов и т.д. После проинициализировать систему. Потом
> уже начинать подсовывать ей куски аудиоданных. Только тогда
> она сможет их воспроизводить.

В этом проблема, поскольку со звуком раньше никогда не работал, то как правильно предоставить данные и проинициализировать систему - не представляю, а в том что нашел по воспроизведению этого не увидел.
Может быть есть какой-то пример или подробное описание?


 
3asys ©   (2012-01-05 12:05) [161]

> DVM ©

> Вот например для аудио http://www.libsdl.org/intro.ru/usingsound.
> html

Насколько я понял из описания, это API не работает на Win64, т.е. на клиентских машинах с 64-битной Win она работать не будет :(
К сожалению очень мало времени для преодоления нестыковок :) поэтому и возникает вопрос о существовании готового примера, который можно было бы прикрутить без серьезных сложностей.


 
DVM ©   (2012-01-05 12:06) [162]


> 3asys ©   (05.01.12 11:57) [160]


> Может быть есть какой-то пример или подробное описание?

я со звуком тоже не особенно много работал, описания конечно же есть:

Олег Гордеев - Программирование звука в Windows.
Н.Секунов - Обработка звука на PC.
Кинтцель Т. - Руководство программиста по работе со звуком.

В документации по DSPack описано как воспроизводить звук, в документации по SDL тоже. Но начни с книг, с первой вот например. После изучения твои вопросы станут более конкретными. Аудио данные у тебя уже есть.


 
DVM ©   (2012-01-05 12:07) [163]


> 3asys ©   (05.01.12 12:05) [161]


> Насколько я понял из описания, это API не работает на Win64

у нас работал, в одном проекте и на Win64 и на Linux 64 бит.


 
DVM ©   (2012-01-05 12:16) [164]

а вот книга по SDL
http://freecodingtutorial.files.wordpress.com/2011/10/premier-press-focus-on-sdl.pdf


 
3asys ©   (2012-01-05 12:23) [165]

> DVM ©
Спасибо Вам большое


 
DVM ©   (2012-01-05 12:26) [166]

Для SDL в двух словах работа выглядит следующим образом:
1) Инициализация SDL
2) Открываем аудио устройство и инициализируем его
3) Передаем SDL указатель на функцию обратного вызова, которую SDL будет дергать через определенные интервалы времени, внутри этой функции мы должны обеспечить SDL данными, заполнив передаваемый нам буфер, если данные у нас есть или заполнив его тишиной.

все. Остальное ложится на плечи SDL.


 
3asys ©   (2012-01-05 12:49) [167]

Спасибо, попробую сделать


 
3asys ©   (2012-01-07 16:20) [168]

> DVM ©
Добрый день,
не могли бы Вы подсказать:
создаю экземпляр клиента видеотрансляции:

procedure CreateNewUserTranslation(Host : String; Port : Integer; UserName : String);
var
 NewClntTransl : TfVideoClient;
begin
 NewClntTransl:=TfVideoClient.Create(fVideoClient);
 NewClntTransl.Host:=Host;
 NewClntTransl.Port := Port;
 NewClntTransl.Caption:=UserName;
 NewClntTransl.Show;
 NewClntTransl.StartTranslation(NewClntTransl);
end;

где StartTranslation(NewClntTransl)

procedure TfVideoClient.StartTranslation(Sender: TObject);
begin
 VideoThread := THTTPInputThread.Create(Host, Port, VideoPath, UserName, Password);
 AudioThread := THTTPInputThread.Create(Host, Port, AudioPath, UserName, Password);
end;

а дальше все, как в Вашем примере.
Форма создается, а трансляция не начинается. При этом, если вызываю StartTranslation напрямую (без создания формы), то все отлично работает.
Поскольку Вы единственный, кроме меня, кто представляет код клиента, не могли бы Вы подсказать, как следует создавать экземпляр клиента для получения на этом экземпляре трансляции?


 
DVM ©   (2012-01-08 12:35) [169]


> 3asys ©   (07.01.12 16:20) [168]

1) Отладчиком посмотри, на строку

VideoThread := THTTPInputThread.Create(Host, Port, VideoPath, UserName, Password);

ты попадаешь вообще?

2) Какому окну шлются сообщения о приходе новых кадров?

Т.е. как THTTPInputThread узнает куда ему слать сообщения?


 
3asys ©   (2012-01-08 14:28) [170]

> DVM ©  

> 1) Отладчиком посмотри, на строку
>
> VideoThread := THTTPInputThread.Create(Host, Port, VideoPath,
>  UserName, Password);
>
> ты попадаешь вообще?

Да, строка инициализируется нормально, все параметры правильные.

> 2) Какому окну шлются сообщения о приходе новых кадров?
>
> Т.е. как THTTPInputThread узнает куда ему слать сообщения?
>

Кажется Вы правы, сообщения отправляются SendMessage:

SendMessage(fVideoClient.Handle, FSendNewFrameMessage, 0, Longint(FrameData));

т.е. идут к fVideoClient, а, по идее, должны отправляться NewClntTransl, который создается в run-time.
Код приема сообщения формы fVideoClient полностью отрабатывается.Весь цикл проходится до самого конца, но картинка не появляется.
Действительно в этой строчке ошибка?
Как, если это так, передать Handle?


 
DVM ©   (2012-01-08 15:37) [171]


> Как, если это так, передать Handle?

в конструктор потока, там где то выше вроде даже было так в коде


 
3asys ©   (2012-01-08 16:14) [172]

Переписал. Теперь SendMessage передает окну с нужным handle, но трансляция не происходит :(  Что здесь может быть?
На всякий случай привожу полный код:
Запуск показа видеотрансляции:

procedure TfMain.N2Click(Sender: TObject);
var
 host, username : String;
 port : Integer;
begin
 host:=dmData.sp_UserList.Fields.fieldByName("user_ip").AsString;
 port:=Port_Video;
 username:=dmData.sp_UserList.Fields.fieldByName("user_name").AsString;
 fVideoClient.CreateNewUserTranslation(host, port, username);
end;

Создание окна и запуск видеотрансляции

procedure TfVideoClient.CreateNewUserTranslation(Host : String; Port : Integer; UserName : String);
var
 NewClntTransl : TfVideoClient;
begin
 NewClntTransl:=TfVideoClient.Create(fVideoClient);
 NewClntTransl.Host:=Host;
 NewClntTransl.Port := Port;
 NewClntTransl.Caption:=UserName;
 VideoThread := THTTPInputThread.Create(Host, Port, VideoPath, UserName, Password, NewClntTransl.Handle);
 AudioThread := THTTPInputThread.Create(Host, Port, AudioPath, UserName, Password, NewClntTransl.Handle);
 NewClntTransl.Show;
end;


 
3asys ©   (2012-01-08 16:17) [173]

Теперь работа потока (полный текст unit-а:

unit uClientFunctions;

interface

uses
Windows, Messages, Sysutils, Classes, SyncObjs, Winsock, EncdDecd, mmsystem,

uBuffer;

const
CR = #13;
LF = #10;
CRLF = #13#10;
StartJpegMarker = #255#216;
EndJpegMarker = #255#217;
HttpResponseHeaderDelimiter = "$%#&$";

type

THTTPInputThread = class(TThread)
private
  FHost: String;
  FPort: integer;
  FPath: String;
  FUsername: String;
  FPassword: String;
  FHandle: HWND;
  FSock: integer;
  FAddr: TSockAddr;
  FTimeout: TTimeVal;
  FBuffer: TBuffer;
  FRequest: String;
  FContentLength: integer;
  function SocketConnect: integer;
  function Init: integer;
  function SendRequest(ASock: integer; ARequest: String): integer;
  function ReadData(ABuffer: TBuffer; BytesExpected: integer): integer;
  function GetResponse: integer;
  function SocketDisconnect: integer;
protected
  procedure Execute; override;
public
  constructor Create(AHost: string; APort: integer; APath: string; AUserName: string; APassword: string; AHendle : HWND);
  destructor Destroy;  override;
end;

var
FSendNewFrameMessage: Cardinal; // Äëÿ Win32API

implementation

uses uVideoClient;

function MemStr2(const S, N: PAnsiChar; const Limit: Cardinal): PAnsiChar;
var
I: Cardinal;
pB1, pB2: PAnsiChar;
begin
result := nil;
if (s = nil) or (n = nil) then exit;
if limit < 2 then exit;
pB1 := S; pB2 := N;
for I := 0 to Limit - 2 do
  if (pB1^ = pB2^) and ((pB1 + 1)^ = (pB2 + 1)^) then
    begin
      result := pB1;
      exit;
    end
  else
    inc(pB1);
end;

//------------------------------------------------------------------------------

constructor THTTPInputThread.Create(AHost: string; APort: integer;
                                  APath: string; AUserName: string; APassword: string; AHendle : HWND);
begin
inherited Create(true);
FHost := AHost;
FPort := APort;
FPath := APath;
FUserName := AUserName;
FPassword := APassword;
FHandle := AHendle;
FBuffer := TBuffer.Create(0);
Resume;
FSendNewFrameMessage := RegisterWindowMessage("WM_NEW_FRAME");
end;

//------------------------------------------------------------------------------

destructor THTTPInputThread.Destroy;
begin
FBuffer.Free;
inherited Destroy;
end;

//------------------------------------------------------------------------------

function THTTPInputThread.SocketConnect: integer;
var
NoBlock: integer;
Wfd, EFd: TFDSet;
TimeVal: TTimeVal;
begin

Result := socket(AF_INET, SOCK_STREAM, 0);
if Result = INVALID_SOCKET then
  begin
    Result := -1;
    exit;
  end;

NoBlock := 1;
if ioctlsocket(Result, FIONBIO, NoBlock) = SOCKET_ERROR then
  begin
    CloseSocket(Result);
    Result := -1;
    exit;
  end;

if Connect(Result, FAddr, SizeOf(FAddr)) = SOCKET_ERROR then
  begin  
    if WSAGetLastError =  WSAEWOULDBLOCK then
      begin
        while not Terminated do
          begin
            FD_ZERO(wfd);
            FD_SET(result, wfd);

            FD_ZERO(efd);
            FD_SET(result, efd);

            TimeVal.tv_sec := 0;
            TimeVal.tv_usec := 100;

            case select(0, nil, @wfd, @efd, @TimeVal) of
              0: sleep(50);
              1: if FD_ISSET(Result, wfd) then
                   break
                 else
                   if FD_ISSET(Result, efd) then
                     begin  
                       NoBlock := 0;
                       ioctlsocket(Result, FIONBIO, NoBlock);
                       CloseSocket(Result);
                       Result := -1;
                       exit;
                     end;
              SOCKET_ERROR:
                begin
                  NoBlock := 0;
                  ioctlsocket(Result, FIONBIO, NoBlock);
                  CloseSocket(Result);
                  Result := -1;
                  exit
                end;
            end;
          end;
       end
     else
       begin
         NoBlock := 0;
         ioctlsocket(Result, FIONBIO, NoBlock);
         CloseSocket(Result);
         Result := -1;
       end;
  end;

// &#194;&#238;&#231;&#226;&#240;&#224;&#242; &#226; &#225;&#235;&#238;&#234;&#232;&#240;&#243;&#254;&#249;&#232;&#233; &#240;&#229;&#230;&#232;&#236;
NoBlock := 0;
if ioctlsocket(Result, FIONBIO, NoBlock) = SOCKET_ERROR then
  begin
    CloseSocket(Result);
    Result := -1;
  end;
end;

//------------------------------------------------------------------------------

function THTTPInputThread.SocketDisconnect(): integer;
begin
if FSock <> -1 then
  begin
    ShutDown(FSock, SD_BOTH);
    CloseSocket(FSock);
    FSock := -1;
  end;
Result := 0;
end;

//------------------------------------------------------------------------------


 
3asys ©   (2012-01-08 16:19) [174]

function InetAddr(const AHost: AnsiString): DWORD;
var
PHost: PAnsiChar;
HostEnt: PHostEnt;
begin
if AHost = "" then
  result := DWORD($FFFFFFFF)
else
  begin
    PHost := PAnsiChar(AHost);
    Result := inet_addr(PHost);
    if Result = DWORD($FFFFFFFF) then
      begin
        HostEnt := GetHostByName(PHost);
        if HostEnt <> nil then
          Result := DWORD(pointer(HostEnt^.h_addr^)^);
      end;
  end;
end;

function THTTPInputThread.Init: integer;
begin
FBuffer.Empty;
ZeroMemory(@FAddr, SizeOf(FAddr));
FAddr.sin_family := PF_INET;
FRequest := "GET " + FPath + " HTTP/1.1" + CRLF +
            "Host: " + FHost + ":" + inttostr(FPort) + CRLF +
            "User-Agent: Mozilla/5.0" + CRLF +
            "Accept: */*" + CRLF +
            "Keep-Alive: 300"  + CRLF +
            "Connection: keep-alive";
FRequest := FRequest + CRLF + "Authorization: Basic " + EncodeString(FUserName + ":" + FPassword);
FRequest := FRequest + CRLF + CRLF;
FAddr.sin_addr.s_addr := InetAddr(AnsiString(FHost));
FAddr.sin_port := htons(FPort);
FTimeout.tv_sec := 20;
FTimeout.tv_usec := 0;
FSock := -1;
Result := 0;
end;

//------------------------------------------------------------------------------

function THTTPInputThread.SendRequest(ASock: integer; ARequest: String): integer;
var
ReturnCode: integer;
Req: AnsiString;
begin
Req := AnsiString(ARequest);
ReturnCode := send(ASock, Req[1], Length(Req), 0);
if ReturnCode = SOCKET_ERROR then
  begin
    Result := -1;
    SocketDisconnect();
  end
else
  begin
    Result := 0;
  end;
end;

//------------------------------------------------------------------------------

function THTTPInputThread.ReadData(ABuffer: TBuffer; BytesExpected: integer): integer;
const
MaxLen = 262144;
var
TotalBytesToRead, Found, TotalBytesRead, BytesToRead, BytesRead: integer;
Rfds: TFDSet;
TempBuff: array [0..Pred(MaxLen)] of AnsiChar;
begin
FD_ZERO(Rfds);
FD_SET(FSock, Rfds);
Found := select(FSock, @Rfds, nil, nil, @FTimeout);
if Found = 0 then
  begin
    // Select timed out
    Result := -1;
    exit;
  end
else
  if Found = SOCKET_ERROR then
    begin
      // Select error
      Result := -1;
      exit;
    end;
TotalBytesToRead := 0;
if BytesExpected <> 0 then
  begin
    TotalBytesToRead := BytesExpected;
  end
else
  begin
    if ioctlsocket(FSock, FIONREAD, TotalBytesToRead) = SOCKET_ERROR then
      begin
        // Cannot ioctl()
        Result := -1;
        exit;
      end;
    if TotalBytesToRead = 0  then
      begin
        SocketDisconnect();
        Result := 0;
        exit;
      end;
  end;
TotalBytesRead := 0;
repeat
  if TotalBytesToRead > MaxLen then
    BytesToRead := MaxLen
  else
  BytesToRead := TotalBytesToRead;
  ZeroMemory(@TempBuff[0], MaxLen);
  BytesRead := recv(FSock, TempBuff, BytesToRead, 0);
  if BytesRead = SOCKET_ERROR then
    begin
      // Read error
      SocketDisconnect();
      Result := -1;
      exit;
    end
  else
    if BytesRead = 0 then
      begin
        SocketDisconnect();
        Result := 0;
        exit;
      end
    else
      begin
        // &#197;&#241;&#235;&#232; &#225;&#243;&#244;&#229;&#240; &#241;&#242;&#224;&#235; &#241;&#235;&#232;&#248;&#234;&#238;&#236; &#225;&#238;&#235;&#252;&#248;&#238;&#233;
        if ABuffer.Size >= 2097152 then
          begin
            SocketDisconnect();
            Result := -1;
            exit;
          end;
        ABuffer.Append(@TempBuff[0], BytesRead);
        TotalBytesRead := TotalBytesRead + BytesRead;
        TotalBytesToRead := TotalBytesToRead - BytesRead;

      end;
until TotalBytesToRead <= 0;
Result := TotalBytesRead;
end;


 
3asys ©   (2012-01-08 16:19) [175]

//------------------------------------------------------------------------------

function THTTPInputThread.GetResponse(): integer;
var
StartPtr, EndPtr: PAnsiChar;
BufferLen, Offset: integer;
GotStartMarker: Boolean;
begin
// &#206;&#193;&#208;&#192;&#193;&#206;&#210;&#202;&#192; &#192;&#211;&#196;&#200;&#206; - &#207;&#206;&#210;&#206;&#202;&#192;:
If FPath = "/GetAudio" Then
begin
result := -1;
Offset := 0;
GotStartMarker := False;
while (not Terminated) do
  begin
    if (not GotStartMarker) and (FBuffer.Size > 2) then
      begin
        StartPtr := MemStr2(FBuffer.Head, StartJpegMarker, FBuffer.Size);
        if StartPtr <> nil then
          begin
            FBuffer.Consume(StartPtr - FBuffer.Head);
            GotStartMarker := true;
          end
        else
          FBuffer.Empty;
      end;
    if GotStartMarker and (FBuffer.Size > 2) then
      begin
        EndPtr := MemStr2(FBuffer.Head + Offset, EndJpegMarker, FBuffer.Size - Offset);
        if EndPtr <> nil then
          begin
            Result := EndPtr - FBuffer.Head + 2;
         //   waveOutWrite(0, Addr(soundTest), FContentLength);
        //    playsound(buf.Memory, 0, SND_MEMORY  or SND_ASYNC); // &#194;&#206;&#209;&#207;&#208;&#206;&#200;&#199;&#194;&#206;&#196;&#200;&#204; &#199;&#194;&#211;&#202;
            result := -1;// &#215;&#210;&#206;&#193;&#219; &#205;&#197; &#206;&#193;&#208;&#192;&#193;&#192;&#210;&#219;&#194;&#192;&#203;&#206;&#209;&# 220; SendMessage

            exit;
          end
        else
          Offset := FBuffer.Size - 2;
      end;
    BufferLen := ReadData(FBuffer, 0);
    if BufferLen < 0 then
      begin
        result := -1;
        exit;
      end;
  end;
end
else If FPath = "/GetVideo" Then // &#206;&#193;&#208;&#192;&#193;&#206;&#210;&#202;&#192; &#194;&#200;&#196;&#197;&#206; - &#207;&#206;&#210;&#206;&#202;&#192;:
begin
result := -1;
Offset := 0;
GotStartMarker := False;
while (not Terminated) do
  begin
    if (not GotStartMarker) and (FBuffer.Size > 2) then
      begin
        StartPtr := MemStr2(FBuffer.Head, StartJpegMarker, FBuffer.Size);
        if StartPtr <> nil then
          begin
            FBuffer.Consume(StartPtr - FBuffer.Head);
            GotStartMarker := true;
          end
        else
          FBuffer.Empty;
      end;
    if GotStartMarker and (FBuffer.Size > 2) then
      begin
        EndPtr := MemStr2(FBuffer.Head + Offset, EndJpegMarker, FBuffer.Size - Offset);
        if EndPtr <> nil then
          begin
            Result := EndPtr - FBuffer.Head + 2;
            exit;
          end
        else
          Offset := FBuffer.Size - 2;
      end;
    BufferLen := ReadData(FBuffer, 0);
    if BufferLen < 0 then
      begin
        result := -1;
        exit;
      end;
  end;
end
else
 result:=-1;

end;

//------------------------------------------------------------------------------
type

TFrameData = record
  FrameData: PAnsiChar;
  FrameDataLen: integer;
end;
PFrameData = ^TFrameData;

procedure THTTPInputThread.Execute;
var
FrameData: PFrameData;
Wsa: TWSADATA;
begin
WSAStartUp($0101, Wsa);
try
  while not Terminated do
    try
      Init;
      FSock := SocketConnect();
      if FSock <> -1 then
        try
          if SendRequest(FSock, FRequest) <> 0 then exit;
          repeat
            FContentLength := GetResponse;
            if FContentLength > 0 then
              begin
                FrameData := New(PFrameData);
                try
                  FrameData^.FrameData := FBuffer.Extract(FContentLength);
                  FrameData^.FrameDataLen := FContentLength;
                  // Передаем указатель на данные форме клиента:
                  SendMessage(FHandle, FSendNewFrameMessage, 0, Longint(FrameData));
                finally
                  Dispose(FrameData);
                end;
              end;
          until Terminated or (FContentLength = -1);
        finally
          SocketDisconnect;
        end
      else sleep(500);
    except
      sleep(500);
    end;
finally
   WSACleanUp;
end;
end;

end.

И, наконец, отрисовка на форме:

procedure TfVideoClient.WndProc(var Msg: TMessage);
var
 FrameData: PFrameData;
 jpeg : TJPEGImage;
 b : TBitmap;
begin
 if Msg.Msg = FSendNewFrameMessage then
 begin
   FrameData := PFrameData(Msg.Lparam);
   VideoStream.Clear;
   VideoStream.WriteBuffer(FrameData^.FrameData^, FrameData^.FrameDataLen);

   jpeg:=TJPEGImage.Create;
   VideoStream.Position:=0;
   jpeg.LoadFromStream(VideoStream);
   b:=TBitmap.Create;
   b.Assign(jpeg);
   // Подгонка размера формы под размер изображения:
   fVideoClient.Width:=b.Width;
   fVideoClient.Height:=b.Height;
   // Вывод картинки на канву:
   fVideoClient.Canvas.Draw(0,0,b);

   jpeg.Free;
   b.Free;
 end
 else
   inherited;
end;


 
3asys ©   (2012-01-08 16:25) [176]

Unit работы с потоком практически не менялся (только добавил Handle в конструктор.
Handle фориы которой отправляет сообщение SendMessage совпадает с Handle формы, которая выводится (в методе OnShow клиента пишу Caption:=IntToStr(Handle);) :)
Вожусь с этим третий день :(
Что еще можно сделать?


 
3asys ©   (2012-01-08 23:40) [177]

Данные какие-то по SendMessage приходят, картинка bitmap создается, но не отрисовывается.
В упор ничего не вижу. Больше 10 раз всю цепочку просмотрел - и не вижу, где может быть ошибка, хотя конечно есть, только где? :)


 
DVM ©   (2012-01-09 00:23) [178]


> Данные какие-то по SendMessage приходят, картинка bitmap
> создается, но не отрисовывается.

раз создается, значит отрисовывается не там, где должен

fVideoClient.Canvas.Draw(0,0,b);

вот здесь fVideoClient - это что?


 
3asys ©   (2012-01-09 00:28) [179]

это форма клиента


 
3asys ©   (2012-01-09 00:30) [180]

у нее тот handle , который задается Thread при инициировании [172] (Создание окна и запуск видеотрансляции)


 
DVM ©   (2012-01-09 00:39) [181]


> 3asys ©   (09.01.12 00:28) [179]

Их много что ли одновременно одинаковых?


 
DVM ©   (2012-01-09 00:43) [182]

Че то ты как то не так сделал. Надо было бы сделать отдельный класс-компонент наследник TWinControl например и его экземпляры создавать на форме, у каждого такого класса должен быть свой поток поставляющий данные для отрисовки и свой постоянно живущий в нем TBitmap который потоком обновляется, этот же TBitmap должен отрисовываться по WM_PAINT на окне этого компонента.

Ладно завтра разберемся. Это весьма все просто.


 
3asys ©   (2012-01-09 00:44) [183]

их должно быть по числу участников конференции - у каждого -свое окно в котором транслируется видео этого участника.
Смотрите, в отмеченном Вами куске действительно стоит форма клиента, а не та, которую я создаю в run-time. НО - создаю я форму в одной процедуре (CreateNewUserTranslation), а рисую на ней в другой (WndProc).
Тогда, как передать именно созданную форму в процедуру рисования?


 
3asys ©   (2012-01-09 00:46) [184]

Спасибоб, сейчас попробую написать.


 
DVM ©   (2012-01-09 00:47) [185]


> Тогда, как передать именно созданную форму в процедуру рисования?

переделать надо, завтра объясню как


 
3asys ©   (2012-01-09 11:58) [186]

> DVM ©
Добрый день,
в процедуре

// &#209;&#238;&#231;&#228;&#224;&#237;&#232;&#229; &#238;&#234;&#237;&#224; &#232; &#231;&#224;&#239;&#243;&#241;&#234; &#226;&#232;&#228;&#229;&#238;-&#224;&#243;&#228;&#232;&#238; &#242;&#240;&#224;&#237;&#241;&#235;&#255;&#246;&#232;&#232; &#239;&#238;&#235;&#252;&#231;&#238;&#226;&#224;&#242;&#229;&#235;&#255;:
procedure TfVideoClient.CreateNewUserTranslation(Host : String; Port : Integer; UserName : String);
var
 NewClntTransl : TfVideoClient;
 Handle : HWND;
 b : TBitmap;
begin
 NewClntTransl:=TfVideoClient.Create(fVideoClient);
 NewClntTransl.Host:=Host;
 NewClntTransl.Port := Port;
 NewClntTransl.Caption:=UserName;
 NewClntTransl.Show;
 b:=TBitmap.Create;
 Handle:=NewClntTransl.Handle;
 VideoThread := THTTPInputThread.Create(Host, Port, VideoPath, UserName, Password, Handle);
 AudioThread := THTTPInputThread.Create(Host, Port, AudioPath, UserName, Password, Handle);
end;

я создаю экземпляр клиента и его собственные видео и аудио потоки (VideoThread, AudioThread).
Далее эти потоки обрабатываются THTTPInputThread. В ходе обработки видеопотока создается

SendMessage(FHandle, FSendNewFrameMessage, 0, Longint(FrameData));

которая передает картинку форме с handle = FHandle
Далее в обработчике

procedure TfVideoClient.WndProc(var Msg: TMessage);
var
 FrameData: PFrameData;
 jpeg : TJPEGImage;
 b : TBitmap;
begin
 if Msg.Msg = FSendNewFrameMessage then
 begin
   // &#199;&#224;&#227;&#240;&#243;&#231;&#234;&#224; &#228;&#224;&#237;&#237;&#251;&#245; &#226; &#239;&#238;&#242;&#238;&#234;, &#226;&#251;&#227;&#240;&#243;&#231;&#234;&#224; &#238;&#242;&#242;&#243;&#228;&#224; &#232;&#245; &#226; Jpeg
   // &#228;&#229;&#234;&#238;&#228;&#232;&#240;&#238;&#226;&#224;&#237;&#232;&#229; &#232; &#238;&#242;&#240;&#232;&#241;&#238;&#226;&#234;&#224;
   FrameData := PFrameData(Msg.Lparam);
   VideoStream.Clear;
   VideoStream.WriteBuffer(FrameData^.FrameData^, FrameData^.FrameDataLen);

   jpeg:=TJPEGImage.Create;
   VideoStream.Position:=0;
   jpeg.LoadFromStream(VideoStream);
   b:=TBitmap.Create;
   b.Assign(jpeg);
   // &#207;&#238;&#228;&#227;&#238;&#237;&#234;&#224; &#240;&#224;&#231;&#236;&#229;&#240;&#224; &#244;&#238;&#240;&#236;&#251; &#239;&#238;&#228; &#240;&#224;&#231;&#236;&#229;&#240; &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#255;:
   fVideoClient.Width:=b.Width;
   fVideoClient.Height:=b.Height;
   // &#194;&#251;&#226;&#238;&#228; &#234;&#224;&#240;&#242;&#232;&#237;&#234;&#232; &#237;&#224; &#234;&#224;&#237;&#226;&#243;:
   fVideoClient.Canvas.Draw(0,0,b);

   jpeg.Free;
   b.Free;
 end
 else
   inherited;
end;

Надо бы вместо fVideoClient указать форму с FHandle, но как это сделать ?
пробовал FindWindow (по имени окна), но как на ней обновить bitmap? (и как при создании привязать bitmap к форме?)


 
3asys ©   (2012-01-15 12:41) [187]

> DVM ©  
Сделал передачу Handle:
Передаю в ветвь hanle:

procedure TfVideoClient.CreateNewUserTranslation(Host : String; Port : Integer; UserName : String);
var
 NewClntTransl : TfVideoClient;
 Handle : HWND;
 b : TBitmap;
begin
 NewClntTransl:=TfVideoClient.Create(fVideoClient);
 NewClntTransl.Host:=Host;
 NewClntTransl.Port := Port;
 NewClntTransl.Caption:=UserName;
 NewClntTransl.Show;
 Handle:=NewClntTransl.Handle;
 VideoThread := THTTPInputThread.Create(Host, Port, VideoPath, UserName, Password, Handle);
 AudioThread := THTTPInputThread.Create(Host, Port, AudioPath, UserName, Password, Handle);
end;

Из ветви передаю в WndProc hanle в WParam:

SendMessage(FHandle, FSendNewFrameMessage, FHandle, Longint(FrameData));

В WndProc обрабатываю:

procedure TfVideoClient.WndProc(var Msg: TMessage);
var
 FrameData: PFrameData;
 jpeg : TJPEGImage;
 b : TBitmap;
 h : HWND;
begin
 if Msg.Msg = FSendNewFrameMessage then
 begin
   FrameData := PFrameData(Msg.Lparam);
   h:=Msg.WParam;
   VideoStream.Clear;
   VideoStream.WriteBuffer(FrameData^.FrameData^, FrameData^.FrameDataLen);

   jpeg:=TJPEGImage.Create;
   VideoStream.Position:=0;
   jpeg.LoadFromStream(VideoStream);
   b:=TBitmap.Create;
   b.Assign(jpeg);
   TForm(FindControl(h)).Width:=b.Width;
   TForm(FindControl(h)).Height:=b.Height;
   TForm(FindControl(h)).Canvas.Draw(0,0,b);

   jpeg.Free;
   b.Free;
 end
 else
   inherited;
end;


Вроде все работает.
Но хотелось бы более красиво - как Вы предлагали.
Как это сделать?



Страницы: 1 2 3 4 5 вся ветка

Форум: "Начинающим";
Текущий архив: 2012.05.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.85 MB
Время: 0.02 c
2-1326697088
Nikitos
2012-01-16 10:58
2012.05.20
Перевод чисел из арабских в почтовый индекс


1-1291970624
mnj
2010-12-10 11:43
2012.05.20
Выбор точек, веток и и х движение в TChart


4-1256831521
reactor
2009-10-29 18:52
2012.05.20
Как считать информацию из Combobox-а


15-1326539168
SQLEX
2012-01-14 15:06
2012.05.20
Шахматы. Короткие партии. Аля "Клуб13"


15-1326499809
KilkennyCat
2012-01-14 04:10
2012.05.20
новый вид памяти





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский