00001 #include "asset.h"
00002 #include "audiodevice.h"
00003 #include "batch.h"
00004 #include "bcsignals.h"
00005 #include "condition.h"
00006 #include "drivesync.h"
00007 #include "edl.h"
00008 #include "edlsession.h"
00009 #include "file.h"
00010 #include "mutex.h"
00011 #include "mwindow.h"
00012 #include "record.h"
00013 #include "recordaudio.h"
00014 #include "recordgui.h"
00015 #include "recordthread.h"
00016 #include "recordvideo.h"
00017 #include "bctimer.h"
00018 #include "videodevice.h"
00019
00020
00021
00022 #define RING_BUFFERS 2
00023
00024
00025 RecordThread::RecordThread(MWindow *mwindow, Record *record)
00026 : Thread(1, 0, 0)
00027 {
00028 this->mwindow = mwindow;
00029 this->record = record;
00030 quit_when_completed = 0;
00031 record_timer = new Timer;
00032 record_audio = 0;
00033 record_video = 0;
00034 pause_lock = new Condition(1, "RecordThread::pause_lock");
00035 startup_lock = new Condition(1, "RecordThread::startup_lock");
00036 loop_lock = new Condition(1, "RecordThread::loop_lock");
00037 state_lock = new Mutex("RecordThread::state_lock");
00038 }
00039
00040 RecordThread::~RecordThread()
00041 {
00042 SET_TRACE
00043 delete record_audio;
00044 SET_TRACE
00045 delete record_video;
00046 SET_TRACE
00047 delete record_timer;
00048 SET_TRACE
00049 delete pause_lock;
00050 SET_TRACE
00051 delete startup_lock;
00052 SET_TRACE
00053 delete loop_lock;
00054 SET_TRACE
00055 delete state_lock;
00056 SET_TRACE
00057 }
00058
00059 int RecordThread::create_objects()
00060 {
00061 if(record->default_asset->audio_data)
00062 record_audio = new RecordAudio(mwindow,
00063 record,
00064 this);
00065
00066 if(record->default_asset->video_data)
00067 record_video = new RecordVideo(mwindow,
00068 record,
00069 this);
00070 engine_done = 0;
00071 return 0;
00072 }
00073
00074 int RecordThread::start_recording(int monitor, int context)
00075 {
00076 engine_done = 0;
00077 this->monitor = monitor;
00078 this->context = context;
00079 resume_monitor = !monitor;
00080 loop_lock->lock("RecordThread::start_recording");
00081
00082 startup_lock->lock("RecordThread::start_recording");
00083
00084
00085 Thread::start();
00086 startup_lock->lock("RecordThread::start_recording");
00087 startup_lock->unlock();
00088 return 0;
00089 }
00090
00091 int RecordThread::stop_recording(int resume_monitor)
00092 {
00093 SET_TRACE
00094
00095 state_lock->lock("RecordThread::stop_recording");
00096
00097 engine_done = 1;
00098 if(monitor)
00099 {
00100 pause_lock->unlock();
00101 }
00102
00103 SET_TRACE
00104 this->resume_monitor = resume_monitor;
00105
00106
00107
00108
00109 SET_TRACE
00110 if(record_video)
00111 {
00112 record_video->batch_done = 1;
00113 state_lock->unlock();
00114 record_video->stop_recording();
00115 }
00116 else
00117 if(record_audio && context != CONTEXT_SINGLEFRAME)
00118 {
00119 record_audio->batch_done = 1;
00120 state_lock->unlock();
00121 record_audio->stop_recording();
00122 }
00123
00124 SET_TRACE
00125 Thread::join();
00126 SET_TRACE
00127 return 0;
00128 }
00129
00130 int RecordThread::pause_recording()
00131 {
00132
00133 pause_lock->lock("RecordThread::pause_recording");
00134
00135 state_lock->lock("RecordThread::pause_recording");
00136 if(record->default_asset->video_data)
00137 {
00138 record_video->batch_done = 1;
00139 }
00140 else if (record->default_asset->audio_data)
00141 {
00142 record_audio->batch_done = 1;
00143 }
00144 state_lock->unlock();
00145
00146 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00147 record_audio->stop_recording();
00148 if(record->default_asset->video_data)
00149 record_video->stop_recording();
00150
00151
00152 loop_lock->lock("RecordThread::pause_recording");
00153 loop_lock->unlock();
00154
00155
00156
00157 record->close_input_devices(monitor);
00158
00159 record->capture_state = IS_DONE;
00160 return 0;
00161 }
00162
00163 int RecordThread::resume_recording()
00164 {
00165
00166 if(record_video)
00167 {
00168 record_video->batch_done = 0;
00169 }
00170 else if (record_audio)
00171 {
00172 record_audio->batch_done = 0;
00173 }
00174 loop_lock->lock("RecordThread::resume_recording");
00175 pause_lock->unlock();
00176
00177 return 0;
00178 }
00179
00180 int64_t RecordThread::sync_position()
00181 {
00182 if(record->default_asset->audio_data)
00183 return record_audio->sync_position();
00184 else
00185 return (int64_t)((float)record_timer->get_difference() /
00186 1000 *
00187 record->default_asset->sample_rate + 0.5);
00188 }
00189
00190 void RecordThread::do_cron()
00191 {
00192 do{
00193 double position = record->current_display_position();
00194 int day;
00195 double seconds;
00196
00197
00198
00199 if(position > 0)
00200 {
00201 break;
00202 }
00203 else
00204
00205 {
00206 record->get_current_time(seconds, day);
00207
00208
00209 if(record->get_current_batch()->start_day == 7)
00210 day = record->get_current_batch()->start_day;
00211
00212 if(record->get_current_batch()->start_day == day &&
00213 record->get_current_batch()->start_time >= last_seconds &&
00214 record->get_current_batch()->start_time <= seconds)
00215 {
00216 break;
00217 }
00218
00219
00220
00221
00222 }
00223
00224 last_seconds = seconds;
00225 last_day = day;
00226 if(!engine_done) usleep(BATCH_DELAY);
00227 if(!engine_done)
00228 {
00229 record->record_gui->lock_window("RecordThread::do_cron");
00230 record->record_gui->flash_batch();
00231 record->record_gui->unlock_window();
00232 }
00233 }while(!engine_done);
00234 }
00235
00236
00237
00238 void RecordThread::run()
00239 {
00240 int rewinding_loop = 0;
00241 startup_lock->unlock();
00242 record->get_current_time(last_seconds, last_day);
00243
00244
00245 do
00246 {
00247
00248 if(context == CONTEXT_BATCH &&
00249 !rewinding_loop)
00250 {
00251 do_cron();
00252 }
00253
00254 state_lock->lock("RecordThread::run");
00255
00256 if(!engine_done)
00257 {
00258
00259 rewinding_loop = 0;
00260
00261
00262
00263 if(context == CONTEXT_BATCH)
00264 {
00265
00266 TRACE("RecordThread::run 1");
00267 record->delete_output_file();
00268 TRACE("RecordThread::run 2");
00269 record->open_input_devices(0, context);
00270 TRACE("RecordThread::run 3");
00271 }
00272
00273
00274
00275 if(!monitor && context == CONTEXT_INTERACTIVE)
00276 context = CONTEXT_BATCH;
00277
00278 if(!monitor)
00279 {
00280
00281 TRACE("RecordThread::run 4");
00282 record->open_output_file();
00283 TRACE("RecordThread::run 5");
00284 if(mwindow->edl->session->record_sync_drives)
00285 {
00286 drivesync = new DriveSync;
00287 drivesync->start();
00288 }
00289 else
00290 drivesync = 0;
00291
00292 record->get_current_batch()->recorded = 1;
00293 TRACE("RecordThread::run 6");
00294
00295
00296 if(record->default_asset->audio_data &&
00297 context != CONTEXT_SINGLEFRAME)
00298 {
00299 int buffer_size, fragment_size;
00300 record->get_audio_write_length(buffer_size,
00301 fragment_size);
00302 record->file->start_audio_thread(buffer_size, RING_BUFFERS);
00303 }
00304 TRACE("RecordThread::run 7");
00305
00306 if(record->default_asset->video_data)
00307 record->file->start_video_thread(mwindow->edl->session->video_write_length,
00308 record->vdevice->get_best_colormodel(record->default_asset),
00309 RING_BUFFERS,
00310 record->vdevice->is_compressed(1, 0));
00311 TRACE("RecordThread::run 8");
00312 }
00313
00314
00315 record->get_current_batch()->session_samples = 0;
00316 record->get_current_batch()->session_frames = 0;
00317 record_timer->update();
00318
00319
00320 TRACE("RecordThread::run 9");
00321 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00322 record_audio->arm_recording();
00323 TRACE("RecordThread::run 10");
00324 if(record->default_asset->video_data)
00325 record_video->arm_recording();
00326 TRACE("RecordThread::run 11");
00327 state_lock->unlock();
00328
00329
00330
00331 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00332 record_audio->start_recording();
00333 TRACE("RecordThread::run 12");
00334 if(record->default_asset->video_data)
00335 record_video->start_recording();
00336 TRACE("RecordThread::run 13");
00337
00338
00339 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00340 record_audio->Thread::join();
00341 TRACE("RecordThread::run 14");
00342 if(record->default_asset->video_data)
00343 record_video->Thread::join();
00344 TRACE("RecordThread::run 15");
00345
00346
00347 if(!monitor)
00348 {
00349 if(drivesync) drivesync->done = 1;
00350 TRACE("RecordThread::run 16");
00351 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00352 record->file->stop_audio_thread();
00353 TRACE("RecordThread::run 17");
00354 if(record->default_asset->video_data)
00355 record->file->stop_video_thread();
00356 TRACE("RecordThread::run 18");
00357
00358
00359 record->get_current_batch()->get_current_asset()->audio_length =
00360 record->get_current_batch()->total_samples;
00361 record->get_current_batch()->get_current_asset()->video_length =
00362 record->get_current_batch()->total_frames;
00363
00364
00365 if(!engine_done)
00366 {
00367
00368 if(record->get_current_batch()->record_mode == RECORD_LOOP)
00369 {
00370
00371 record->rewind_file();
00372 record->get_current_batch()->session_samples = 0;
00373 record->get_current_batch()->session_frames = 0;
00374 rewinding_loop = 1;
00375 }
00376 else
00377
00378 if(record->get_next_batch() >= 0 && context != CONTEXT_SINGLEFRAME)
00379 {
00380 record->activate_batch(record->get_next_batch(), 0);
00381 record->close_input_devices(monitor);
00382 }
00383 else
00384
00385 {
00386 engine_done = 1;
00387 }
00388 }
00389 TRACE("RecordThread::run 20");
00390
00391 if(drivesync) delete drivesync;
00392 }
00393 SET_TRACE
00394 }
00395 else
00396 {
00397 state_lock->unlock();
00398 }
00399
00400 SET_TRACE
00401
00402 loop_lock->unlock();
00403 if(monitor)
00404 {
00405
00406 pause_lock->lock("RecordThread::run");
00407 pause_lock->unlock();
00408 }
00409 SET_TRACE
00410 }while(!engine_done);
00411
00412 SET_TRACE
00413 record->close_input_devices(monitor);
00414 SET_TRACE
00415
00416
00417 if(!monitor)
00418 {
00419 record->stop_duplex();
00420 if(resume_monitor) record->resume_monitor();
00421 }
00422 else
00423 {
00424 record->capture_state = IS_DONE;
00425 }
00426 SET_TRACE
00427 }
00428