00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "condition.h"
00004 #include "file.h"
00005 #include "filethread.h"
00006 #include "mutex.h"
00007 #include "vframe.h"
00008
00009 #include <unistd.h>
00010
00011 FileThread::FileThread(File *file, int do_audio, int do_video)
00012 : Thread(1, 0, 0)
00013 {
00014 reset();
00015 create_objects(file,
00016 do_audio,
00017 do_video);
00018 }
00019
00020 FileThread::~FileThread()
00021 {
00022 delete_objects();
00023
00024
00025
00026 delete file_lock;
00027 }
00028
00029 void FileThread::reset()
00030 {
00031 audio_buffer = 0;
00032 video_buffer = 0;
00033 output_size = 0;
00034 input_lock = 0;
00035 output_lock = 0;
00036 last_buffer = 0;
00037 }
00038
00039
00040 void FileThread::create_objects(File *file,
00041 int do_audio,
00042 int do_video)
00043 {
00044 this->file = file;
00045 this->do_audio = do_audio;
00046 this->do_video = do_video;
00047 file_lock = new Mutex("FileThread::file_lock");
00048 }
00049
00050
00051 void FileThread::delete_objects()
00052 {
00053 if(output_lock)
00054 {
00055 for(int i = 0; i < ring_buffers; i++)
00056 {
00057 delete output_lock[i];
00058 }
00059 delete [] output_lock;
00060 }
00061
00062 if(input_lock)
00063 {
00064 for(int i = 0; i < ring_buffers; i++)
00065 {
00066 delete input_lock[i];
00067 }
00068 delete [] input_lock;
00069 }
00070
00071
00072 if(last_buffer)
00073 delete [] last_buffer;
00074
00075
00076 delete [] output_size;
00077
00078 reset();
00079 }
00080
00081 void FileThread::run()
00082 {
00083 int done = 0;
00084 int i, j, result;
00085
00086 while(!done)
00087 {
00088 output_lock[local_buffer]->lock("FileThread::run 1");
00089 return_value = 0;
00090
00091
00092
00093
00094 if(!last_buffer[local_buffer])
00095 {
00096 if(output_size[local_buffer])
00097 {
00098 file_lock->lock("FileThread::run 2");
00099 if(do_audio)
00100 {
00101 TRACE("FileThread::run 4");
00102 result = file->write_samples(audio_buffer[local_buffer],
00103 output_size[local_buffer]);
00104 TRACE("FileThread::run 5");
00105 }
00106 else
00107 if(do_video)
00108 {
00109 result = 0;
00110 if(compressed)
00111 {
00112 for(j = 0; j < file->asset->layers && !result; j++)
00113 for(i = 0; i < output_size[local_buffer] && !result; i++)
00114 result = file->write_compressed_frame(video_buffer[local_buffer][j][i]);
00115 }
00116 else
00117 {
00118 result = file->write_frames(video_buffer[local_buffer],
00119 output_size[local_buffer]);
00120 }
00121 }
00122
00123 file_lock->unlock();
00124 return_value = result;
00125 }
00126 else
00127 return_value = 0;
00128
00129 output_size[local_buffer] = 0;
00130 }
00131 else
00132 done = 1;
00133
00134 input_lock[local_buffer]->unlock();
00135 local_buffer++;
00136 if(local_buffer >= ring_buffers) local_buffer = 0;
00137 }
00138 }
00139
00140
00141
00142 int FileThread::stop_writing()
00143 {
00144
00145 int i, buffer, layer, frame;
00146
00147 swap_buffer();
00148 input_lock[current_buffer]->lock("FileThread::stop_writing 1");
00149
00150 last_buffer[current_buffer] = 1;
00151
00152 for(i = 0; i < ring_buffers; i++)
00153 output_lock[i]->unlock();
00154
00155 swap_buffer();
00156
00157
00158 Thread::join();
00159
00160
00161 file_lock->lock("FileThread::stop_writing 2");
00162 if(do_audio)
00163 {
00164 for(buffer = 0; buffer < ring_buffers; buffer++)
00165 {
00166 for(i = 0; i < file->asset->channels; i++)
00167 delete [] audio_buffer[buffer][i];
00168 delete [] audio_buffer[buffer];
00169 }
00170 delete [] audio_buffer;
00171 audio_buffer = 0;
00172 }
00173
00174
00175
00176
00177
00178
00179 if(do_video)
00180 {
00181 for(buffer = 0; buffer < ring_buffers; buffer++)
00182 {
00183 for(layer = 0; layer < file->asset->layers; layer++)
00184 {
00185 for(frame = 0; frame < buffer_size; frame++)
00186 {
00187 delete video_buffer[buffer][layer][frame];
00188 }
00189 delete [] video_buffer[buffer][layer];
00190 }
00191 delete [] video_buffer[buffer];
00192 }
00193 delete [] video_buffer;
00194 video_buffer = 0;
00195 }
00196
00197 file_lock->unlock();
00198 return 0;
00199 }
00200
00201 int FileThread::start_writing(long buffer_size,
00202 int color_model,
00203 int ring_buffers,
00204 int compressed)
00205 {
00206
00207 int buffer, layer, frame;
00208 long bytes_per_frame;
00209
00210 this->ring_buffers = ring_buffers;
00211 this->buffer_size = buffer_size;
00212 this->color_model = color_model;
00213 this->compressed = compressed;
00214 this->current_buffer = ring_buffers - 1;
00215 return_value = 0;
00216 local_buffer = 0;
00217
00218 file_lock->lock("FileThread::start_writing 1");
00219
00220
00221
00222
00223
00224 last_buffer = new int[ring_buffers];
00225 output_size = new long[ring_buffers];
00226
00227
00228 output_lock = new Condition*[ring_buffers];
00229 input_lock = new Condition*[ring_buffers];
00230 for(int i = 0; i < ring_buffers; i++)
00231 {
00232 output_lock[i] = new Condition(0, "FileThread::output_lock");
00233 input_lock[i] = new Condition(1, "FileThread::input_lock");
00234 last_buffer[i] = 0;
00235 output_size[i] = 0;
00236 }
00237
00238
00239
00240 if(do_audio)
00241 {
00242 audio_buffer = new double**[ring_buffers];
00243 for(buffer = 0; buffer < ring_buffers; buffer++)
00244 {
00245 audio_buffer[buffer] = new double*[file->asset->channels];
00246
00247 for(int channel = 0; channel < file->asset->channels; channel++)
00248 {
00249 audio_buffer[buffer][channel] = new double[buffer_size];
00250 }
00251 }
00252 }
00253
00254 if(do_video)
00255 {
00256 this->color_model = color_model;
00257 bytes_per_frame = VFrame::calculate_data_size(file->asset->width,
00258 file->asset->height,
00259 -1,
00260 color_model);
00261
00262 video_buffer = new VFrame***[ring_buffers];
00263
00264
00265
00266
00267
00268 for(buffer = 0; buffer < ring_buffers; buffer++)
00269 {
00270 video_buffer[buffer] = new VFrame**[file->asset->layers];
00271 for(layer = 0; layer < file->asset->layers; layer++)
00272 {
00273 video_buffer[buffer][layer] = new VFrame*[buffer_size];
00274 for(frame = 0; frame < buffer_size; frame++)
00275 {
00276 if(compressed)
00277 video_buffer[buffer][layer][frame] = new VFrame;
00278 else
00279 {
00280 video_buffer[buffer][layer][frame] =
00281 new VFrame(0,
00282 file->asset->width,
00283 file->asset->height,
00284 color_model);
00285
00286
00287
00288
00289
00290 }
00291 }
00292 }
00293 }
00294 }
00295 file_lock->unlock();
00296
00297 for(int i = 0; i < ring_buffers; i++)
00298 {
00299 last_buffer[i] = 0;
00300 }
00301
00302
00303 start();
00304 return 0;
00305 }
00306
00307 double** FileThread::get_audio_buffer()
00308 {
00309 swap_buffer();
00310
00311 input_lock[current_buffer]->lock("FileThread::get_audio_buffer");
00312 return audio_buffer[current_buffer];
00313 }
00314
00315 VFrame*** FileThread::get_video_buffer()
00316 {
00317 swap_buffer();
00318
00319 input_lock[current_buffer]->lock("FileThread::get_video_buffer");
00320 return video_buffer[current_buffer];
00321 }
00322
00323 int FileThread::write_buffer(long size)
00324 {
00325 output_size[current_buffer] = size;
00326
00327
00328 output_lock[current_buffer]->unlock();
00329
00330 return return_value;
00331 }
00332
00333 int FileThread::swap_buffer()
00334 {
00335 current_buffer++;
00336 if(current_buffer >= ring_buffers) current_buffer = 0;
00337 }