hedgewars/uVideoRec.pas
changeset 11612 b7d5d75469ee
parent 11532 bf86c6cb9341
child 11821 d8844d4c67de
equal deleted inserted replaced
11611:b53c3134d55a 11612:b7d5d75469ee
    56 function AVWrapper_Init(
    56 function AVWrapper_Init(
    57               AddLog: TAddFileLogRaw;
    57               AddLog: TAddFileLogRaw;
    58               filename, desc, soundFile, format, vcodec, acodec: PChar;
    58               filename, desc, soundFile, format, vcodec, acodec: PChar;
    59               width, height, framerateNum, framerateDen, vquality: LongInt): LongInt; cdecl; external AvwrapperLibName;
    59               width, height, framerateNum, framerateDen, vquality: LongInt): LongInt; cdecl; external AvwrapperLibName;
    60 function AVWrapper_Close: LongInt; cdecl; external AvwrapperLibName;
    60 function AVWrapper_Close: LongInt; cdecl; external AvwrapperLibName;
    61 function AVWrapper_WriteFrame( pY, pCb, pCr: PByte ): LongInt; cdecl; external AvwrapperLibName;
    61 function AVWrapper_WriteFrame(rgb: PByte): LongInt; cdecl; external AvwrapperLibName;
    62 
    62 
    63 type TFrame = record
    63 type TFrame = record
    64                   realTicks: LongWord;
    64                   realTicks: LongWord;
    65                   gameTicks: LongWord;
    65                   gameTicks: LongWord;
    66                   CamX, CamY: LongInt;
    66                   CamX, CamY: LongInt;
   119         , cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cVideoQuality) >= 0,
   119         , cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cVideoQuality) >= 0,
   120         'AVWrapper_Init failed',
   120         'AVWrapper_Init failed',
   121         true) then exit(false);
   121         true) then exit(false);
   122 
   122 
   123     numPixels:= cScreenWidth*cScreenHeight;
   123     numPixels:= cScreenWidth*cScreenHeight;
   124     YCbCr_Planes[0]:= GetMem(numPixels);
       
   125     YCbCr_Planes[1]:= GetMem(numPixels div 4);
       
   126     YCbCr_Planes[2]:= GetMem(numPixels div 4);
       
   127 
       
   128     if (YCbCr_Planes[0] = nil) or (YCbCr_Planes[1] = nil) or (YCbCr_Planes[2] = nil) then
       
   129     begin
       
   130         AddFileLog('Error: Could not allocate memory for video recording (YCbCr buffer).');
       
   131         exit(false);
       
   132     end;
       
   133 
   124 
   134     RGB_Buffer:= GetMem(4*numPixels);
   125     RGB_Buffer:= GetMem(4*numPixels);
   135     if RGB_Buffer = nil then
   126     if RGB_Buffer = nil then
   136     begin
   127     begin
   137         AddFileLog('Error: Could not allocate memory for video recording (RGB buffer).');
   128         AddFileLog('Error: Could not allocate memory for video recording (RGB buffer).');
   145 end;
   136 end;
   146 
   137 
   147 procedure StopVideoRecording;
   138 procedure StopVideoRecording;
   148 begin
   139 begin
   149     AddFileLog('StopVideoRecording');
   140     AddFileLog('StopVideoRecording');
   150     FreeMem(YCbCr_Planes[0], numPixels);
       
   151     FreeMem(YCbCr_Planes[1], numPixels div 4);
       
   152     FreeMem(YCbCr_Planes[2], numPixels div 4);
       
   153     FreeMem(RGB_Buffer, 4*numPixels);
   141     FreeMem(RGB_Buffer, 4*numPixels);
   154     Close(cameraFile);
   142     Close(cameraFile);
   155     if AVWrapper_Close() < 0 then
   143     if AVWrapper_Close() < 0 then
   156         halt(-1);
   144         halt(-1);
   157     Erase(cameraFile);
   145     Erase(cameraFile);
   158     DeleteFile(soundFilePath);
   146     DeleteFile(soundFilePath);
   159     SendIPC(_S'v'); // inform frontend that we finished
   147     SendIPC(_S'v'); // inform frontend that we finished
   160 end;
   148 end;
   161 
   149 
   162 function pixel(x, y, color: LongInt): LongInt;
       
   163 begin
       
   164     pixel:= RGB_Buffer[(cScreenHeight-y-1)*cScreenWidth*4 + x*4 + color];
       
   165 end;
       
   166 
       
   167 procedure EncodeFrame;
   150 procedure EncodeFrame;
   168 var x, y, r, g, b: LongInt;
   151 var s: shortstring;
   169     s: shortstring;
       
   170 begin
   152 begin
   171     // read pixels from OpenGL
   153     // read pixels from OpenGL
   172     glReadPixels(0, 0, cScreenWidth, cScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, RGB_Buffer);
   154     glReadPixels(0, 0, cScreenWidth, cScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, RGB_Buffer);
   173 
   155 
   174     // convert to YCbCr 4:2:0 format
   156     if AVWrapper_WriteFrame(RGB_Buffer) < 0 then
   175     // Y
       
   176     for y := 0 to cScreenHeight-1 do
       
   177         for x := 0 to cScreenWidth-1 do
       
   178             YCbCr_Planes[0][y*cScreenWidth + x]:= Byte(16 + ((16828*pixel(x,y,0) + 33038*pixel(x,y,1) + 6416*pixel(x,y,2)) shr 16));
       
   179 
       
   180     // Cb and Cr
       
   181     for y := 0 to cScreenHeight div 2 - 1 do
       
   182         for x := 0 to cScreenWidth div 2 - 1 do
       
   183         begin
       
   184             r:= pixel(2*x,2*y,0) + pixel(2*x+1,2*y,0) + pixel(2*x,2*y+1,0) + pixel(2*x+1,2*y+1,0);
       
   185             g:= pixel(2*x,2*y,1) + pixel(2*x+1,2*y,1) + pixel(2*x,2*y+1,1) + pixel(2*x+1,2*y+1,1);
       
   186             b:= pixel(2*x,2*y,2) + pixel(2*x+1,2*y,2) + pixel(2*x,2*y+1,2) + pixel(2*x+1,2*y+1,2);
       
   187             YCbCr_Planes[1][y*(cScreenWidth div 2) + x]:= Byte(128 + ((-2428*r - 4768*g + 7196*b) shr 16));
       
   188             YCbCr_Planes[2][y*(cScreenWidth div 2) + x]:= Byte(128 + (( 7196*r - 6026*g - 1170*b) shr 16));
       
   189         end;
       
   190 
       
   191     if AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]) < 0 then
       
   192         halt(-1);
   157         halt(-1);
   193 
   158 
   194     // inform frontend that we have encoded new frame
   159     // inform frontend that we have encoded new frame
   195     s[0]:= #3;
   160     s[0]:= #3;
   196     s[1]:= 'p'; // p for progress
   161     s[1]:= 'p'; // p for progress