00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "bctimer.h"
00004 #include "cache.h"
00005 #include "clip.h"
00006 #include "condition.h"
00007 #include "datatype.h"
00008 #include "edl.h"
00009 #include "edlsession.h"
00010 #include "file.h"
00011 #include "framecache.h"
00012 #include "mutex.h"
00013 #include "mwindow.h"
00014 #include "mwindowgui.h"
00015 #include "resourcethread.h"
00016 #include "resourcepixmap.h"
00017 #include "trackcanvas.h"
00018 #include "vframe.h"
00019 #include "wavecache.h"
00020
00021
00022 ResourceThreadItem::ResourceThreadItem(ResourcePixmap *pixmap,
00023 Asset *asset,
00024 int data_type,
00025 int operation_count)
00026 {
00027 this->data_type = data_type;
00028 this->pixmap = pixmap;
00029 this->asset = asset;
00030 this->operation_count = operation_count;
00031 asset->GarbageObject::add_user();
00032 last = 0;
00033 }
00034
00035 ResourceThreadItem::~ResourceThreadItem()
00036 {
00037 asset->GarbageObject::remove_user();
00038 }
00039
00040
00041
00042
00043
00044
00045
00046 VResourceThreadItem::VResourceThreadItem(ResourcePixmap *pixmap,
00047 int picon_x,
00048 int picon_y,
00049 int picon_w,
00050 int picon_h,
00051 double frame_rate,
00052 int64_t position,
00053 int layer,
00054 Asset *asset,
00055 int operation_count)
00056 : ResourceThreadItem(pixmap, asset, TRACK_VIDEO, operation_count)
00057 {
00058 this->picon_x = picon_x;
00059 this->picon_y = picon_y;
00060 this->picon_w = picon_w;
00061 this->picon_h = picon_h;
00062 this->frame_rate = frame_rate;
00063 this->position = position;
00064 this->layer = layer;
00065 }
00066
00067 VResourceThreadItem::~VResourceThreadItem()
00068 {
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078 AResourceThreadItem::AResourceThreadItem(ResourcePixmap *pixmap,
00079 Asset *asset,
00080 int x,
00081 int channel,
00082 int64_t start,
00083 int64_t end,
00084 int operation_count)
00085 : ResourceThreadItem(pixmap, asset, TRACK_AUDIO, operation_count)
00086 {
00087 this->x = x;
00088 this->channel = channel;
00089 this->start = start;
00090 this->end = end;
00091 }
00092
00093 AResourceThreadItem::~AResourceThreadItem()
00094 {
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 ResourceThread::ResourceThread(MWindow *mwindow)
00114 {
00115 this->mwindow = mwindow;
00116 interrupted = 1;
00117 temp_picon = 0;
00118 temp_picon2 = 0;
00119 draw_lock = new Condition(0, "ResourceThread::draw_lock", 0);
00120
00121 item_lock = new Mutex("ResourceThread::item_lock");
00122 audio_buffer = 0;
00123 timer = new Timer;
00124 prev_x = -1;
00125 prev_h = 0;
00126 prev_l = 0;
00127 operation_count = 0;
00128 }
00129
00130 ResourceThread::~ResourceThread()
00131 {
00132 delete draw_lock;
00133
00134 delete item_lock;
00135 delete temp_picon;
00136 delete temp_picon2;
00137 delete [] audio_buffer;
00138 delete timer;
00139 }
00140
00141 void ResourceThread::create_objects()
00142 {
00143 Thread::start();
00144 }
00145
00146 void ResourceThread::add_picon(ResourcePixmap *pixmap,
00147 int picon_x,
00148 int picon_y,
00149 int picon_w,
00150 int picon_h,
00151 double frame_rate,
00152 int64_t position,
00153 int layer,
00154 Asset *asset)
00155 {
00156 item_lock->lock("ResourceThread::item_lock");
00157
00158 items.append(new VResourceThreadItem(pixmap,
00159 picon_x,
00160 picon_y,
00161 picon_w,
00162 picon_h,
00163 frame_rate,
00164 position,
00165 layer,
00166 asset,
00167 operation_count));
00168 item_lock->unlock();
00169 }
00170
00171 void ResourceThread::add_wave(ResourcePixmap *pixmap,
00172 Asset *asset,
00173 int x,
00174 int channel,
00175 int64_t source_start,
00176 int64_t source_end)
00177 {
00178 item_lock->lock("ResourceThread::item_lock");
00179
00180 items.append(new AResourceThreadItem(pixmap,
00181 asset,
00182 x,
00183 channel,
00184 source_start,
00185 source_end,
00186 operation_count));
00187 item_lock->unlock();
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 void ResourceThread::stop_draw(int reset)
00201 {
00202 if(!interrupted)
00203 {
00204 interrupted = 1;
00205 item_lock->lock("ResourceThread::stop_draw");
00206 if(reset) items.remove_all_objects();
00207 operation_count++;
00208 item_lock->unlock();
00209 prev_x = -1;
00210 prev_h = 0;
00211 prev_l = 0;
00212 }
00213 }
00214
00215 void ResourceThread::start_draw()
00216 {
00217 interrupted = 0;
00218
00219 for(int i = items.total - 1; i >= 0; i--)
00220 {
00221 ResourceThreadItem *item = items.values[i];
00222 if(item->data_type == TRACK_AUDIO)
00223 {
00224 item->last = 1;
00225 break;
00226 }
00227 }
00228 timer->update();
00229 draw_lock->unlock();
00230 }
00231
00232 void ResourceThread::run()
00233 {
00234 while(1)
00235 {
00236
00237 draw_lock->lock("ResourceThread::run");
00238
00239
00240 while(!interrupted)
00241 {
00242
00243
00244 item_lock->lock("ResourceThread::run");
00245 int total_items = items.total;
00246 ResourceThreadItem *item = 0;
00247 if(items.total)
00248 {
00249 item = items.values[0];
00250 items.remove_number(0);
00251 }
00252 item_lock->unlock();
00253
00254 if(!total_items) break;
00255
00256
00257 if(item->data_type == TRACK_VIDEO)
00258 {
00259
00260 do_video((VResourceThreadItem*)item);
00261 }
00262 else
00263 if(item->data_type == TRACK_AUDIO)
00264 {
00265 do_audio((AResourceThreadItem*)item);
00266 }
00267
00268 delete item;
00269 }
00270 }
00271 }
00272
00273
00274
00275
00276 void ResourceThread::do_video(VResourceThreadItem *item)
00277 {
00278 if(temp_picon &&
00279 (temp_picon->get_w() != item->asset->width ||
00280 temp_picon->get_h() != item->asset->height))
00281 {
00282 delete temp_picon;
00283 temp_picon = 0;
00284 }
00285
00286 if(!temp_picon)
00287 {
00288 temp_picon = new VFrame(0,
00289 item->asset->width,
00290 item->asset->height,
00291 BC_RGB888);
00292 }
00293
00294
00295 if(temp_picon2 &&
00296 (temp_picon2->get_w() != item->picon_w ||
00297 temp_picon2->get_h() != item->picon_h))
00298 {
00299 delete temp_picon2;
00300 temp_picon2 = 0;
00301 }
00302
00303 if(!temp_picon2)
00304 {
00305 temp_picon2 = new VFrame(0,
00306 item->picon_w,
00307 item->picon_h,
00308 BC_RGB888);
00309 }
00310
00311
00312
00313
00314
00315 VFrame *picon_frame = 0;
00316
00317 if((picon_frame = mwindow->frame_cache->get_frame_ptr(item->position,
00318 item->layer,
00319 item->frame_rate,
00320 BC_RGB888,
00321 item->picon_w,
00322 item->picon_h,
00323 item->asset->id)) != 0)
00324 {
00325 temp_picon2->copy_from(picon_frame);
00326
00327 mwindow->frame_cache->unlock();
00328 }
00329 else
00330 {
00331
00332 File *source = mwindow->video_cache->check_out(item->asset,
00333 mwindow->edl);
00334 if(!source)
00335 {
00336 return;
00337 }
00338 source->set_layer(item->layer);
00339 source->set_video_position(item->position,
00340 item->frame_rate);
00341
00342 source->read_frame(temp_picon);
00343 picon_frame = new VFrame(0, item->picon_w, item->picon_h, BC_RGB888);
00344 cmodel_transfer(picon_frame->get_rows(),
00345 temp_picon->get_rows(),
00346 0,
00347 0,
00348 0,
00349 0,
00350 0,
00351 0,
00352 0,
00353 0,
00354 temp_picon->get_w(),
00355 temp_picon->get_h(),
00356 0,
00357 0,
00358 picon_frame->get_w(),
00359 picon_frame->get_h(),
00360 BC_RGB888,
00361 BC_RGB888,
00362 0,
00363 temp_picon->get_bytes_per_line(),
00364 picon_frame->get_bytes_per_line());
00365 temp_picon2->copy_from(picon_frame);
00366 mwindow->frame_cache->put_frame(picon_frame,
00367 item->position,
00368 item->layer,
00369 mwindow->edl->session->frame_rate,
00370 0,
00371 item->asset);
00372 mwindow->video_cache->check_in(item->asset);
00373 }
00374
00375
00376
00377 if(interrupted)
00378 {
00379 return;
00380 }
00381
00382
00383
00384 mwindow->gui->lock_window("ResourceThread::do_video");
00385
00386 if(interrupted)
00387 {
00388 mwindow->gui->unlock_window();
00389 return;
00390 }
00391
00392
00393
00394
00395 if(item->operation_count == operation_count)
00396 {
00397 int exists = 0;
00398 for(int i = 0; i < mwindow->gui->canvas->resource_pixmaps.total; i++)
00399 {
00400 if(mwindow->gui->canvas->resource_pixmaps.values[i] == item->pixmap)
00401 exists = 1;
00402 }
00403 if(exists)
00404 {
00405 item->pixmap->draw_vframe(temp_picon2,
00406 item->picon_x,
00407 item->picon_y,
00408 item->picon_w,
00409 item->picon_h,
00410 0,
00411 0);
00412 mwindow->gui->update(0, 3, 0, 0, 0, 0, 0);
00413 }
00414 }
00415
00416 mwindow->gui->unlock_window();
00417 }
00418
00419
00420 #define BUFFERSIZE 65536
00421 void ResourceThread::do_audio(AResourceThreadItem *item)
00422 {
00423
00424 WaveCacheItem *wave_item;
00425 double high;
00426 double low;
00427
00428 if((wave_item = mwindow->wave_cache->get_wave(item->asset->id,
00429 item->channel,
00430 item->start,
00431 item->end)))
00432 {
00433 high = wave_item->high;
00434 low = wave_item->low;
00435 mwindow->wave_cache->unlock();
00436 }
00437 else
00438 {
00439 int first_sample = 1;
00440 int64_t start = item->start;
00441 int64_t end = item->end;
00442 if(start == end) end = start + 1;
00443
00444 for(int64_t sample = start; sample < end; sample++)
00445 {
00446 double value;
00447
00448 if(audio_buffer &&
00449 item->channel == audio_channel &&
00450 item->asset->id == audio_asset_id &&
00451 sample >= audio_start &&
00452 sample < audio_start + audio_samples)
00453 {
00454 ;
00455 }
00456 else
00457
00458 {
00459 File *source = mwindow->audio_cache->check_out(item->asset,
00460 mwindow->edl);
00461 if(!source)
00462 return;
00463
00464 source->set_channel(item->channel);
00465 source->set_audio_position(sample, item->asset->sample_rate);
00466 int64_t total_samples = source->get_audio_length(-1);
00467 if(!audio_buffer) audio_buffer = new double[BUFFERSIZE];
00468 int fragment = BUFFERSIZE;
00469 if(fragment + sample > total_samples)
00470 fragment = total_samples - sample;
00471 source->read_samples(audio_buffer, fragment, item->asset->sample_rate);
00472 audio_channel = item->channel;
00473 audio_start = sample;
00474 audio_samples = fragment;
00475 audio_asset_id = item->asset->id;
00476 mwindow->audio_cache->check_in(item->asset);
00477 }
00478
00479
00480 value = audio_buffer[sample - audio_start];
00481 if(first_sample)
00482 {
00483 high = low = value;
00484 first_sample = 0;
00485 }
00486 else
00487 {
00488 if(value > high)
00489 high = value;
00490 else
00491 if(value < low)
00492 low = value;
00493 }
00494 }
00495
00496 mwindow->wave_cache->put_wave(item->asset,
00497 item->channel,
00498 item->start,
00499 item->end,
00500 high,
00501 low);
00502 }
00503
00504
00505 if(interrupted)
00506 return;
00507
00508
00509 mwindow->gui->lock_window("ResourceThread::do_audio");
00510 if(interrupted)
00511 {
00512 mwindow->gui->unlock_window();
00513 return;
00514 }
00515
00516 if(item->operation_count == operation_count)
00517 {
00518
00519
00520 int exists = 0;
00521 for(int i = 0; i < mwindow->gui->canvas->resource_pixmaps.total; i++)
00522 {
00523 if(mwindow->gui->canvas->resource_pixmaps.values[i] == item->pixmap)
00524 exists = 1;
00525 }
00526
00527 if(exists)
00528 {
00529 if(prev_x == item->x - 1)
00530 {
00531 high = MAX(high, prev_l);
00532 low = MIN(low, prev_h);
00533 }
00534 prev_x = item->x;
00535 prev_h = high;
00536 prev_l = low;
00537 item->pixmap->draw_wave(item->x, high, low);
00538 if(timer->get_difference() > 250 || item->last)
00539 {
00540 mwindow->gui->update(0, 3, 0, 0, 0, 0, 0);
00541 timer->update();
00542 }
00543 }
00544 }
00545
00546 mwindow->gui->unlock_window();
00547
00548 }
00549
00550
00551
00552