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

« back to all changes in this revision

Viewing changes to src/rmd_load_cache.c

  • Committer: Bazaar Package Importer
  • Author(s): Alan Pope
  • Date: 2009-04-21 10:57:22 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20090421105722-w6l4gz958gva15wn
Tags: 0.3.8.1-0ubuntu1
* New upstream release (LP: #364674)
* debian/control: Fixed libjack0.100.0-dev dependancy
* debian/control: Fixed project home page

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
*                            recordMyDesktop                                  *
 
3
*******************************************************************************
 
4
*                                                                             *
 
5
*            Copyright (C) 2006,2007,2008 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
 
 
27
#include "config.h"
 
28
#include "rmd_load_cache.h"
 
29
 
 
30
#include "rmd_cache.h"
 
31
#include "rmd_encode_image_buffer.h"
 
32
#include "rmd_encode_sound_buffer.h"
 
33
#include "rmd_macro.h"
 
34
#include "rmd_types.h"
 
35
 
 
36
#include <pthread.h>
 
37
#include <signal.h>
 
38
 
 
39
#include <stdio.h>
 
40
#include <stdlib.h>
 
41
#include <string.h>
 
42
 
 
43
 
 
44
//The number of bytes for every
 
45
//sub-block of the y,u and v planes.
 
46
//Since the blocks are square
 
47
//these are obviously the squares
 
48
//of the widths(specified above),
 
49
//but the definitions bellow are only
 
50
//for convenience anyway.
 
51
#define Y_UNIT_BYTES    0x0100
 
52
#define UV_UNIT_BYTES   0x0040
 
53
 
 
54
 
 
55
//The frame after retrieval.
 
56
//Based on the Header information
 
57
//we can read the correct amount of bytes.
 
58
typedef struct _CachedFrame{
 
59
    FrameHeader *header;
 
60
    u_int32_t     *YBlocks,     //identifying number on the grid,
 
61
                  *UBlocks,     //starting at top left
 
62
                  *VBlocks;     //       >>      >>
 
63
    unsigned char *YData,   //pointer to data for the blocks that have changed,
 
64
                  *UData,   //which have to be remapped
 
65
                  *VData;   //on the buffer when reading
 
66
}CachedFrame;
 
67
 
 
68
 
 
69
static void LoadBlock(unsigned char *dest,
 
70
                      unsigned char *source,
 
71
                      int blockno,
 
72
                      int width,
 
73
                      int height,
 
74
                      int blockwidth) {
 
75
    int j,
 
76
        block_i=blockno/(width/blockwidth),//place on the grid
 
77
        block_k=blockno%(width/blockwidth);
 
78
    for(j=0;j<blockwidth;j++)//we copy rows
 
79
        memcpy( &dest[(block_i*width+block_k)*blockwidth+j*width],
 
80
                &source[j*blockwidth],
 
81
                blockwidth);
 
82
}
 
83
 
 
84
//returns number of bytes
 
85
static int ReadZF(void * buffer, size_t size, size_t nmemb, FILE *ucfp, gzFile *ifp) {
 
86
    if((ifp!=NULL && ucfp!=NULL)||
 
87
       (ifp==NULL && ucfp==NULL))
 
88
        return -1;
 
89
    else if(ucfp!=NULL){
 
90
        return (size*fread(buffer,size,nmemb,ucfp));
 
91
    }
 
92
    else
 
93
        return gzread(ifp,buffer,size*nmemb);
 
94
}
 
95
 
 
96
static int ReadFrame(CachedFrame *frame, FILE *ucfp, gzFile *ifp) {
 
97
    int index_entry_size=sizeof(u_int32_t);
 
98
    if(frame->header->Ynum>0){
 
99
        if(ReadZF(frame->YBlocks,
 
100
                index_entry_size,
 
101
                frame->header->Ynum,
 
102
                ucfp,
 
103
                ifp)!=index_entry_size*frame->header->Ynum){
 
104
            return -1;
 
105
        }
 
106
    }
 
107
    if(frame->header->Unum>0){
 
108
        if(ReadZF(frame->UBlocks,
 
109
                index_entry_size,
 
110
                frame->header->Unum,
 
111
                ucfp,
 
112
                ifp)!=index_entry_size*frame->header->Unum){
 
113
            return -1;
 
114
        }
 
115
    }
 
116
    if(frame->header->Vnum>0){
 
117
        if(ReadZF(frame->VBlocks,
 
118
                index_entry_size,
 
119
                frame->header->Vnum,
 
120
                ucfp,
 
121
                ifp)!=index_entry_size*frame->header->Vnum){
 
122
            return -1;
 
123
        }
 
124
    }
 
125
    if(frame->header->Ynum>0){
 
126
        if(ReadZF(frame->YData,
 
127
                  Y_UNIT_BYTES,
 
128
                  frame->header->Ynum,
 
129
                  ucfp,
 
130
                  ifp)!=Y_UNIT_BYTES*frame->header->Ynum){
 
131
            return -2;
 
132
        }
 
133
    }
 
134
    if(frame->header->Unum>0){
 
135
        if(ReadZF(frame->UData,
 
136
                  UV_UNIT_BYTES,
 
137
                  frame->header->Unum,
 
138
                  ucfp,
 
139
                  ifp)!=UV_UNIT_BYTES*frame->header->Unum){
 
140
            return -2;
 
141
        }
 
142
    }
 
143
    if(frame->header->Vnum>0){
 
144
        if(ReadZF(frame->VData,
 
145
                  UV_UNIT_BYTES,
 
146
                  frame->header->Vnum,
 
147
                  ucfp,
 
148
                  ifp)!=UV_UNIT_BYTES*frame->header->Vnum){
 
149
            return -2;
 
150
        }
 
151
    }
 
152
    return 0;
 
153
}
 
154
 
 
155
void *LoadCache(ProgData *pdata){
 
156
 
 
157
    yuv_buffer *yuv=&pdata->enc_data->yuv;
 
158
    gzFile *ifp=NULL;
 
159
    FILE *ucfp=NULL;
 
160
    FILE *afp=pdata->cache_data->afp;
 
161
    FrameHeader fheader;
 
162
    CachedFrame frame;
 
163
    int j=0,
 
164
        nth_cache=1,
 
165
        audio_end=0,
 
166
        extra_frames=0,//total number of duplicated frames
 
167
        missing_frames=0,//if this is found >0 current run will not load
 
168
                        //a frame but it will proccess the previous
 
169
        thread_exit=0,//0 success, -1 couldn't find files,1 couldn't remove
 
170
        blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
 
171
        blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH,
 
172
        blockszy=Y_UNIT_BYTES,//size of y plane block in bytes
 
173
        blockszuv=UV_UNIT_BYTES;//size of u,v plane blocks in bytes
 
174
    signed char *sound_data=(signed char *)malloc(pdata->periodsize*
 
175
                                                  pdata->sound_framesize);
 
176
 
 
177
    u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES],
 
178
              UBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES],
 
