~ubuntu-branches/ubuntu/karmic/recordmydesktop/karmic

« back to all changes in this revision

Viewing changes to src/cache_frame.c

  • Committer: Bazaar Package Importer
  • Author(s): José L. Redrejo Rodríguez
  • Date: 2007-04-25 11:54:22 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070425115422-5jvf144ln0c44afr
Tags: 0.3.4-1
* New upstream release
* debian/control: conflicts with previous gtk-recordmydesktop versions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************************************
2
 
*                             recordMyDesktop                                    *
3
 
**********************************************************************************
4
 
*                                                                                *
5
 
*             Copyright (C) 2006  John Varouhakis                                *
6
 
*                                                                                *
7
 
*                                                                                *
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.                                         *
12
 
*                                                                                *
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.                                *
17
 
*                                                                                *
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   *
21
 
*                                                                                *
22
 
*                                                                                *
23
 
*                                                                                *
24
 
*    For further information contact me at johnvarouhakis@gmail.com              *
25
 
**********************************************************************************/
 
1
/******************************************************************************
 
2
*                            recordMyDesktop                                  *
 
3
*******************************************************************************
 
4
*                                                                             *
 
5
*            Copyright (C) 2006,2007 John Varouhakis                          *
 
6
*                                                                             *
 
7
*                                                                             *
 
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.                                       *
 
12
*                                                                             *
 
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.                              *
 
17
*                                                                             *
 
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  *
 
21
*                                                                             *
 
22
*                                                                             *
 
23
*                                                                             *
 
24
*   For further information contact me at johnvarouhakis@gmail.com            *
 
25
******************************************************************************/
26
26
 
27
27
#include <recordmydesktop.h>
28
28
 
29
29
 
30
 
int CompareBlocks(unsigned char *incoming,unsigned char *old,int blockno,int width, int height,int divisor){
 
30
int CompareBlocks(unsigned char *incoming,
 
31
                  unsigned char *old,
 
32
                  int blockno,
 
33
                  int width,
 
34
                  int height,
 
35
                  int blockwidth){
31
36
    int j,i,
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]);
36
 
 
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*
 
40
                                     width+
 
41
                                     block_k)*blockwidth]),
 
42
                       *old_reg=(cmp_int_t *)&(old[(block_i*
 
43
                                width+
 
44
                                block_k)*blockwidth]);
 
45
    //blocks are square
 
46
    for(j=0;j<blockwidth;j++){
 
47
        for(i=0;i<blockwidth/COMPARE_STRIDE;i++){
39
48
            if((*(incoming_reg++))!=(*(old_reg++)))
40
49
                return 1;
41
50
        }
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;
44
53
    }
45
54
 
46
55
    return 0;
47
56
}
48
57
 
49
 
int FlushBlock(unsigned char *buf,int blockno,int width, int height,int divisor,gzFile *fp,FILE *ucfp){
50
 
    int j,
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]);
54
 
    if(ucfp==NULL){
55
 
        for(j=0;j<height/divisor;j++){//we flush in rows
56
 
            gzwrite(fp,(void *)buf_reg,width/divisor);
57
 
            buf_reg+=width;
58
 
        }
59
 
    }
60
 
    else{
61
 
        for(j=0;j<height/divisor;j++){//we flush in rows
62
 
            fwrite((void *)buf_reg,width/divisor,1,ucfp);
63
 
            buf_reg+=width;
64
 
        }
65
 
    }
66
 
    return ((height*width)/pow(divisor,2));
 
58
int FlushBlock(unsigned char *buf,
 
59
               int blockno,
 
60
               int width,
 
61
               int height,
 
62
               int blockwidth,
 
63
               gzFile *fp,
 
64
               FILE *ucfp,
 
65
               int flush){
 
66
    int j,i,
 
67
        bytes_written=0,
 
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*
 
71
                                         width+
 
72
                                         block_k)*blockwidth]);
 
73
    static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE];
 
74
    static unsigned int out_buffer_bytes=0;
 
75
 
 
76
    if(out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE ||
 
77
       (flush && out_buffer_bytes)){
 
78
        if(ucfp==NULL)
 
79
            gzwrite(fp,(void *)out_buffer,out_buffer_bytes);
 
80
        else
 
81
            fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp);
 
82
        bytes_written=out_buffer_bytes;
 
83
        out_buffer_bytes=0;
 
84
    }
 
85
    if(!flush){
 
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;
 
92
        }
 
93
    }
 
94
 
 
95
    return bytes_written;
67
96
}
68
97
 
