justcomputers
asked on
Stream video or Jpeg across internet
I want to be able to stream video (PVIDEOHDR) or jpeg across the internet.
I have some code working (using socket components), but the full jpeg is not getting delivered. across the internet maybe only 10% of the picture is "decoded" correctly, over a local lan (10 speed), if i make the compression of the jpeg 50% or less, it displays correctly, anything above that gives jpeg error #52 on the client end.
Dropping the frame rate seems to have no effect on the display, can anyone give me working code ?.
PS : I am using the TVideoCap Version 2.3 component to capture the video at the server end.
I have some code working (using socket components), but the full jpeg is not getting delivered. across the internet maybe only 10% of the picture is "decoded" correctly, over a local lan (10 speed), if i make the compression of the jpeg 50% or less, it displays correctly, anything above that gives jpeg error #52 on the client end.
Dropping the frame rate seems to have no effect on the display, can anyone give me working code ?.
PS : I am using the TVideoCap Version 2.3 component to capture the video at the server end.
I have 2 examples of sending a stream over TCP/IP. One is non-blocking the other is blocking (faster but more difficult). They both transfer files but it won't be difficult to have it loading a jpeg (or something else) from memory into a stream and transfer that.
ASKER
Can you post the code here or email it as an attatchment so i can see if it works ?.
Thanks.
Alternativley i can post my code here, then you can see where my code is faulty.
Thanks.
Alternativley i can post my code here, then you can see where my code is faulty.
Post to where..?
If it's not too big the show me your code.
If it's not too big the show me your code.
ASKER
Post to experts-exchange if possible.
OK here is my code.
******************** client socket read **************
procedure TForm1.ClientSocketRead(Se nder: TObject;
Socket: TCustomWinSocket);
var
Memorystream: TMemoryStream;
JPEG : TJPEGImage;
Buffer: Array[0..10000] of byte;
Received: Integer;
begin
try
MemoryStream := TMemoryStream.Create;
Received := socket.ReceiveBuf(Buffer, sizeof(Buffer));
Memorystream.Write(Buffer, Received);
Memorystream.Seek(0,0);
cledit2.Text := inttostr(Received);
JPEG := TJpegImage.Create;
try
JPeg.LoadFromStream(Memory Stream);
except;
exit;
{Ive placed this exception here just to get rid of those annoying messgaes}
end;
Image1.Width:= JPEG.Width;
CLEditImageHeight.Text := inttostr(JPEG.Height);
CLEditImageWidth.Text := inttostr(JPEG.Width);
Image1.Height:= JPEG.Height;
image1.Picture.Assign(Jpeg );
finally
Memorystream.free;
Jpeg.free;
end;
end;
***************** end of client socket read ************
****** start of onvideostream event of videocap *********
procedure TForm1.VideoCap1VideoStrea m(sender: TObject; lpVhdr: PVIDEOHDR);
var Bitmap:TBitmap;
info:TBitmapInfo;
j : TJPegImage;
MemoryStream: TMemoryStream;
begin
try
inc(Frames);
Editframes.text := inttostr(Frames);
j:=TJPegImage.create;
info:= videocap1.BitMapInfo;
Bitmap:=TBitmap.Create;
frameToBitmap(Bitmap,lpvhd r^.lpData, Info);
j.assign(Bitmap);
J.CompressionQuality :=CompressionValue;// Anything above 50 causes corruption
J.Compress;
Image1.Picture.Assign(J);
MemoryStream := TMemoryStream.Create;
Memorystream.Seek(0,0);
J.SaveToStream(MemoryStrea m);
Memorystream.Seek(0,0);
ServerSocket.Socket.Connec tions[0].s endstream( MemoryStre am);
finally;
J.free;
Bitmap.free;
end;
end;
OK here is my code.
******************** client socket read **************
procedure TForm1.ClientSocketRead(Se
Socket: TCustomWinSocket);
var
Memorystream: TMemoryStream;
JPEG : TJPEGImage;
Buffer: Array[0..10000] of byte;
Received: Integer;
begin
try
MemoryStream := TMemoryStream.Create;
Received := socket.ReceiveBuf(Buffer, sizeof(Buffer));
Memorystream.Write(Buffer,
Memorystream.Seek(0,0);
cledit2.Text := inttostr(Received);
JPEG := TJpegImage.Create;
try
JPeg.LoadFromStream(Memory
except;
exit;
{Ive placed this exception here just to get rid of those annoying messgaes}
end;
Image1.Width:= JPEG.Width;
CLEditImageHeight.Text := inttostr(JPEG.Height);
CLEditImageWidth.Text := inttostr(JPEG.Width);
Image1.Height:= JPEG.Height;
image1.Picture.Assign(Jpeg
finally
Memorystream.free;
Jpeg.free;
end;
end;
***************** end of client socket read ************
****** start of onvideostream event of videocap *********
procedure TForm1.VideoCap1VideoStrea
var Bitmap:TBitmap;
info:TBitmapInfo;
j : TJPegImage;
MemoryStream: TMemoryStream;
begin
try
inc(Frames);
Editframes.text := inttostr(Frames);
j:=TJPegImage.create;
info:= videocap1.BitMapInfo;
Bitmap:=TBitmap.Create;
frameToBitmap(Bitmap,lpvhd
j.assign(Bitmap);
J.CompressionQuality :=CompressionValue;// Anything above 50 causes corruption
J.Compress;
Image1.Picture.Assign(J);
MemoryStream := TMemoryStream.Create;
Memorystream.Seek(0,0);
J.SaveToStream(MemoryStrea
Memorystream.Seek(0,0);
ServerSocket.Socket.Connec
finally;
J.free;
Bitmap.free;
end;
end;
//Bloodline Listening
Hi, the way you receive the packets is not right. It seems that everyone makes the same mistakes ;o)
The best thing you should do is sending the number of bytes to send first. This is because the receiving part can get multiple OnRead events. This means that the first packet contains the size (let's say 4 or 8 bytes) and some data. The second packet has more data and so on until the number of received bytes equals the size received at the beginning of the first packet.
If you are sending a continuous stream of data (e.g. multiple image), you must take into account that the size of the n-th image can be in the middle of a packet. So if image n-1 has been received, don't throw away the date after the last byte of image n-1.
Use some FIFO queue or something like that during the life of the connection.
I hope this clears things up a little.
The best thing you should do is sending the number of bytes to send first. This is because the receiving part can get multiple OnRead events. This means that the first packet contains the size (let's say 4 or 8 bytes) and some data. The second packet has more data and so on until the number of received bytes equals the size received at the beginning of the first packet.
If you are sending a continuous stream of data (e.g. multiple image), you must take into account that the size of the n-th image can be in the middle of a packet. So if image n-1 has been received, don't throw away the date after the last byte of image n-1.
Use some FIFO queue or something like that during the life of the connection.
I hope this clears things up a little.
ASKER
Yes, it's more or less what i had guessed at, but do you have any example code, i cant find any examples to work from, and this is my first time working with sockets.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for the examples, i only got an email telling me of your post on Sunday morning @ 08:00, i am looking at the code now, and will get back within a day or 2, but it certainly looks like you will be getting the points.
Thanks very much for your help.
Thanks very much for your help.
ASKER
Thanks Epsylon, your code did the trick so here are the points, thanks very much once again, you are a star.
PS :- Do you know where i can find decent documentation explaining sockets, and how your code works.
PS :- Do you know where i can find decent documentation explaining sockets, and how your code works.
So far I haven't found any good documentation for Delphi's components. Most of it I found out myself using the knowlegde I have since 1990.
delphi.about.com has a search engine which is the best option I can think of right now.
delphi.about.com has a search engine which is the best option I can think of right now.
ASKER
OK Thanks