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_cache_frame.h"
30
#include "rmd_yuv_utils.h"
31
#include "rmd_cache.h"
32
#include "rmd_types.h"
41
#define BYTES_PER_MB (1024 * 1024)
42
#define CACHE_OUT_BUFFER_SIZE (4 * 1024)
43
#define CACHE_FILE_SIZE_LIMIT (500 * 1024 * 1024)
46
static int FlushBlock(unsigned char *buf,
56
block_i=(!blockwidth)?0:(blockno/(width/blockwidth)),//place on the grid
57
block_k=(!blockwidth)?0:(blockno%(width/blockwidth));
58
register unsigned char *buf_reg=(&buf[(block_i*
60
block_k)*blockwidth]);
61
static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE];
62
static unsigned int out_buffer_bytes=0;
64
if(out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE ||
65
(flush && out_buffer_bytes)){
67
gzwrite(fp,(void *)out_buffer,out_buffer_bytes);
69
fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp);
70
bytes_written=out_buffer_bytes;
74
register unsigned char *out_buf_reg=&out_buffer[out_buffer_bytes];
75
for(j=0;j<blockwidth;j++){
76
for(i=0;i<blockwidth;i++)
77
(*out_buf_reg++)=(*buf_reg++);
78
out_buffer_bytes+=blockwidth;
79
buf_reg+=width-blockwidth;
86
void *CacheImageBuffer(ProgData *pdata){
90
int index_entry_size=sizeof(u_int32_t),
91
blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH,
92
blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH,
97
u_int32_t ynum,unum,vnum,
98
y_short_blocks[blocknum_x*blocknum_y],
99
u_short_blocks[blocknum_x*blocknum_y],
100
v_short_blocks[blocknum_x*blocknum_y];
101
unsigned long long int total_bytes = 0;
102
unsigned long long int total_received_bytes = 0;
104
if(!pdata->args.zerocompression){
105
fp=pdata->cache_data->ifp;
106
if(fp==NULL)exit(13);
109
ucfp=pdata->cache_data->uncifp;
110
if(ucfp==NULL)exit(13);
114
while(pdata->running){
119
pdata->th_enc_thread_waiting=1;
120
pthread_mutex_lock(&pdata->img_buff_ready_mutex);
121
pthread_cond_wait(&pdata->image_buffer_ready,
122
&pdata->img_buff_ready_mutex);
123
pthread_mutex_unlock(&pdata->img_buff_ready_mutex);
124
pdata->th_enc_thread_waiting=0;
127
pthread_mutex_lock(&pdata->pause_mutex);
128
pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex);
129
pthread_mutex_unlock(&pdata->pause_mutex);
132
pthread_mutex_lock(&pdata->yuv_mutex);
134
//find and flush different blocks
137
for(j=0;j<blocknum_x*blocknum_y;j++){
140
y_short_blocks[ynum-1]=j;
143
u_short_blocks[ynum-1]=j;
146
v_short_blocks[ynum-1]=j;
151
for(j=0;j<blocknum_x*blocknum_y;j++){
154
y_short_blocks[ynum-1]=j;
158
u_short_blocks[unum-1]=j;
162
v_short_blocks[vnum-1]=j;
167
/**WRITE FRAME TO DISK*/
168
if(!pdata->args.zerocompression){
169
if(ynum*4+unum+vnum>(blocknum_x*blocknum_y*6)/10)
170
gzsetparams (fp,1,Z_FILTERED);
172
gzsetparams (fp,0,Z_FILTERED);
175
strncpy(fheader.frame_prefix,"FRAM",4);
176
fheader.frameno=++frameno;
177
fheader.current_total = pdata->frames_total;
182
if(!pdata->args.zerocompression){
183
nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader));
185
if(ynum)nbytes+=gzwrite(fp,
186
(void*)y_short_blocks,
187
ynum*index_entry_size);
188
if(unum)nbytes+=gzwrite(fp,
189
(void*)u_short_blocks,
190
unum*index_entry_size);
191
if(vnum)nbytes+=gzwrite(fp,
192
(void*)v_short_blocks,
193
vnum*index_entry_size);
196
nbytes+=sizeof(FrameHeader)*
197
fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp);
199
if(ynum)nbytes+=index_entry_size*
200
fwrite(y_short_blocks,index_entry_size,ynum,ucfp);
201
if(unum)nbytes+=index_entry_size*
202
fwrite(u_short_blocks,index_entry_size,unum,ucfp);
203
if(vnum)nbytes+=index_entry_size*
204
fwrite(v_short_blocks,index_entry_size,vnum,ucfp);
206
//flush the blocks for each buffer
209
nbytes+=FlushBlock( pdata->enc_data->yuv.y,y_short_blocks[j],
210
pdata->enc_data->yuv.y_width,
211
pdata->enc_data->yuv.y_height,
219
nbytes+=FlushBlock( pdata->enc_data->yuv.u,u_short_blocks[j],
220
pdata->enc_data->yuv.uv_width,
221
pdata->enc_data->yuv.uv_height,
229
nbytes+=FlushBlock( pdata->enc_data->yuv.v,v_short_blocks[j],
230
pdata->enc_data->yuv.uv_width,
231
pdata->enc_data->yuv.uv_height,
237
//release main buffer
238
pthread_mutex_unlock(&pdata->yuv_mutex);
240
nbytes+=FlushBlock(NULL,0,0,0,0,fp,ucfp,1);
241
/**@________________@**/
242
pdata->avd+=pdata->frametime;
243
if(nbytes>CACHE_FILE_SIZE_LIMIT){
244
if(SwapCacheFilesWrite(pdata->cache_data->imgdata,
245
nth_cache,&fp,&ucfp)){
246
fprintf(stderr,"New cache file could not be created.\n"
247
"Ending recording...\n");
249
raise(SIGINT); //if for some reason we cannot make a new file
250
//we have to stop. If we are out of space,
252
//that encoding cannot happen either,
253
//InitEncoder will cause an abrupt end with an
254
//error code and the cache will remain intact.
255
//If we've chosen separate two-stages,
256
//the program will make a
258
//In either case data will be preserved so if
259
//space is freed the recording
260
//can be proccessed later.
262
total_bytes += nbytes;
267
total_bytes += nbytes;
270
unsigned int bytes_per_pixel = pdata->specs.depth >= 24 ? 4 : 2;
271
unsigned int pixels_per_frame = pdata->brwin.rrect.width * pdata->brwin.rrect.height;
273
total_received_bytes = ((unsigned int)frameno) * bytes_per_pixel * pixels_per_frame;
276
if(total_received_bytes){
277
double percent_of_data_left = (total_bytes / (double)total_received_bytes) * 100;
281
"*********************************************\n"
283
"Cached %llu MB, from %llu MB that were received.\n"
284
"Average cache compression ratio: %.1f %%\n"
286
"*********************************************\n",
287
total_bytes / BYTES_PER_MB,
288
total_received_bytes / BYTES_PER_MB,
289
100 - percent_of_data_left);
294
"Saved %d frames in a total of %d requests\n",
296
pdata->frames_total);
299
if(!pdata->args.zerocompression){
300
gzflush(fp,Z_FINISH);
307
pthread_exit(&errno);