6 #include "colormodels.h"
11 #include "edlsession.h"
13 #include "filesystem.h"
14 #include "framecache.h"
15 #include "indexfile.h"
17 #include "localsession.h"
19 #include "resourcepixmap.h"
22 #include "trackcanvas.h"
27 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
32 : BC_Pixmap(canvas, w, h)
36 this->mwindow = mwindow;
37 this->canvas = canvas;
38 startsource = edit->startsource;
39 data_type = edit->track->data_type;
40 source_framerate = edit->asset->frame_rate;
41 project_framerate = edit->edl->session->frame_rate;
42 source_samplerate = edit->asset->sample_rate;
43 project_samplerate = edit->edl->session->sample_rate;
47 ResourcePixmap::~ResourcePixmap()
52 void ResourcePixmap::reset()
64 void ResourcePixmap::resize(int w, int h)
66 int new_w = (w > get_w()) ? w : get_w();
67 int new_h = (h > get_h()) ? h : get_h();
69 BC_Pixmap::resize(new_w, new_h);
73 void ResourcePixmap::draw_data(Edit *edit,
82 // Get new areas to fill in relative to pixmap
83 // Area to redraw relative to pixmap
90 if(mwindow->edl->session->show_titles) y += mwindow->theme->get_image("title_bg_data")->get_h();
91 Track *track = edit->edits->track;
94 // If index can't be drawn, don't do anything.
96 int64_t index_zoom = 0;
99 IndexFile indexfile(mwindow);
100 if(!indexfile.open_index(edit->asset))
102 index_zoom = edit->asset->index_zoom;
103 indexfile.close_index();
108 if(data_type == TRACK_AUDIO)
110 double asset_over_session = (double)edit->asset->sample_rate /
111 mwindow->edl->session->sample_rate;
113 if(index_zoom <= mwindow->edl->local_session->zoom_sample *
125 if(edit->startsource != this->startsource ||
126 (data_type == TRACK_AUDIO &&
127 edit->asset->sample_rate != source_samplerate) ||
128 (data_type == TRACK_VIDEO &&
129 !EQUIV(edit->asset->frame_rate, source_framerate)) ||
130 mwindow->edl->session->sample_rate != project_samplerate ||
131 mwindow->edl->session->frame_rate != project_framerate ||
132 mwindow->edl->local_session->zoom_sample != zoom_sample ||
133 mwindow->edl->local_session->zoom_track != zoom_track ||
134 this->pixmap_h != pixmap_h ||
135 (data_type == TRACK_AUDIO &&
136 mwindow->edl->local_session->zoom_y != zoom_y) ||
140 // Shouldn't draw at all if zoomed in below index zoom.
142 refresh_w = pixmap_w;
146 // Start translated right
147 if(pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w)
149 refresh_w = this->edit_x - edit_x;
150 refresh_x = this->pixmap_w - refresh_w;
152 // Moved completely off the pixmap
153 if(refresh_w > this->pixmap_w)
155 refresh_w = this->pixmap_w;
163 mwindow->edl->local_session->zoom_track,
169 // Start translated left
170 if(pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w)
173 refresh_w = edit_x - this->edit_x;
175 // Moved completely off the pixmap
176 if(refresh_w > this->pixmap_w)
178 refresh_w = this->pixmap_w;
184 this->pixmap_w - refresh_w,
185 mwindow->edl->local_session->zoom_track,
191 // Start translated right and pixmap came off of right side
192 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x &&
193 this->edit_x + edit_w > this->pixmap_x + this->pixmap_w)
195 refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
196 refresh_x = pixmap_w - refresh_w;
198 if(refresh_w >= pixmap_w)
201 refresh_w = pixmap_w;
205 copy_area(this->edit_x - edit_x,
207 pixmap_w - refresh_w,
208 mwindow->edl->local_session->zoom_track,
214 // Start translated right and reduced in size on the right.
215 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x)
220 copy_area(this->pixmap_w - pixmap_w,
223 mwindow->edl->local_session->zoom_track,
228 // Start translated left and pixmap came off left side
229 if(edit_x >= 0 && this->edit_x < 0)
232 refresh_w = -this->edit_x;
234 if(refresh_w > pixmap_w)
236 refresh_w = pixmap_w;
243 mwindow->edl->local_session->zoom_track,
249 // Start translated left and reduced in size on the right
250 if(pixmap_w < this->pixmap_w && edit_x > this->edit_x)
256 // Start translated right and left went into left side.
257 if(pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0)
259 refresh_w = pixmap_w - (edit_x + this->pixmap_w);
260 refresh_x = pixmap_w - refresh_w;
262 // Moved completely off new pixmap
263 if(refresh_w > pixmap_w)
265 refresh_w = pixmap_w;
273 mwindow->edl->local_session->zoom_track,
279 // Start translated right and increased in size on the right
280 if(pixmap_w > this->pixmap_w && edit_x <= this->edit_x)
282 refresh_w = pixmap_w - this->pixmap_w;
283 refresh_x = pixmap_w - refresh_w;
286 // Start translated left and increased in size on the right
287 if(pixmap_w > this->pixmap_w && edit_x > this->edit_x)
290 refresh_w = edit_x - this->edit_x;
292 // Moved completely off new pixmap
293 if(refresh_w > this->pixmap_w)
295 refresh_w = pixmap_w;
304 mwindow->edl->local_session->zoom_track,
311 // Update pixmap settings
312 this->edit_id = edit->id;
313 this->startsource = edit->startsource;
314 this->source_framerate = edit->asset->frame_rate;
315 this->source_samplerate = edit->asset->sample_rate;
316 this->project_framerate = edit->edl->session->frame_rate;
317 this->project_samplerate = edit->edl->session->sample_rate;
318 this->edit_x = edit_x;
319 this->pixmap_x = pixmap_x;
320 this->pixmap_w = pixmap_w;
321 this->pixmap_h = pixmap_h;
322 this->zoom_sample = mwindow->edl->local_session->zoom_sample;
323 this->zoom_track = mwindow->edl->local_session->zoom_track;
324 this->zoom_y = mwindow->edl->local_session->zoom_y;
328 // Draw in new background
330 mwindow->theme->draw_resource_bg(canvas,
337 refresh_x + refresh_w,
338 mwindow->edl->local_session->zoom_track + y);
339 //printf("ResourcePixmap::draw_data 70\n");
345 switch(track->data_type)
348 draw_audio_resource(edit, refresh_x, refresh_w);
352 draw_video_resource(edit,
364 if(mwindow->edl->session->show_titles)
365 draw_title(edit, edit_x, edit_w, pixmap_x, pixmap_w);
368 void ResourcePixmap::draw_title(Edit *edit,
374 // coords relative to pixmap
375 int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
376 int64_t x = total_x, w = total_w;
377 int left_margin = 10;
384 if(w > pixmap_w) w -= w - pixmap_w;
386 canvas->draw_3segmenth(x,
391 mwindow->theme->get_image("title_bg_data"),
394 if(total_x > -BC_INFINITY)
396 char title[BCTEXTLEN], channel[BCTEXTLEN];
399 if(edit->user_title[0])
400 strcpy(title, edit->user_title);
403 fs.extract_name(title, edit->asset->path);
405 sprintf(channel, " #%d", edit->channel + 1);
406 strcat(title, channel);
409 canvas->set_color(mwindow->theme->title_color);
410 canvas->set_font(mwindow->theme->title_font);
411 //printf("ResourcePixmap::draw_title 1 %d\n", total_x + 10);
413 // Justify the text on the left boundary of the edit if it is visible.
414 // Otherwise justify it on the left side of the screen.
415 int text_x = total_x + left_margin;
416 text_x = MAX(left_margin, text_x);
417 canvas->draw_text(text_x,
418 canvas->get_text_ascent(MEDIUMFONT_3D) + 2,
426 // Need to draw one more x
427 void ResourcePixmap::draw_audio_resource(Edit *edit, int x, int w)
430 double asset_over_session = (double)edit->asset->sample_rate /
431 mwindow->edl->session->sample_rate;
433 // Develop strategy for drawing
434 switch(edit->asset->index_status)
436 case INDEX_NOTTESTED:
439 // Disabled. Always draw from index.
441 draw_audio_source(edit, x, w);
446 IndexFile indexfile(mwindow);
447 if(!indexfile.open_index(edit->asset))
449 if(edit->asset->index_zoom >
450 mwindow->edl->local_session->zoom_sample *
453 draw_audio_source(edit, x, w);
456 indexfile.draw_index(this, edit, x, w);
457 indexfile.close_index();
481 void ResourcePixmap::draw_audio_source(Edit *edit, int x, int w)
483 File *source = mwindow->audio_cache->check_out(edit->asset,
488 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
493 int source_start = (pixmap_x - edit_x + x) * mwindow->edl->local_session->zoom_sample + edit->startsource;
494 double asset_over_session = (double)edit->asset->sample_rate /
495 mwindow->edl->session->sample_rate;
496 int source_len = w * mwindow->edl->local_session->zoom_sample;
497 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
498 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->get_image("title_bg_data")->get_h();
500 // Single sample zoom
501 if(mwindow->edl->local_session->zoom_sample == 1)
503 double oldsample, newsample;
504 int total_source_samples = (int)((double)(source_len + 1) *
506 double *buffer = new double[total_source_samples];
508 source->set_audio_position((int)((double)source_start *
510 edit->asset->sample_rate);
511 source->set_channel(edit->channel);
512 canvas->set_color(mwindow->theme->audio_color);
514 if(!source->read_samples(buffer,
515 total_source_samples,
516 edit->asset->sample_rate))
518 oldsample = newsample = *buffer;
519 for(int x1 = x, x2 = x + w, i = 0;
523 oldsample = newsample;
524 newsample = buffer[(int)(i * asset_over_session)];
525 canvas->draw_line(x1 - 1,
526 (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
528 (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
534 canvas->test_timer();
537 // Multiple sample zoom
540 int buffersize = fragmentsize = 65536;
541 double *buffer = new double[buffersize + 1];
542 double highsample, lowsample;
543 float sample_of_pixel = 0;
544 int total_source_samples = (int)(source_len *
546 double asset_samples_per_pixel =
547 mwindow->edl->local_session->zoom_sample *
556 source->set_audio_position((int)(source_start * asset_over_session),
557 edit->asset->sample_rate);
558 source->set_channel(edit->channel);
559 canvas->set_color(mwindow->theme->audio_color);
561 for(int source_sample = 0;
562 source_sample < total_source_samples;
563 source_sample += buffersize)
565 fragmentsize = buffersize;
566 if(total_source_samples - source_sample < buffersize)
567 fragmentsize = total_source_samples - source_sample;
569 if(source_sample == 0)
571 highsample = buffer[0];
572 lowsample = buffer[0];
575 if(!source->read_samples(buffer,
577 edit->asset->sample_rate))
581 // Draw samples for this buffer
582 for(int bufferposition = 0;
583 bufferposition < fragmentsize;
587 if(asset_samples_per_pixel < 1)
589 int x1 = (int)x_double;
590 x_double += (double)1 / asset_samples_per_pixel;
591 int x2 = (int)x_double;
593 y1 = (int)(center_pixel -
594 buffer[bufferposition] *
595 mwindow->edl->local_session->zoom_y /
599 canvas->draw_line(x1,
607 canvas->draw_line(x1,
615 if(asset_samples_per_pixel >= 1 &&
616 sample_of_pixel >= asset_samples_per_pixel)
618 // Draw column and reset
619 y1 = (int)(center_pixel -
621 mwindow->edl->local_session->zoom_y /
623 y2 = (int)(center_pixel -
625 mwindow->edl->local_session->zoom_y /
645 sample_of_pixel -= asset_samples_per_pixel;
647 lowsample = highsample = buffer[bufferposition];
652 if(sample_of_pixel >= 1)
654 // update lowsample and highsample
655 if(buffer[bufferposition] < lowsample)
656 lowsample = buffer[bufferposition];
658 if(buffer[bufferposition] > highsample)
659 highsample = buffer[bufferposition];
673 canvas->test_timer();
678 mwindow->audio_cache->check_in(edit->asset);
700 void ResourcePixmap::draw_video_resource(Edit *edit,
708 // pixels spanned by a picon
709 int64_t picon_w = Units::round(edit->picon_w());
710 int64_t picon_h = edit->picon_h();
713 // Don't draw video if picon is bigger than edit
714 if(picon_w > edit_w) return;
716 // pixels spanned by a frame
717 double frame_w = edit->frame_w();
719 // Frames spanned by a picon
720 double frames_per_picon = edit->frames_per_picon();
722 // Current pixel relative to pixmap
725 if(mwindow->edl->session->show_titles)
726 y += mwindow->theme->get_image("title_bg_data")->get_h();
727 // Frame in project touched by current pixel
728 int64_t project_frame;
730 // Get first frame touched by x and fix x to start of frame
731 if(frames_per_picon > 1)
733 int picon = Units::to_int64(
734 (double)(refresh_x + pixmap_x - edit_x) /
736 x = picon_w * picon + edit_x - pixmap_x;
737 project_frame = Units::to_int64((double)picon * frames_per_picon);
741 project_frame = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) /
743 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
746 File *source = mwindow->video_cache->check_out(edit->asset, mwindow->edl);
749 while(x < refresh_x + refresh_w)
751 int64_t source_frame = project_frame + edit->startsource;
752 source->set_layer(edit->channel);
753 source->set_video_position(source_frame,
754 mwindow->edl->session->frame_rate);
756 // Try displaying from source cache
757 FrameCache *frame_cache = source->get_frame_cache();
758 VFrame *picon_frame = 0;
761 if((picon_frame = frame_cache->get_frame_ptr(source_frame,
762 mwindow->edl->session->frame_rate,
770 // Display from file and put in cache
772 if(canvas->temp_picon &&
773 (canvas->temp_picon->get_w() != edit->asset->width ||
774 canvas->temp_picon->get_h() != edit->asset->height))
776 delete canvas->temp_picon;
777 canvas->temp_picon = 0;
780 if(!canvas->temp_picon)
782 canvas->temp_picon = new VFrame(0,
788 source->read_frame(canvas->temp_picon);
789 picon_frame = new VFrame(0, picon_w, picon_h, BC_RGB888);
790 frame_cache->put_frame(picon_frame,
792 mwindow->edl->session->frame_rate,
794 cmodel_transfer(picon_frame->get_rows(),
795 canvas->temp_picon->get_rows(),
804 canvas->temp_picon->get_w(),
805 canvas->temp_picon->get_h(),
808 picon_frame->get_w(),
809 picon_frame->get_h(),
813 canvas->temp_picon->get_bytes_per_line(),
814 picon_frame->get_bytes_per_line());
817 draw_vframe(picon_frame,
827 frame_cache->unlock();
829 if(frames_per_picon > 1)
831 x += Units::round(picon_w);
832 project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
836 x += Units::round(frame_w);
837 project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
841 canvas->test_timer();
846 mwindow->video_cache->check_in(edit->asset);
851 void ResourcePixmap::dump()
853 printf("ResourcePixmap %p\n", this);
854 printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);