179
              VBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES];
 
180
 
 
181
    // We allocate the frame that we will use
 
182
    frame.header  = &fheader;
 
183
    frame.YBlocks = YBlocks;
 
184
    frame.UBlocks = UBlocks;
 
185
    frame.VBlocks = VBlocks;
 
186
    frame.YData   = malloc(yuv->y_width  * yuv->y_height);
 
187
    frame.UData   = malloc(yuv->uv_width * yuv->uv_height);
 
188
    frame.VData   = malloc(yuv->uv_width * yuv->uv_height);
 
189
 
 
190
    //and the we open our files
 
191
    if(!pdata->args.zerocompression){
 
192
        ifp=gzopen(pdata->cache_data->imgdata,"rb");
 
193
        if(ifp==NULL){
 
194
            thread_exit=-1;
 
195
            pthread_exit(&thread_exit);
 
196
        }
 
197
    }
 
198
    else{
 
199
        ucfp=fopen(pdata->cache_data->imgdata,"rb");
 
200
        if(ucfp==NULL){
 
201
            thread_exit=-1;
 
202
            pthread_exit(&thread_exit);
 
203
        }
 
204
    }
 
205
 
 
206
 
 
207
    if(!pdata->args.nosound){
 
208
        afp=fopen(pdata->cache_data->audiodata,"rb");
 
209
        if(afp==NULL){
 
210
            thread_exit=-1;
 
211
            pthread_exit(&thread_exit);
 
212
        }
 
213
    }
 
214
 
 
215
    //this will be used now to define if we proccess audio or video
 
216
    //on any given loop.
 
217
    pdata->avd=0;
 
218
    //If sound finishes first,we go on with the video.
 
219
    //If video ends we will do one more run to flush audio in the ogg file
 
