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 |