69
98
void *CacheImageBuffer(ProgData *pdata){
70
 
    pthread_mutex_t pmut,imut;
71
 
    pthread_mutex_init(&pmut,NULL);
72
 
    pthread_mutex_init(&imut,NULL);
73
99
    yuv_buffer yuv[2];
74
100
    gzFile *fp=NULL;
75
101
    FILE *ucfp=NULL;
76
102
    int i,
77
103
        current=0,
78
 
        divisor=16,
 
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,
79
107
        firstrun=1,
80
108
        frameno=0,
81
109
        nbytes=0,
82
110
        nth_cache=1;
83
 
 
 
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){
107
138
        int prev;
108
139
        int j;
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;
113
142
 
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;
117
149
 
118
 
        if(Paused)
119
 
            pthread_cond_wait(&pdata->pause_cond,&pmut);
 
150
        if(Paused){
 
151
            pthread_mutex_lock(&pause_mutex);
 
152
            pthread_cond_wait(&pdata->pause_cond,&pause_mutex);
 
153
            pthread_mutex_unlock(&pause_mutex);
 
154
        }
 
155
 
120
156
        pthread_mutex_lock(&pdata->yuv_mutex);
121
157
 
122
158
        //rotate buffers
123
159
        prev=current;
124
160
        current=(current)?0:1;
125
161
        //copy incoming
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
134
173
        if(firstrun){
135
174
            firstrun=0;
136
 
            for(j=0;j<pow(divisor,2);j++){
 
175
            for(j=0;j<blocknum_x*blocknum_y;j++){
137
176
                    ynum++;
138
177
                    yblocks[ynum-1]=j;
139
 
            }
140
 
            for(j=0;j<pow(divisor/2,2);j++){
141
178
                    unum++;
142
179
                    ublocks[unum-1]=j;
143
 
            }
144
 
            for(j=0;j<pow(divisor/2,2);j++){
145
180
                    vnum++;
146
181
                    vblocks[vnum-1]=j;
147
182
            }
148
 
 
149
183
        }
150
184
        else{
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,
 
187
                                 yuv[prev].y,
 
188
                                 j,
 
189
                                 yuv[current].y_width,
 
190
                                 yuv[current].y_height,
 
191
                                 Y_UNIT_WIDTH)){
153
192
                    ynum++;
154
193
                    yblocks[ynum-1]=j;
155
194
                }
156
 
            }
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,
 
196
                                 yuv[prev].u,
 
197
                                 j,
 
198
                                 yuv[current].uv_width,
 
199
                                 yuv[current].uv_height,
 
200
                                 UV_UNIT_WIDTH)){
159
201
                    unum++;
160
202
                    ublocks[unum-1]=j;
161
203
                }
162
 
            }
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,
 
205
                                 yuv[prev].v,
 
206
                                 j,
 
207
                                 yuv[current].uv_width,
 
208
                                 yuv[current].uv_height,
 
209
                                 UV_UNIT_WIDTH)){
165
210
                    vnum++;
166
211
                    vblocks[vnum-1]=j;
167
212
                }
170
215
        }
171
216
        /**WRITE FRAME TO DISK*/
172
217
        if(!pdata->args.zerocompression){
173
 
            if(ynum+unum+vnum>(pow(divisor,2)+pow(divisor/2,2)*2)/10)
 
218
            if(ynum*4+unum+vnum>(blocknum_x*blocknum_y*6)/10)
174
219
                gzsetparams (fp,1,Z_FILTERED);
175
220
            else
176
221
                gzsetparams (fp,0,Z_FILTERED);
179
224
        strncpy(fheader.frame_prefix,"FRAM",4);
180
225
        fheader.frameno=++frameno;
181
226
        fheader.current_total=frames_total;
 
227
 
182
228
        fheader.Ynum=ynum;
183
229
        fheader.Unum=unum;
184
230
        fheader.Vnum=vnum;
185
 
        fheader.pad=0;
186
231
        if(!pdata->args.zerocompression){
187
232
            nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader));
188
233
            //flush indexes
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);
192
237
        }
193
238
        else{
194
 
            nbytes+=sizeof(FrameHeader)*fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp);
 
239
            nbytes+=sizeof(FrameHeader)*
 
240
                    fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp);
195
241
            //flush indexes
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);
199
248
        }
200
249
        //flush the blocks for each buffer
201
 
        if(ynum)
 
250
        if(ynum){
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,
206
 
                                    divisor,
 
255
                                    Y_UNIT_WIDTH,
207
256
                                    fp,
208
 
                                    ucfp);
209
 
        if(unum)
 
257
                                    ucfp,
 
258
                                    0);
 
259
        }
 
260
        if(unum){
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,
214
 
                                    divisor/2,
 
265
                                    UV_UNIT_WIDTH,
215
266
                                    fp,
216
 
                                    ucfp);
217
 
        if(vnum)
 
267
                                    ucfp,
 
268
                                    0);
 
269
        }
 
270
        if(vnum){
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,
222
 
                                    divisor/2,
 
275
                                    UV_UNIT_WIDTH,
223
276
                                    fp,
224
 
                                    ucfp);
225
 
 
226
 
 
 
277
                                    ucfp,
 
278
                                    0);
 
279
        }
 
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");
232
288
                fflush(stderr);
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,
 
291
                                //which means
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
239
297
                                //clean exit.
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.
242
301
            }
243
302
            nth_cache++;
244
303
            nbytes=0;
245
304
        }
246
305
    }
247
 
 
248
306
    //clean up since we're not finished
249
307
    for(i=0;i<2;i++){
250
308
        free(yuv[i].y);
251
309
        free(yuv[i].u);
252
310
        free(yuv[i].v);
253
311
    }
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);
257
316
        gzclose(fp);