1
/*********************************************************************************
3
**********************************************************************************
5
* Copyright (C) 2006 John Varouhakis *
8
* This program is free software; you can redistribute it and/or modify *
9
* it under the terms of the GNU General Public License as published by *
10
* the Free Software Foundation; either version 2 of the License, or *
11
* (at your option) any later version. *
13
* This program is distributed in the hope that it will be useful, *
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16
* GNU General Public License for more details. *
18
* You should have received a copy of the GNU General Public License *
19
* along with this program; if not, write to the Free Software *
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
24
* For further information contact me at johnvarouhakis@gmail.com *
25
**********************************************************************************/
1
/******************************************************************************
3
*******************************************************************************
5
* Copyright (C) 2006,2007 John Varouhakis *
8
* This program is free software; you can redistribute it and/or modify *
9
* it under the terms of the GNU General Public License as published by *
10
* the Free Software Foundation; either version 2 of the License, or *
11
* (at your option) any later version. *
13
* This program is distributed in the hope that it will be useful, *
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16
* GNU General Public License for more details. *
18
* You should have received a copy of the GNU General Public License *
19
* along with this program; if not, write to the Free Software *
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
24
* For further information contact me at johnvarouhakis@gmail.com *
25
******************************************************************************/
27
27
#include <recordmydesktop.h>
30
int CompareBlocks(unsigned char *incoming,unsigned char *old,int blockno,int width, int height,int divisor){
30
int CompareBlocks(unsigned char *incoming,
32
block_i=blockno/divisor,//place on the grid
33
block_k=blockno%divisor;
34
register unsigned char *incoming_reg=&(incoming[block_i*(width*height/divisor)+block_k*width/divisor]),
35
*old_reg=&(old[block_i*(width*height/divisor)+block_k*width/divisor]);
37
for(j=0;j<height/divisor;j++){
38
for(i=0;i<width/divisor;i++){
37
block_i=blockno/(width/blockwidth),//place on the grid
38
block_k=blockno%(width/blockwidth);
39
register cmp_int_t *incoming_reg=(cmp_int_t *)&(incoming[(block_i*
41
block_k)*blockwidth]),
42
*old_reg=(cmp_int_t *)&(old[(block_i*
44
block_k)*blockwidth]);
46
for(j=0;j<blockwidth;j++){
47
for(i=0;i<blockwidth/COMPARE_STRIDE;i++){
39
48
if((*(incoming_reg++))!=(*(old_reg++)))
42
incoming_reg+=(width-width/divisor);
43
old_reg+=(width-width/divisor);
51
incoming_reg+=(width-blockwidth)/COMPARE_STRIDE;
52
old_reg+=(width-blockwidth)/COMPARE_STRIDE;
49
int FlushBlock(unsigned char *buf,int blockno,int width, int height,int divisor,gzFile *fp,FILE *ucfp){
51
block_i=blockno/divisor,//place on the grid
52
block_k=blockno%divisor;
53
register unsigned char *buf_reg=(&buf[block_i*(width*height/divisor)+block_k*width/divisor]);
55
for(j=0;j<height/divisor;j++){//we flush in rows
56
gzwrite(fp,(void *)buf_reg,width/divisor);
61
for(j=0;j<height/divisor;j++){//we flush in rows
62
fwrite((void *)buf_reg,width/divisor,1,ucfp);
66
return ((height*width)/pow(divisor,2));
58
int FlushBlock(unsigned char *buf,
68
block_i=(!blockwidth)?0:(blockno/(width/blockwidth)),//place on the grid
69
block_k=(!blockwidth)?0:(blockno%(width/blockwidth));
70
register unsigned char *buf_reg=(&buf[(block_i*
72
block_k)*blockwidth]);
73
static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE];
74
static unsigned int out_buffer_bytes=0;
76
if(out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE ||
77
(flush && out_buffer_bytes)){
79
gzwrite(fp,(void *)out_buffer,out_buffer_bytes);
81
fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp);
82
bytes_written=out_buffer_bytes;
86
register unsigned char *out_buf_reg=&out_buffer[out_buffer_bytes];
87
for(j=0;j<blockwidth;j++){
88
for(i=0;i<blockwidth;i++)
89
(*out_buf_reg++)=(*buf_reg++);
90
out_buffer_bytes+=blockwidth;
91
buf_reg+=width-blockwidth;
69
98
void *CacheImageBuffer(ProgData *pdata){
70
pthread_mutex_t pmut,imut;
71
pthread_mutex_init(&pmut,NULL);
72
pthread_mutex_init(&imut,NULL);
104
index_entry_size=sizeof(u_int32_t),
105
blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
106
blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH,
111
u_int32_t ynum,unum,vnum;
112
u_int32_t yblocks[blocknum_x*blocknum_y],
113
ublocks[blocknum_x*blocknum_y],
114
vblocks[blocknum_x*blocknum_y];
84
115
if(!pdata->args.zerocompression){
85
116
fp=pdata->cache_data->ifp;
86
117
if(fp==NULL)exit(13);
106
137
while(pdata->running){
109
unsigned short ynum,unum,vnum;
110
unsigned char yblocks[256],ublocks[64],vblocks[64];
111
140
FrameHeader fheader;
112
141
ynum=unum=vnum=0;
114
143
pdata->th_enc_thread_waiting=1;
115
pthread_cond_wait(&pdata->image_buffer_ready,&imut);
144
pthread_mutex_lock(&pdata->img_buff_ready_mutex);
145
pthread_cond_wait(&pdata->image_buffer_ready,
146
&pdata->img_buff_ready_mutex);
147
pthread_mutex_unlock(&pdata->img_buff_ready_mutex);
116
148
pdata->th_enc_thread_waiting=0;
119
pthread_cond_wait(&pdata->pause_cond,&pmut);
151
pthread_mutex_lock(&pause_mutex);
152
pthread_cond_wait(&pdata->pause_cond,&pause_mutex);
153
pthread_mutex_unlock(&pause_mutex);
120
156
pthread_mutex_lock(&pdata->yuv_mutex);
124
160
current=(current)?0:1;
126
memcpy(yuv[current].y,pdata->enc_data->yuv.y,yuv[current].y_width*yuv[current].y_height);
127
memcpy(yuv[current].u,pdata->enc_data->yuv.u,yuv[current].uv_width*yuv[current].uv_height);
128
memcpy(yuv[current].v,pdata->enc_data->yuv.v,yuv[current].uv_width*yuv[current].uv_height);
162
memcpy(yuv[current].y,pdata->enc_data->yuv.y,
163
yuv[current].y_width*yuv[current].y_height);
164
memcpy(yuv[current].u,pdata->enc_data->yuv.u,
165
yuv[current].uv_width*yuv[current].uv_height);
166
memcpy(yuv[current].v,pdata->enc_data->yuv.v,
167
yuv[current].uv_width*yuv[current].uv_height);
129
168
//release main buffer
130
169
pthread_mutex_unlock(&pdata->yuv_mutex);
131
170
//get checksums for new
133
172
//find and flush different blocks
136
for(j=0;j<pow(divisor,2);j++){
175
for(j=0;j<blocknum_x*blocknum_y;j++){
138
177
yblocks[ynum-1]=j;
140
for(j=0;j<pow(divisor/2,2);j++){
142
179
ublocks[unum-1]=j;
144
for(j=0;j<pow(divisor/2,2);j++){
146
181
vblocks[vnum-1]=j;
151
for(j=0;j<pow(divisor,2);j++){
152
if(CompareBlocks(yuv[current].y,yuv[prev].y,j,yuv[current].y_width,yuv[current].y_height,divisor)){
185
for(j=0;j<blocknum_x*blocknum_y;j++){
186
if(CompareBlocks(yuv[current].y,
189
yuv[current].y_width,
190
yuv[current].y_height,
154
193
yblocks[ynum-1]=j;
157
for(j=0;j<pow(divisor/2,2);j++){
158
if(CompareBlocks(yuv[current].u,yuv[prev].u,j,yuv[current].uv_width,yuv[current].uv_height,divisor/2)){
195
if(CompareBlocks(yuv[current].u,
198
yuv[current].uv_width,
199
yuv[current].uv_height,
160
202
ublocks[unum-1]=j;
163
for(j=0;j<pow(divisor/2,2);j++){
164
if(CompareBlocks(yuv[current].v,yuv[prev].v,j,yuv[current].uv_width,yuv[current].uv_height,divisor/2)){
204
if(CompareBlocks(yuv[current].v,
207
yuv[current].uv_width,
208
yuv[current].uv_height,
166
211
vblocks[vnum-1]=j;
179
224
strncpy(fheader.frame_prefix,"FRAM",4);
180
225
fheader.frameno=++frameno;
181
226
fheader.current_total=frames_total;
182
228
fheader.Ynum=ynum;
183
229
fheader.Unum=unum;
184
230
fheader.Vnum=vnum;
186
231
if(!pdata->args.zerocompression){
187
232
nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader));
189
if(ynum)nbytes+=gzwrite(fp,yblocks,ynum);
190
if(unum)nbytes+=gzwrite(fp,ublocks,unum);
191
if(vnum)nbytes+=gzwrite(fp,vblocks,vnum);
234
if(ynum)nbytes+=gzwrite(fp,(void*)yblocks,ynum*index_entry_size);
235
if(unum)nbytes+=gzwrite(fp,(void*)ublocks,unum*index_entry_size);
236
if(vnum)nbytes+=gzwrite(fp,(void*)vblocks,vnum*index_entry_size);
194
nbytes+=sizeof(FrameHeader)*fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp);
239
nbytes+=sizeof(FrameHeader)*
240
fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp);
196
if(ynum)nbytes+=ynum*fwrite(yblocks,ynum,1,ucfp);
197
if(unum)nbytes+=unum*fwrite(ublocks,unum,1,ucfp);
198
if(vnum)nbytes+=vnum*fwrite(vblocks,vnum,1,ucfp);
242
if(ynum)nbytes+=index_entry_size*
243
fwrite(yblocks,index_entry_size,ynum,ucfp);
244
if(unum)nbytes+=index_entry_size*
245
fwrite(ublocks,index_entry_size,unum,ucfp);
246
if(vnum)nbytes+=index_entry_size*
247
fwrite(vblocks,index_entry_size,vnum,ucfp);
200
249
//flush the blocks for each buffer
202
251
for(j=0;j<ynum;j++)
203
252
nbytes+=FlushBlock( yuv[current].y,yblocks[j],
204
253
yuv[current].y_width,
205
254
yuv[current].y_height,
210
261
for(j=0;j<unum;j++)
211
262
nbytes+=FlushBlock( yuv[current].u,ublocks[j],
212
263
yuv[current].uv_width,
213
264
yuv[current].uv_height,
218
271
for(j=0;j<vnum;j++)
219
272
nbytes+=FlushBlock( yuv[current].v,vblocks[j],
220
273
yuv[current].uv_width,
221
274
yuv[current].uv_height,
280
nbytes+=FlushBlock(NULL,0,0,0,0,fp,ucfp,1);
227
281
/**@________________@**/
228
282
pdata->avd+=pdata->frametime;
229
283
if(nbytes>CACHE_FILE_SIZE_LIMIT){
230
if(SwapCacheFilesWrite(pdata->cache_data->imgdata,nth_cache,&fp,&ucfp)){
231
fprintf(stderr,"New cache file could not be created.\nEnding recording...\n");
284
if(SwapCacheFilesWrite(pdata->cache_data->imgdata,
285
nth_cache,&fp,&ucfp)){
286
fprintf(stderr,"New cache file could not be created.\n"
287
"Ending recording...\n");
233
289
raise(SIGINT); //if for some reason we cannot make a new file
234
//we have to stop. If we are out of space,which means
290
//we have to stop. If we are out of space,
235
292
//that encoding cannot happen either,
236
293
//InitEncoder will cause an abrupt end with an
237
294
//error code and the cache will remain intact.
238
//If we've chosen separate two-stages, the program will make a
295
//If we've chosen separate two-stages,
296
//the program will make a
240
298
//In either case data will be preserved so if
241
//space is freed the recording can be proccessed later.
299
//space is freed the recording
300
//can be proccessed later.
248
306
//clean up since we're not finished
249
307
for(i=0;i<2;i++){
254
fprintf(stderr,"Saved %d frames in a total of %d requests\n",frameno,frames_total);
312
fprintf(stderr,"Saved %d frames in a total of %d requests\n",
313
frameno,frames_total);
255
314
if(!pdata->args.zerocompression){
256
315
gzflush(fp,Z_FINISH);