Reputation: 779
I am trying to capture still images from various security cameras around our offices on a regular basis. I use the following code to do so:
Var
MS: TMemoryStream;
I: Integer;
Begin
MS := TMemoryStream.Create;
Try
// Loop through however many channels the camera has (most have 1 but 180
// cams have 4).
For I := 1 To FCamera.Channels Do
Begin
MS.Clear;
Try
// Use basic authentication only if a user name and password has been
// specified for access to the camera.
FHTTP.Request.BasicAuthentication := False;
If (FCamera.UserName <> '') Or (FCamera.Password <> '') Then
Begin
FHTTP.Request.Username := FCamera.UserName;
FHTTP.Request.Password := FCamera.Password;
FHTTP.Request.BasicAuthentication := True;
End;
FHTTP.Request.UserAgent := USERAGENT;
// Get the image from the camera.
FHTTP.Get(FCamera.BuildURL(I), MS);
This works fine for most of the cameras as they have URLs that you can go to to get a current still image. I have a few cameras though that will only give you an MJPEG stream and therefore, the FHTTP.Get never finishes as the stream is basically infinite. How could I do a HTTP GET and only get the first MB or so which I could then extract the first image from?
Upvotes: 1
Views: 886
Reputation: 597951
To answer your specific question:
How could I do a HTTP GET and only get the first MB or so
IF the web server supports the Range
request header, you can use the TIdHTTP.Request.Range
property to specify the desired range of bytes to retrieve, eg:
FHTTP.Request.Range := 'bytes; 0-1048575';
FHTTP.Get(FCamera.BuildURL(I), MS);
Support for byte ranges is indicated by the presence of an Accept-Ranges: bytes
response header (see the TIdHTTP.Response.AcceptRanges
property), such as on a HEAD
request for the same resource that will be retrieved with a subsequent GET
request.
However, if the web server does not support bytes ranges, and IF the web server is using a MIME-formatted server push to send the images, such as with the multipart/x-mixed-replace
content type, then you can enable the hoNoReadMultipartMIME
flag in the TIdHTTP.HTTPOptions
property to tell TIdHTTP.Get()
to exit when it reaches the beginning of the stream data, and then you can manually read from the TIdHTTP.IOHanlder
directly and process the stream data as needed. There is a blog post on Indy's website about that topic:
New TIdHTTP hoNoReadMultipartMIME flag
Upvotes: 3