Форум: "Начинающим";
Текущий архив: 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;
// Âîçâðàò â áëîêèðóþùèé ðåæèì
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
// Åñëè áóôåð ñòàë ñëèøêîì áîëüøîé
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
// ÎÁÐÀÁÎÒÊÀ ÀÓÄÈÎ - ÏÎÒÎÊÀ:
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); // ÂÎÑÏÐÎÈÇÂÎÄÈÌ ÇÂÓÊ
result := -1;// ×ÒÎÁÛ ÍÅ ÎÁÐÀÁÀÒÛÂÀËÎÑ&# 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 // ÎÁÐÀÁÎÒÊÀ ÂÈÄÅÎ - ÏÎÒÎÊÀ:
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 ©
Добрый день,
в процедуре
// Ñîçäàíèå îêíà è çàïóñê âèäåî-àóäèî òðàíñëÿöèè ïîëüçîâàòåëÿ:
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
// Çàãðóçêà äàííûõ â ïîòîê, âûãðóçêà îòòóäà èõ â Jpeg
// äåêîäèðîâàíèå è îòðèñîâêà
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;
Надо бы вместо 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