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 "rmd_load_cache.h"
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"
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
55
//The frame after retrieval.
56
//Based on the Header information
57
//we can read the correct amount of bytes.
58
typedef struct _CachedFrame{
60
u_int32_t *YBlocks, //identifying number on the grid,
61
*UBlocks, //starting at top left
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
69
static void LoadBlock(unsigned char *dest,
70
unsigned char *source,
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],
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))
90
return (size*fread(buffer,size,nmemb,ucfp));
93
return gzread(ifp,buffer,size*nmemb);
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,
103
ifp)!=index_entry_size*frame->header->Ynum){
107
if(frame->header->Unum>0){
108
if(ReadZF(frame->UBlocks,
112
ifp)!=index_entry_size*frame->header->Unum){
116
if(frame->header->Vnum>0){
117
if(ReadZF(frame->VBlocks,
121
ifp)!=index_entry_size*frame->header->Vnum){
125
if(frame->header->Ynum>0){
126
if(ReadZF(frame->YData,
130
ifp)!=Y_UNIT_BYTES*frame->header->Ynum){
134
if(frame->header->Unum>0){
135
if(ReadZF(frame->UData,
139
ifp)!=UV_UNIT_BYTES*frame->header->Unum){
143
if(frame->header->Vnum>0){
144
if(ReadZF(frame->VData,
148
ifp)!=UV_UNIT_BYTES*frame->header->Vnum){
155
void *LoadCache(ProgData *pdata){
157
yuv_buffer *yuv=&pdata->enc_data->yuv;
160
FILE *afp=pdata->cache_data->afp;
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);
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];
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);
190
//and the we open our files
191
if(!pdata->args.zerocompression){
192
ifp=gzopen(pdata->cache_data->imgdata,"rb");
195
pthread_exit(&thread_exit);
199
ucfp=fopen(pdata->cache_data->imgdata,"rb");
202
pthread_exit(&thread_exit);
207
if(!pdata->args.nosound){
208
afp=fopen(pdata->cache_data->audiodata,"rb");
211
pthread_exit(&thread_exit);
215
//this will be used now to define if we proccess audio or video
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){
226
SyncEncodeImageBuffer(pdata);
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))){
234
missing_frames+=frame.header->current_total-
235
(extra_frames+frame.header->frameno);
236
if (pdata->frames_total) {
239
((frame.header->frameno + extra_frames) * 100) / pdata->frames_total);
242
fprintf(stdout,"\r[%d frames rendered] ",
243
(frame.header->frameno+extra_frames));
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) &&
249
((pdata->args.zerocompression)?ucfp:NULL),
250
((pdata->args.zerocompression)?NULL:ifp)))
252
//load the blocks for each buffer
253
if(frame.header->Ynum)
254
for(j=0;j<frame.header->Ynum;j++)
256
&frame.YData[j*blockszy],
261
if(frame.header->Unum)
262
for(j=0;j<frame.header->Unum;j++)
264
&frame.UData[j*blockszuv],
269
if(frame.header->Vnum)
270
for(j=0;j<frame.header->Vnum;j++)
272
&frame.VData[j*blockszuv],
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);
289
if(SwapCacheFilesRead(pdata->cache_data->imgdata,
296
fprintf(stderr,"\t[Cache File %d]",nth_cache);
302
//audio load and encoding
305
int nbytes=fread(sound_data,1,pdata->periodsize*
306
pdata->sound_framesize,afp);
310
SyncEncodeSoundBuffer(pdata,sound_data);
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");
331
if(!pdata->args.nosound){
335
pthread_exit(&thread_exit);