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->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->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);
487 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
492 int source_start = (pixmap_x - edit_x + x) * mwindow->edl->local_session->zoom_sample + edit->startsource;
493 int source_len = w * mwindow->edl->local_session->zoom_sample;
494 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
495 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->title_bg_data->get_h();
496 double asset_over_session = (double)edit->asset->sample_rate /
497 mwindow->edl->session->sample_rate;
499 // Single sample zoom
500 if(mwindow->edl->local_session->zoom_sample == 1)
502 double oldsample, newsample;
503 int total_source_samples = (int)((double)(source_len + 1) *
505 double *buffer = new double[total_source_samples];
507 source->set_audio_position((int)((double)source_start *
509 edit->asset->sample_rate);
510 source->set_channel(edit->channel);
511 canvas->set_color(mwindow->theme->audio_color);
513 if(!source->read_samples(buffer,
514 total_source_samples,
515 edit->asset->sample_rate))
517 oldsample = newsample = *buffer;
518 for(int x1 = x, x2 = x + w, i = 0;
522 oldsample = newsample;
523 newsample = buffer[(int)(i * asset_over_session)];
524 canvas->draw_line(x1 - 1,
525 (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
527 (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
533 canvas->test_timer();
536 // Multiple sample zoom
539 int buffersize = fragmentsize = 65536;
540 double *buffer = new double[buffersize + 1];
541 double highsample, lowsample;
542 float sample_of_pixel = 0;
543 int total_source_samples = (int)(source_len *
545 double asset_samples_per_pixel =
546 mwindow->edl->local_session->zoom_sample *
555 source->set_audio_position((int)(source_start * asset_over_session),
556 edit->asset->sample_rate);
557 source->set_channel(edit->channel);
558 canvas->set_color(mwindow->theme->audio_color);
560 for(int source_sample = 0;
561 source_sample < total_source_samples;
562 source_sample += buffersize)
564 fragmentsize = buffersize;
565 if(total_source_samples - source_sample < buffersize)
566 fragmentsize = total_source_samples - source_sample;
568 if(source_sample == 0)
570 highsample = buffer[0];
571 lowsample = buffer[0];
574 if(!source->read_samples(buffer,
576 edit->asset->sample_rate))
580 // Draw samples for this buffer
581 for(int bufferposition = 0;
582 bufferposition < fragmentsize;
586 if(asset_samples_per_pixel < 1)
588 int x1 = (int)x_double;
589 x_double += (double)1 / asset_samples_per_pixel;
590 int x2 = (int)x_double;
592 y1 = (int)(center_pixel -
593 buffer[bufferposition] *
594 mwindow->edl->local_session->zoom_y /
598 canvas->draw_line(x1,
606 canvas->draw_line(x1,
614 if(asset_samples_per_pixel >= 1 &&
615 sample_of_pixel >= asset_samples_per_pixel)
617 // Draw column and reset
618 y1 = (int)(center_pixel -
620 mwindow->edl->local_session->zoom_y /
622 y2 = (int)(center_pixel -
624 mwindow->edl->local_session->zoom_y /
644 sample_of_pixel -= asset_samples_per_pixel;
646 lowsample = highsample = buffer[bufferposition];
651 if(sample_of_pixel >= 1)
653 // update lowsample and highsample
654 if(buffer[bufferposition] < lowsample)
655 lowsample = buffer[bufferposition];
657 if(buffer[bufferposition] > highsample)
658 highsample = buffer[bufferposition];
672 canvas->test_timer();
677 mwindow->audio_cache->check_in(edit->asset);
699 void ResourcePixmap::draw_video_resource(Edit *edit,
707 //printf("ResourcePixmap::draw_video_resource 1\n");
708 // pixels spanned by a picon
709 int64_t picon_w = Units::round(edit->picon_w());
710 int64_t picon_h = edit->picon_h();
712 //printf("ResourcePixmap::draw_video_resource 1\n");
713 // Don't draw video if picon is bigger than edit
714 if(picon_w > edit_w) return;
716 //printf("ResourcePixmap::draw_video_resource 1\n");
717 // pixels spanned by a frame
718 double frame_w = edit->frame_w();
720 //printf("ResourcePixmap::draw_video_resource 1\n");
721 // Frames spanned by a picon
722 double frames_per_picon = edit->frames_per_picon();
724 //printf("ResourcePixmap::draw_video_resource 1\n");
725 // Current pixel relative to pixmap
728 if(mwindow->edl->session->show_titles)
729 y += mwindow->theme->title_bg_data->get_h();
730 // Frame in project touched by current pixel
731 int64_t project_frame;
733 // Get first frame touched by x and fix x to start of frame
734 if(frames_per_picon > 1)
736 int picon = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) / picon_w);
737 x = picon_w * picon + edit_x - pixmap_x;
738 project_frame = Units::to_int64((double)picon * frames_per_picon);
742 project_frame = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) /
744 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
747 //printf("ResourcePixmap::draw_video_resource 1 %s\n", edit->asset->path);
748 File *source = mwindow->video_cache->check_out(edit->asset);
752 //printf("ResourcePixmap::draw_video_resource 2 project_frame=%d frame_w=%f refresh_x=%d refresh_w=%d x=%d\n",
753 //project_frame, frame_w, refresh_x, refresh_w, x);
754 while(x < refresh_x + refresh_w)
756 int64_t source_frame = project_frame + edit->startsource;
757 source->set_layer(edit->channel);
758 source->set_video_position(source_frame,
759 mwindow->edl->session->frame_rate);
761 // Try displaying from source cache
762 FrameCache *frame_cache = source->get_frame_cache();
763 VFrame *picon_frame = 0;
766 //frame_cache->dump();
767 if((picon_frame = frame_cache->get_frame_ptr(source_frame,
768 mwindow->edl->session->frame_rate,
776 // Display from file and put in cache
778 if(canvas->temp_picon &&
779 (canvas->temp_picon->get_w() != edit->asset->width ||
780 canvas->temp_picon->get_h() != edit->asset->height))
782 delete canvas->temp_picon;
783 canvas->temp_picon = 0;
786 if(!canvas->temp_picon)
788 canvas->temp_picon = new VFrame(0,
794 source->read_frame(canvas->temp_picon);
795 picon_frame = new VFrame(0, picon_w, picon_h, BC_RGB888);
796 frame_cache->put_frame(picon_frame,
798 mwindow->edl->session->frame_rate,
800 cmodel_transfer(picon_frame->get_rows(),
801 canvas->temp_picon->get_rows(),
810 canvas->temp_picon->get_w(),
811 canvas->temp_picon->get_h(),
814 picon_frame->get_w(),
815 picon_frame->get_h(),
819 canvas->temp_picon->get_bytes_per_line(),
820 picon_frame->get_bytes_per_line());
823 draw_vframe(picon_frame,
832 frame_cache->unlock();
834 if(frames_per_picon > 1)
836 x += Units::round(picon_w);
837 project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
841 x += Units::round(frame_w);
842 project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
846 canvas->test_timer();
851 mwindow->video_cache->check_in(edit->asset);
856 void ResourcePixmap::dump()
858 printf("ResourcePixmap %p\n", this);
859 printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);