Subversion Repositories alarming

Rev

Blame | Last modification | View Log | RSS feed

  1. {
  2. MJPEG Decoder Class
  3. Copyright 2006, Steve Blinch
  4. http://code.blitzaffe.com
  5.  
  6. This script is free software; you can redistribute it and/or modify it under the
  7. terms of the GNU General Public License as published by the Free Software
  8. Foundation; either version 2 of the License, or (at your option) any later
  9. version.
  10.  
  11. This script is distributed in the hope that it will be useful, but WITHOUT ANY
  12. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  14. details.
  15.  
  16. You should have received a copy of the GNU General Public License along
  17. with this script; if not, write to the Free Software Foundation, Inc.,
  18. 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. }
  20.  
  21. unit MJPEGDecoderThread;
  22.  
  23. {$M+} // Added VTS 06.05.2019 to supress compiler warning
  24.  
  25. interface
  26.  
  27. uses Classes,IdTCPClient;
  28.  
  29. const
  30.   MSG_MJPEG_FRAME   = 1;
  31.   MSG_MJPEG_ERROR   = 2;
  32.   MSG_MJPEG_MESSAGE = 3;
  33.  
  34.   ERROR_MJPEG_BADFRAME    = 1;
  35.   ERROR_MJPEG_EXCEPT      = 2;
  36.   ERROR_MJPEG_DISCONNECT  = 3;
  37.  
  38. Type
  39.   TMJPEGDecoderMsg = class(TObject)
  40.       public
  41.         Msg: String;
  42.     end;
  43.  
  44.   TMJPEGDecoderThread = class(TThread)
  45.     private
  46.       FClient: TIdTCPClient;
  47.       FActive: Boolean;
  48.       FNotifyWindow: THandle;
  49.  
  50.       procedure Info(S: String);
  51.       function CheckConnected: Boolean;
  52.     public
  53.       constructor Create(TCPClient: TIdTCPClient; NotifyWindow: THandle);
  54.       procedure Execute; override;
  55.     published
  56.       property Active: Boolean read FActive;
  57.     end;
  58.  
  59. implementation
  60.  
  61. uses SysUtils,Windows,Messages;
  62.  
  63. constructor TMJPEGDecoderThread.Create(TCPClient: TIdTCPClient; NotifyWindow: THandle);
  64. begin
  65.   FActive:=False;
  66.   FClient:=TCPClient;
  67.   FNotifyWindow:=NotifyWindow;
  68.  
  69.   inherited Create(True);
  70.   FreeOnTerminate:=True;
  71. end;
  72.  
  73. function TMJPEGDecoderThread.CheckConnected: Boolean;
  74. begin
  75.   if not FClient.Connected then
  76.     begin
  77.       PostMessage(FNotifyWindow,WM_USER,MSG_MJPEG_ERROR,ERROR_MJPEG_DISCONNECT);
  78.       Terminate;
  79.     end;
  80.   Result:=FClient.Connected;
  81. end;
  82.  
  83. procedure TMJPEGDecoderThread.Execute;
  84. var
  85.   S: String;
  86.   CLength: Integer;
  87.   JPEG: TMemoryStream;
  88. begin
  89.   FActive:=True;
  90.   try
  91.     try
  92.  
  93.       CLength:=0;
  94.       Info('Decoder thread starting execution loop');
  95.       while (not Terminated) do
  96.         begin
  97.           if not CheckConnected then break;
  98.  
  99.           // grab a header
  100.           Info('Waiting for data...');
  101.           try
  102.             S:=Trim(LowerCase(FClient.IOHandler.ReadLn));
  103.           except
  104.             if (not CheckConnected) then break;
  105.             PostMessage(FNotifyWindow,WM_USER,MSG_MJPEG_ERROR,ERROR_MJPEG_EXCEPT);
  106.             Terminate;
  107.             break;
  108.           end;
  109.           Info('Data: '+S);
  110.  
  111.           if not CheckConnected then break;
  112.  
  113.           // if it's a content-length line, record the content length
  114.           if (Copy(S,1,15)='content-length:') then
  115.             begin
  116.               Delete(S,1,15);
  117.               S:=Trim(S);
  118.               CLength:=StrToIntDef(S,0);
  119.               Info('Next frame content length: '+IntToStr(CLength));
  120.             end;
  121.  
  122.           // if it's a blank line and we have a content-length, then we're good to receive the stream
  123.           if (Length(S)=0) and (CLength>0) then
  124.             begin
  125.               Info('Receiving frame');
  126.               JPEG:=TMemoryStream.Create;
  127.               JPEG.SetSize(CLength);
  128.               try
  129.                 FClient.IOHandler.ReadStream(JPEG,CLength);
  130.                 PostMessage(FNotifyWindow,WM_USER,MSG_MJPEG_FRAME,Integer(JPEG));
  131.               except
  132.                 PostMessage(FNotifyWindow,WM_USER,MSG_MJPEG_ERROR,ERROR_MJPEG_BADFRAME);
  133.                 Terminate;
  134.                 break;
  135.               end;
  136.               Info('Frame received');
  137.               CLength:=0;
  138.             end;
  139.  
  140.         end;
  141.       Info('Decoder thread execution loop complete');
  142.     except
  143.       on E: Exception do
  144.         begin
  145.           PostMessage(FNotifyWindow,WM_USER,MSG_MJPEG_ERROR,ERROR_MJPEG_EXCEPT);
  146.         end;
  147.     end;
  148.   finally
  149.     FActive:=False;
  150.   end;
  151.  
  152. end;
  153.  
  154. procedure TMJPEGDecoderThread.Info(S: String);
  155. var Msg: TMJPEGDecoderMsg;
  156. begin
  157.   exit;
  158.   Msg:=TMJPEGDecoderMsg.Create;
  159.   Msg.Msg:=S;
  160.   PostMessage(FNotifyWindow,WM_USER,MSG_MJPEG_MESSAGE,Integer(Msg));
  161. end;
  162.  
  163. end.
  164.