1
/******************************************************************************
3
*******************************************************************************
5
* Copyright (C) 2006,2007,2008 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
******************************************************************************/
28
#include <recordmydesktop.h>
30
void LoadBlock(unsigned char *dest,
31
unsigned char *source,
37
block_i=blockno/(width/blockwidth),//place on the grid
38
block_k=blockno%(width/blockwidth);
39
for(j=0;j<blockwidth;j++)//we copy rows
40
memcpy( &dest[(block_i*width+block_k)*blockwidth+j*width],
41
&source[j*blockwidth],
45
//returns number of bytes
46
int ReadZF(void * buffer,size_t size,size_t nmemb,FILE *ucfp,gzFile *ifp){
47
if((ifp!=NULL && ucfp!=NULL)||
48
(ifp==NULL && ucfp==NULL))
51
return (size*fread(buffer,size,nmemb,ucfp));
54
return gzread(ifp,buffer,size*nmemb);
57
int ReadFrame(CachedFrame *frame,FILE *ucfp,gzFile *ifp){
58
int index_entry_size=sizeof(u_int32_t);
59
if(frame->header->Ynum>0){
60
if(ReadZF(frame->YBlocks,
64
ifp)!=index_entry_size*frame->header->Ynum){
68
if(frame->header->Unum>0){
69
if(ReadZF(frame->UBlocks,
73
ifp)!=index_entry_size*frame->header->Unum){
77
if(frame->header->Vnum>0){
78
if(ReadZF(frame->VBlocks,
82
ifp)!=index_entry_size*frame->header->Vnum){
86
if(frame->header->Ynum>0){
87
if(ReadZF(frame->YData,
91
ifp)!=Y_UNIT_BYTES*frame->header->Ynum){
95
if(frame->header->Unum>0){
96
if(ReadZF(frame->UData,
100
ifp)!=UV_UNIT_BYTES*frame->header->Unum){
104
if(frame->header->Vnum>0){
105
if(ReadZF(frame->VData,
109
ifp)!=UV_UNIT_BYTES*frame->header->Vnum){
116
void *LoadCache(ProgData *pdata){
118
yuv_buffer *yuv=&pdata->enc_data->yuv;
121
FILE *afp=pdata->cache_data->afp;
127
extra_frames=0,//total number of duplicated frames
128
missing_frames=0,//if this is found >0 current run will not load
129
//a frame but it will proccess the previous
130
thread_exit=0,//0 success, -1 couldn't find files,1 couldn't remove
131
blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
132
blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH,
133
blockszy=Y_UNIT_BYTES,//size of y plane block in bytes
134
blockszuv=UV_UNIT_BYTES;//size of u,v plane blocks in bytes
135
signed char *sound_data=(signed char *)malloc(pdata->periodsize*
136
pdata->sound_framesize);
138
u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES],
139
UBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES],
140
VBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES];
141
//we allocate the frame that we will use
142
INIT_FRAME(&frame,&fheader,yuv,
143
YBlocks,UBlocks,VBlocks);
144
//and the we open our files
145
if(!pdata->args.zerocompression){
146
ifp=gzopen(pdata->cache_data->imgdata,"rb");
149
pthread_exit(&thread_exit);
153
ucfp=fopen(pdata->cache_data->imgdata,"rb");
156
pthread_exit(&thread_exit);
161
if(!pdata->args.nosound){
162
afp=fopen(pdata->cache_data->audiodata,"rb");
165
pthread_exit(&thread_exit);
169
//this will be used now to define if we proccess audio or video
172
//If sound finishes first,we go on with the video.
173
//If video ends we will do one more run to flush audio in the ogg file
174
while(pdata->running){
175
//video load and encoding
176
if(pdata->avd<=0 || pdata->args.nosound || audio_end){
177
if(missing_frames>0){
180
SyncEncodeImageBuffer(pdata);
182
else if(((!pdata->args.zerocompression)&&
183
(gzread(ifp,frame.header,sizeof(FrameHeader))==
184
sizeof(FrameHeader) ))||
185
((pdata->args.zerocompression)&&
186
(fread(frame.header,sizeof(FrameHeader),1,ucfp)==1))){
188
missing_frames+=frame.header->current_total-
189
(extra_frames+frame.header->frameno);
191
fprintf(stdout,"\r[%d%%] ",
192
((frame.header->frameno+extra_frames)*100)/frames_total);
194
fprintf(stdout,"\r[%d frames rendered] ",
195
(frame.header->frameno+extra_frames));
197
if( (frame.header->Ynum<=blocknum_x*blocknum_y) &&
198
(frame.header->Unum<=blocknum_x*blocknum_y) &&
199
(frame.header->Vnum<=blocknum_x*blocknum_y) &&
201
((pdata->args.zerocompression)?ucfp:NULL),
202
((pdata->args.zerocompression)?NULL:ifp)))
204
//load the blocks for each buffer
205
if(frame.header->Ynum)
206
for(j=0;j<frame.header->Ynum;j++)
208
&frame.YData[j*blockszy],
213
if(frame.header->Unum)
214
for(j=0;j<frame.header->Unum;j++)
216
&frame.UData[j*blockszuv],
221
if(frame.header->Vnum)
222
for(j=0;j<frame.header->Vnum;j++)
224
&frame.VData[j*blockszuv],
229
//encode. This is not made in a thread since
230
//now blocking is not a problem
231
//and this way sync problems
232
//can be avoided more easily.
233
SyncEncodeImageBuffer(pdata);
241
if(SwapCacheFilesRead(pdata->cache_data->imgdata,
248
fprintf(stderr,"\t[Cache File %d]",nth_cache);
254
//audio load and encoding
257
int nbytes=fread(sound_data,1,pdata->periodsize*
258
pdata->sound_framesize,afp);
262
SyncEncodeSoundBuffer(pdata,sound_data);
267
pdata->v_encoding_clean=pdata->th_encoding_clean=1;
268
pthread_mutex_lock(&pdata->theora_lib_mutex);
269
pthread_cond_signal(&pdata->theora_lib_clean);
270
pthread_mutex_unlock(&pdata->theora_lib_mutex);
271
pthread_mutex_lock(&pdata->vorbis_lib_mutex);
272
pthread_cond_signal(&pdata->vorbis_lib_clean);
273
pthread_mutex_unlock(&pdata->vorbis_lib_mutex);
274
fprintf(stdout,"\n");
278
if(!pdata->args.nosound){
282
pthread_exit(&thread_exit);