00001 #include "aedit.h"
00002 #include "asset.h"
00003 #include "asset.inc"
00004 #include "cache.h"
00005 #include "clip.h"
00006 #include "colormodels.h"
00007 #include "datatype.h"
00008 #include "edit.h"
00009 #include "edits.h"
00010 #include "edl.h"
00011 #include "edlsession.h"
00012 #include "file.h"
00013 #include "filesystem.h"
00014 #include "framecache.h"
00015 #include "indexfile.h"
00016 #include "language.h"
00017 #include "localsession.h"
00018 #include "mwindow.h"
00019 #include "resourcepixmap.h"
00020 #include "theme.h"
00021 #include "track.h"
00022 #include "trackcanvas.h"
00023 #include "vedit.h"
00024 #include "vframe.h"
00025
00026
00027 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
00028 TrackCanvas *canvas,
00029 Edit *edit,
00030 int w,
00031 int h)
00032 : BC_Pixmap(canvas, w, h)
00033 {
00034 reset();
00035
00036 this->mwindow = mwindow;
00037 this->canvas = canvas;
00038 startsource = edit->startsource;
00039 data_type = edit->track->data_type;
00040 source_framerate = edit->asset->frame_rate;
00041 project_framerate = edit->edl->session->frame_rate;
00042 source_samplerate = edit->asset->sample_rate;
00043 project_samplerate = edit->edl->session->sample_rate;
00044 edit_id = edit->id;
00045 }
00046
00047 ResourcePixmap::~ResourcePixmap()
00048 {
00049 }
00050
00051
00052 void ResourcePixmap::reset()
00053 {
00054 edit_x = 0;
00055 pixmap_x = 0;
00056 pixmap_w = 0;
00057 pixmap_h = 0;
00058 zoom_sample = 0;
00059 zoom_track = 0;
00060 zoom_y = 0;
00061 visible = 1;
00062 }
00063
00064 void ResourcePixmap::resize(int w, int h)
00065 {
00066 int new_w = (w > get_w()) ? w : get_w();
00067 int new_h = (h > get_h()) ? h : get_h();
00068
00069 BC_Pixmap::resize(new_w, new_h);
00070 }
00071
00072
00073 void ResourcePixmap::draw_data(Edit *edit,
00074 int64_t edit_x,
00075 int64_t edit_w,
00076 int64_t pixmap_x,
00077 int64_t pixmap_w,
00078 int64_t pixmap_h,
00079 int force,
00080 int indexes_only)
00081 {
00082
00083
00084 int refresh_x = 0;
00085 int refresh_w = 0;
00086
00087
00088
00089 int y = 0;
00090 if(mwindow->edl->session->show_titles) y += mwindow->theme->title_bg_data->get_h();
00091 Track *track = edit->edits->track;
00092
00093
00094
00095 int need_redraw = 0;
00096 int64_t index_zoom = 0;
00097 if(indexes_only)
00098 {
00099 IndexFile indexfile(mwindow);
00100 if(!indexfile.open_index(edit->asset))
00101 {
00102 index_zoom = edit->asset->index_zoom;
00103 indexfile.close_index();
00104 }
00105
00106 if(index_zoom)
00107 {
00108 if(data_type == TRACK_AUDIO)
00109 {
00110 double asset_over_session = (double)edit->asset->sample_rate /
00111 mwindow->edl->session->sample_rate;
00112 asset_over_session;
00113 if(index_zoom <= mwindow->edl->local_session->zoom_sample *
00114 asset_over_session)
00115 need_redraw = 1;
00116 }
00117 }
00118
00119 if(!need_redraw)
00120 return;
00121 }
00122
00123
00124
00125 if(edit->startsource != this->startsource ||
00126 (data_type == TRACK_AUDIO &&
00127 edit->asset->sample_rate != source_samplerate) ||
00128 (data_type == TRACK_VIDEO &&
00129 !EQUIV(edit->asset->frame_rate, source_framerate)) ||
00130 mwindow->edl->session->sample_rate != project_samplerate ||
00131 mwindow->edl->session->frame_rate != project_framerate ||
00132 mwindow->edl->local_session->zoom_sample != zoom_sample ||
00133 mwindow->edl->local_session->zoom_track != zoom_track ||
00134 this->pixmap_h != pixmap_h ||
00135 (data_type == TRACK_AUDIO &&
00136 mwindow->edl->local_session->zoom_y != zoom_y) ||
00137 force ||
00138 need_redraw)
00139 {
00140
00141 refresh_x = 0;
00142 refresh_w = pixmap_w;
00143 }
00144 else
00145 {
00146
00147 if(pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w)
00148 {
00149 refresh_w = this->edit_x - edit_x;
00150 refresh_x = this->pixmap_w - refresh_w;
00151
00152
00153 if(refresh_w > this->pixmap_w)
00154 {
00155 refresh_w = this->pixmap_w;
00156 refresh_x = 0;
00157 }
00158 else
00159 {
00160 copy_area(refresh_w,
00161 y,
00162 refresh_x,
00163 mwindow->edl->local_session->zoom_track,
00164 0,
00165 y);
00166 }
00167 }
00168 else
00169
00170 if(pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w)
00171 {
00172 refresh_x = 0;
00173 refresh_w = edit_x - this->edit_x;
00174
00175
00176 if(refresh_w > this->pixmap_w)
00177 {
00178 refresh_w = this->pixmap_w;
00179 }
00180 else
00181 {
00182 copy_area(0,
00183 y,
00184 this->pixmap_w - refresh_w,
00185 mwindow->edl->local_session->zoom_track,
00186 refresh_w,
00187 y);
00188 }
00189 }
00190 else
00191
00192 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x &&
00193 this->edit_x + edit_w > this->pixmap_x + this->pixmap_w)
00194 {
00195 refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
00196 refresh_x = pixmap_w - refresh_w;
00197
00198 if(refresh_w >= pixmap_w)
00199 {
00200 refresh_x = 0;
00201 refresh_w = pixmap_w;
00202 }
00203 else
00204 {
00205 copy_area(this->edit_x - edit_x,
00206 y,
00207 pixmap_w - refresh_w,
00208 mwindow->edl->local_session->zoom_track,
00209 0,
00210 y);
00211 }
00212 }
00213 else
00214
00215 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x)
00216 {
00217 refresh_x = 0;
00218 refresh_w = 0;
00219
00220 copy_area(this->pixmap_w - pixmap_w,
00221 y,
00222 pixmap_w,
00223 mwindow->edl->local_session->zoom_track,
00224 0,
00225 y);
00226 }
00227 else
00228
00229 if(edit_x >= 0 && this->edit_x < 0)
00230 {
00231 refresh_x = 0;
00232 refresh_w = -this->edit_x;
00233
00234 if(refresh_w > pixmap_w)
00235 {
00236 refresh_w = pixmap_w;
00237 }
00238 else
00239 {
00240 copy_area(0,
00241 y,
00242 this->pixmap_w,
00243 mwindow->edl->local_session->zoom_track,
00244 refresh_w,
00245 y);
00246 }
00247 }
00248 else
00249
00250 if(pixmap_w < this->pixmap_w && edit_x > this->edit_x)
00251 {
00252 refresh_x = 0;
00253 refresh_w = 0;
00254 }
00255 else
00256
00257 if(pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0)
00258 {
00259 refresh_w = pixmap_w - (edit_x + this->pixmap_w);
00260 refresh_x = pixmap_w - refresh_w;
00261
00262
00263 if(refresh_w > pixmap_w)
00264 {
00265 refresh_w = pixmap_w;
00266 refresh_x = 0;
00267 }
00268 else
00269 {
00270 copy_area(-edit_x,
00271 y,
00272 refresh_x,
00273 mwindow->edl->local_session->zoom_track,
00274 0,
00275 y);
00276 }
00277 }
00278 else
00279
00280 if(pixmap_w > this->pixmap_w && edit_x <= this->edit_x)
00281 {
00282 refresh_w = pixmap_w - this->pixmap_w;
00283 refresh_x = pixmap_w - refresh_w;
00284 }
00285 else
00286
00287 if(pixmap_w > this->pixmap_w && edit_x > this->edit_x)
00288 {
00289 refresh_x = 0;
00290 refresh_w = edit_x - this->edit_x;
00291
00292
00293 if(refresh_w > this->pixmap_w)
00294 {
00295 refresh_w = pixmap_w;
00296 refresh_x = 0;
00297 }
00298
00299 else
00300 {
00301 copy_area(0,
00302 y,
00303 this->pixmap_w,
00304 mwindow->edl->local_session->zoom_track,
00305 refresh_w,
00306 y);
00307 }
00308 }
00309 }
00310
00311
00312 this->edit_id = edit->id;
00313 this->startsource = edit->startsource;
00314 this->source_framerate = edit->asset->frame_rate;
00315 this->source_samplerate = edit->asset->sample_rate;
00316 this->project_framerate = edit->edl->session->frame_rate;
00317 this->project_samplerate = edit->edl->session->sample_rate;
00318 this->edit_x = edit_x;
00319 this->pixmap_x = pixmap_x;
00320 this->pixmap_w = pixmap_w;
00321 this->pixmap_h = pixmap_h;
00322 this->zoom_sample = mwindow->edl->local_session->zoom_sample;
00323 this->zoom_track = mwindow->edl->local_session->zoom_track;
00324 this->zoom_y = mwindow->edl->local_session->zoom_y;
00325
00326
00327
00328
00329 if(refresh_w > 0)
00330 mwindow->theme->draw_resource_bg(canvas,
00331 this,
00332 edit_x,
00333 edit_w,
00334 pixmap_x,
00335 refresh_x,
00336 y,
00337 refresh_x + refresh_w,
00338 mwindow->edl->local_session->zoom_track + y);
00339
00340
00341
00342
00343 if(track->draw)
00344 {
00345 switch(track->data_type)
00346 {
00347 case TRACK_AUDIO:
00348 draw_audio_resource(edit, refresh_x, refresh_w);
00349 break;
00350
00351 case TRACK_VIDEO:
00352 draw_video_resource(edit,
00353 edit_x,
00354 edit_w,
00355 pixmap_x,
00356 pixmap_w,
00357 refresh_x,
00358 refresh_w);
00359 break;
00360 }
00361 }
00362
00363
00364 if(mwindow->edl->session->show_titles)
00365 draw_title(edit, edit_x, edit_w, pixmap_x, pixmap_w);
00366 }
00367
00368 void ResourcePixmap::draw_title(Edit *edit,
00369 int64_t edit_x,
00370 int64_t edit_w,
00371 int64_t pixmap_x,
00372 int64_t pixmap_w)
00373 {
00374
00375 int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
00376 int64_t x = total_x, w = total_w;
00377 int left_margin = 10;
00378
00379 if(x < 0)
00380 {
00381 w -= -x;
00382 x = 0;
00383 }
00384 if(w > pixmap_w) w -= w - pixmap_w;
00385
00386 canvas->draw_3segmenth(x,
00387 0,
00388 w,
00389 total_x,
00390 total_w,
00391 mwindow->theme->title_bg_data,
00392 this);
00393
00394 if(total_x > -BC_INFINITY)
00395 {
00396 char title[BCTEXTLEN], channel[BCTEXTLEN];
00397 FileSystem fs;
00398
00399 if(edit->user_title[0])
00400 strcpy(title, edit->user_title);
00401 else
00402 {
00403 fs.extract_name(title, edit->asset->path);
00404
00405 sprintf(channel, " #%d", edit->channel + 1);
00406 strcat(title, channel);
00407 }
00408
00409 canvas->set_color(mwindow->theme->title_color);
00410 canvas->set_font(mwindow->theme->title_font);
00411
00412
00413
00414
00415 int text_x = total_x + left_margin;
00416 text_x = MAX(left_margin, text_x);
00417 canvas->draw_text(text_x,
00418 canvas->get_text_ascent(MEDIUMFONT_3D) + 2,
00419 title,
00420 strlen(title),
00421 this);
00422 }
00423 }
00424
00425
00426
00427 void ResourcePixmap::draw_audio_resource(Edit *edit, int x, int w)
00428 {
00429 if(w <= 0) return;
00430 double asset_over_session = (double)edit->asset->sample_rate /
00431 mwindow->edl->session->sample_rate;
00432
00433
00434 switch(edit->asset->index_status)
00435 {
00436 case INDEX_NOTTESTED:
00437 return;
00438 break;
00439
00440 case INDEX_TOOSMALL:
00441 draw_audio_source(edit, x, w);
00442 break;
00443 case INDEX_BUILDING:
00444 case INDEX_READY:
00445 {
00446 IndexFile indexfile(mwindow);
00447 if(!indexfile.open_index(edit->asset))
00448 {
00449 if(edit->asset->index_zoom >
00450 mwindow->edl->local_session->zoom_sample *
00451 asset_over_session)
00452 {
00453 draw_audio_source(edit, x, w);
00454 }
00455 else
00456 indexfile.draw_index(this, edit, x, w);
00457 indexfile.close_index();
00458 }
00459 break;
00460 }
00461 }
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 void ResourcePixmap::draw_audio_source(Edit *edit, int x, int w)
00482 {
00483 File *source = mwindow->audio_cache->check_out(edit->asset);
00484
00485 if(!source)
00486 {
00487 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
00488 return;
00489 }
00490
00491 w++;
00492 int source_start = (pixmap_x - edit_x + x) * mwindow->edl->local_session->zoom_sample + edit->startsource;
00493 int source_len = w * mwindow->edl->local_session->zoom_sample;
00494 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
00495 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->title_bg_data->get_h();
00496 double asset_over_session = (double)edit->asset->sample_rate /
00497 mwindow->edl->session->sample_rate;
00498
00499
00500 if(mwindow->edl->local_session->zoom_sample == 1)
00501 {
00502 double oldsample, newsample;
00503 int total_source_samples = (int)((double)(source_len + 1) *
00504 asset_over_session);
00505 double *buffer = new double[total_source_samples];
00506
00507 source->set_audio_position((int)((double)source_start *
00508 asset_over_session),
00509 edit->asset->sample_rate);
00510 source->set_channel(edit->channel);
00511 canvas->set_color(mwindow->theme->audio_color);
00512
00513 if(!source->read_samples(buffer,
00514 total_source_samples,
00515 edit->asset->sample_rate))
00516 {
00517 oldsample = newsample = *buffer;
00518 for(int x1 = x, x2 = x + w, i = 0;
00519 x1 < x2;
00520 x1++, i++)
00521 {
00522 oldsample = newsample;
00523 newsample = buffer[(int)(i * asset_over_session)];
00524 canvas->draw_line(x1 - 1,
00525 (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
00526 x1,
00527 (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
00528 this);
00529 }
00530 }
00531
00532 delete [] buffer;
00533 canvas->test_timer();
00534 }
00535 else
00536
00537 {
00538 int fragmentsize;
00539 int buffersize = fragmentsize = 65536;
00540 double *buffer = new double[buffersize + 1];
00541 double highsample, lowsample;
00542 float sample_of_pixel = 0;
00543 int total_source_samples = (int)(source_len *
00544 asset_over_session);
00545 double asset_samples_per_pixel =
00546 mwindow->edl->local_session->zoom_sample *
00547 asset_over_session;
00548 int first_pixel = 1;
00549 int prev_y1 = -1;
00550 int prev_y2 = -1;
00551 int y1;
00552 int y2;
00553 double x_double = x;
00554
00555 source->set_audio_position((int)(source_start * asset_over_session),
00556 edit->asset->sample_rate);
00557 source->set_channel(edit->channel);
00558 canvas->set_color(mwindow->theme->audio_color);
00559
00560 for(int source_sample = 0;
00561 source_sample < total_source_samples;
00562 source_sample += buffersize)
00563 {
00564 fragmentsize = buffersize;
00565 if(total_source_samples - source_sample < buffersize)
00566 fragmentsize = total_source_samples - source_sample;
00567
00568 if(source_sample == 0)
00569 {
00570 highsample = buffer[0];
00571 lowsample = buffer[0];
00572 }
00573
00574 if(!source->read_samples(buffer,
00575 fragmentsize,
00576 edit->asset->sample_rate))
00577 {
00578
00579
00580
00581 for(int bufferposition = 0;
00582 bufferposition < fragmentsize;
00583 bufferposition++)
00584 {
00585
00586 if(asset_samples_per_pixel < 1)
00587 {
00588 int x1 = (int)x_double;
00589 x_double += (double)1 / asset_samples_per_pixel;
00590 int x2 = (int)x_double;
00591
00592 y1 = (int)(center_pixel -
00593 buffer[bufferposition] *
00594 mwindow->edl->local_session->zoom_y /
00595 2);
00596 if(first_pixel)
00597 {
00598 canvas->draw_line(x1,
00599 y1,
00600 x2,
00601 y1,
00602 this);
00603 first_pixel = 0;
00604 }
00605 else
00606 canvas->draw_line(x1,
00607 prev_y1,
00608 x2,
00609 y1,
00610 this);
00611 prev_y1 = y1;
00612 }
00613 else
00614 if(asset_samples_per_pixel >= 1 &&
00615 sample_of_pixel >= asset_samples_per_pixel)
00616 {
00617
00618 y1 = (int)(center_pixel -
00619 highsample *
00620 mwindow->edl->local_session->zoom_y /
00621 2);
00622 y2 = (int)(center_pixel -
00623 lowsample *
00624 mwindow->edl->local_session->zoom_y /
00625 2);
00626
00627 int current_y1;
00628 int current_y2;
00629 if(first_pixel)
00630 {
00631 canvas->draw_line(x,
00632 y1,
00633 x,
00634 y2,
00635 this);
00636 first_pixel = 0;
00637 }
00638 else
00639 canvas->draw_line(x,
00640 MIN(y1, prev_y2),
00641 x,
00642 MAX(y2, prev_y1),
00643 this);
00644 sample_of_pixel -= asset_samples_per_pixel;
00645 x++;
00646 lowsample = highsample = buffer[bufferposition];
00647 prev_y1 = y1;
00648 prev_y2 = y2;
00649 }
00650
00651 if(sample_of_pixel >= 1)
00652 {
00653
00654 if(buffer[bufferposition] < lowsample)
00655 lowsample = buffer[bufferposition];
00656 else
00657 if(buffer[bufferposition] > highsample)
00658 highsample = buffer[bufferposition];
00659 }
00660
00661
00662 sample_of_pixel++;
00663 }
00664
00665
00666
00667
00668
00669 }
00670
00671
00672 canvas->test_timer();
00673 }
00674 delete [] buffer;
00675 }
00676
00677 mwindow->audio_cache->check_in(edit->asset);
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 void ResourcePixmap::draw_video_resource(Edit *edit,
00700 int64_t edit_x,
00701 int64_t edit_w,
00702 int64_t pixmap_x,
00703 int64_t pixmap_w,
00704 int refresh_x,
00705 int refresh_w)
00706 {
00707
00708
00709 int64_t picon_w = Units::round(edit->picon_w());
00710 int64_t picon_h = edit->picon_h();
00711
00712
00713
00714 if(picon_w > edit_w) return;
00715
00716
00717
00718 double frame_w = edit->frame_w();
00719
00720
00721
00722 double frames_per_picon = edit->frames_per_picon();
00723
00724
00725
00726 int x = 0;
00727 int y = 0;
00728 if(mwindow->edl->session->show_titles)
00729 y += mwindow->theme->title_bg_data->get_h();
00730
00731 int64_t project_frame;
00732
00733
00734 if(frames_per_picon > 1)
00735 {
00736 int picon = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) / picon_w);
00737 x = picon_w * picon + edit_x - pixmap_x;
00738 project_frame = Units::to_int64((double)picon * frames_per_picon);
00739 }
00740 else
00741 {
00742 project_frame = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) /
00743 frame_w);
00744 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
00745 }
00746
00747
00748 File *source = mwindow->video_cache->check_out(edit->asset);
00749 if(!source) return;
00750
00751
00752
00753
00754 while(x < refresh_x + refresh_w)
00755 {
00756 int64_t source_frame = project_frame + edit->startsource;
00757 source->set_layer(edit->channel);
00758 source->set_video_position(source_frame,
00759 mwindow->edl->session->frame_rate);
00760
00761
00762 FrameCache *frame_cache = source->get_frame_cache();
00763 VFrame *picon_frame = 0;
00764 int use_cache = 0;
00765
00766
00767 if((picon_frame = frame_cache->get_frame_ptr(source_frame,
00768 mwindow->edl->session->frame_rate,
00769 BC_RGB888,
00770 picon_w,
00771 picon_h)) != 0)
00772 {
00773 use_cache = 1;
00774 }
00775 else
00776
00777 {
00778 if(canvas->temp_picon &&
00779 (canvas->temp_picon->get_w() != edit->asset->width ||
00780 canvas->temp_picon->get_h() != edit->asset->height))
00781 {
00782 delete canvas->temp_picon;
00783 canvas->temp_picon = 0;
00784 }
00785
00786 if(!canvas->temp_picon)
00787 {
00788 canvas->temp_picon = new VFrame(0,
00789 edit->asset->width,
00790 edit->asset->height,
00791 BC_RGB888);
00792 }
00793
00794 source->read_frame(canvas->temp_picon);
00795 picon_frame = new VFrame(0, picon_w, picon_h, BC_RGB888);
00796 frame_cache->put_frame(picon_frame,
00797 source_frame,
00798 mwindow->edl->session->frame_rate,
00799 0);
00800 cmodel_transfer(picon_frame->get_rows(),
00801 canvas->temp_picon->get_rows(),
00802 0,
00803 0,
00804 0,
00805 0,
00806 0,
00807 0,
00808 0,
00809 0,
00810 canvas->temp_picon->get_w(),
00811 canvas->temp_picon->get_h(),
00812 0,
00813 0,
00814 picon_frame->get_w(),
00815 picon_frame->get_h(),
00816 BC_RGB888,
00817 BC_RGB888,
00818 0,
00819 canvas->temp_picon->get_bytes_per_line(),
00820 picon_frame->get_bytes_per_line());
00821 }
00822
00823 draw_vframe(picon_frame,
00824 x,
00825 y,
00826 picon_w,
00827 picon_h,
00828 0,
00829 0);
00830
00831 if(use_cache)
00832 frame_cache->unlock();
00833
00834 if(frames_per_picon > 1)
00835 {
00836 x += Units::round(picon_w);
00837 project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
00838 }
00839 else
00840 {
00841 x += Units::round(frame_w);
00842 project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
00843 }
00844
00845
00846 canvas->test_timer();
00847 }
00848
00849 if(source)
00850 {
00851 mwindow->video_cache->check_in(edit->asset);
00852 }
00853 }
00854
00855
00856 void ResourcePixmap::dump()
00857 {
00858 printf("ResourcePixmap %p\n", this);
00859 printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);
00860 }
00861
00862
00863