220
    while(pdata->running){
 
221
        //video load and encoding
 
222
        if(pdata->avd<=0 || pdata->args.nosound || audio_end){
 
223
            if(missing_frames>0){
 
224
                extra_frames++;
 
225
                missing_frames--;
 
226
                SyncEncodeImageBuffer(pdata);
 
227
            }
 
228
            else if(((!pdata->args.zerocompression)&&
 
229
                     (gzread(ifp,frame.header,sizeof(FrameHeader))==
 
230
                      sizeof(FrameHeader) ))||
 
231
                    ((pdata->args.zerocompression)&&
 
232
                    (fread(frame.header,sizeof(FrameHeader),1,ucfp)==1))){
 
233
                //sync
 
234
                missing_frames+=frame.header->current_total-
 
235
                                (extra_frames+frame.header->frameno);
 
236
                if (pdata->frames_total) {
 
237
                    fprintf(stdout,
 
238
                            "\r[%d%%] ",
 
239
                            ((frame.header->frameno + extra_frames) * 100) / pdata->frames_total);
 
240
                }
 
241
                else
 
242
                    fprintf(stdout,"\r[%d frames rendered] ",
 
243
                            (frame.header->frameno+extra_frames));
 
244
                fflush(stdout);
 
245
                if( (frame.header->Ynum<=blocknum_x*blocknum_y) &&
 
246
                    (frame.header->Unum<=blocknum_x*blocknum_y) &&
 
247
                    (frame.header->Vnum<=blocknum_x*blocknum_y) &&
 
248
                    (!ReadFrame(&frame,
 
249
                                ((pdata->args.zerocompression)?ucfp:NULL),
 
250
                                ((pdata->args.zerocompression)?NULL:ifp)))
 
251
                        ){
 
252
                        //load the blocks for each buffer
 
253
                        if(frame.header->Ynum)
 
254
                            for(j=0;j<frame.header->Ynum;j++)
 
255
                                LoadBlock(  yuv->y,
 
256
                                            &frame.YData[j*blockszy],
 
257
                                            frame.YBlocks[j],
 
258
                                            yuv->y_width,
 
259
                                            yuv->y_height,
 
260
                                            Y_UNIT_WIDTH);
 
261
                        if(frame.header->Unum)
 
262
                            for(j=0;j<frame.header->Unum;j++)
 
263
                                LoadBlock(  yuv->u,
 
264
                                            &frame.UData[j*blockszuv],
 
265
                                            frame.UBlocks[j],
 
266
                                            yuv->uv_width,
 
267
                                            yuv->uv_height,
 
268
                                            UV_UNIT_WIDTH);
 
269
                        if(frame.header->Vnum)
 
270
                            for(j=0;j<frame.header->Vnum;j++)
 
271
                                LoadBlock(  yuv->v,
 
272
                                            &frame.VData[j*blockszuv],
 
273
                                            frame.VBlocks[j],
 
274
                                            yuv->uv_width,
 
275
                                            yuv->uv_height,
 
276
                                            UV_UNIT_WIDTH);
 
277
                        //encode. This is not made in a thread since
 
278
                        //now blocking is not a problem
 
279
                        //and this way sync problems
 
280
                        //can be avoided more easily.
 
281
                        SyncEncodeImageBuffer(pdata);
 
282
                }
 
283
                else{
 
284
                    raise(SIGINT);
 
285
                    continue;
 
286
                }
 
287
            }
 
288
            else{
 
289
                if(SwapCacheFilesRead(pdata->cache_data->imgdata,
 
290
                                      nth_cache,
 
291
                                      &ifp,
 
292
                                      &ucfp)){
 
293
                    raise(SIGINT);
 
294
                }
 
295
                else{
 
296
                    fprintf(stderr,"\t[Cache File %d]",nth_cache);
 
297
                    nth_cache++;
 
298
                }
 
299
                continue;
 
300
            }
 
301
        }
 
302
        //audio load and encoding
 
303
        else{
 
304
            if(!audio_end){
 
305
                int nbytes=fread(sound_data,1,pdata->periodsize*
 
306
                                 pdata->sound_framesize,afp);
 
307
                if(nbytes<=0)
 
308
                    audio_end=1;
 
309
                else
 
310
                    SyncEncodeSoundBuffer(pdata,sound_data);
 
311
            }
 
312
        }
 
313
    }
 
314
 
 
315
    pdata->v_encoding_clean=pdata->th_encoding_clean=1;
 
316
    pthread_mutex_lock(&pdata->theora_lib_mutex);
 
317
    pthread_cond_signal(&pdata->theora_lib_clean);
 
318
    pthread_mutex_unlock(&pdata->theora_lib_mutex);
 
319
    pthread_mutex_lock(&pdata->vorbis_lib_mutex);
 
320
    pthread_cond_signal(&pdata->vorbis_lib_clean);
 
321
    pthread_mutex_unlock(&pdata->vorbis_lib_mutex);
 
322
    fprintf(stdout,"\n");
 
323
 
 
324
    // Clear frame
 
325
    free(frame.YData);
 
326
    free(frame.UData);
 
327
    free(frame.VData);
 
328
 
 
329
    free(sound_data);
 
330
 
 
331
    if(!pdata->args.nosound){
 
332
        fclose(afp);
 
333
    }
 
334
 
 
335
    pthread_exit(&thread_exit);
 
336
 
 
337
 
 
338
}
 
339