6 #include "colormodels.h"
11 #include "edlsession.h"
13 #include "filesystem.h"
14 #include "indexfile.h"
15 #include "localsession.h"
17 #include "resourcepixmap.h"
20 #include "trackcanvas.h"
26 #define _(String) gettext(String)
27 #define gettext_noop(String) String
28 #define N_(String) gettext_noop (String)
31 ResourcePixmap::ResourcePixmap(MWindow *mwindow,
36 : BC_Pixmap(canvas, w, h)
40 this->mwindow = mwindow;
41 this->canvas = canvas;
42 startsource = edit->startsource;
43 data_type = edit->track->data_type;
44 source_framerate = edit->asset->frame_rate;
45 project_framerate = edit->edl->session->frame_rate;
46 source_samplerate = edit->asset->sample_rate;
47 project_samplerate = edit->edl->session->sample_rate;
51 ResourcePixmap::~ResourcePixmap()
56 void ResourcePixmap::reset()
68 void ResourcePixmap::resize(int w, int h)
70 int new_w = (w > get_w()) ? w : get_w();
71 int new_h = (h > get_h()) ? h : get_h();
73 BC_Pixmap::resize(new_w, new_h);
76 void ResourcePixmap::draw_data(Edit *edit,
85 // Get new areas to fill in relative to pixmap
86 // Area to redraw relative to pixmap
87 int refresh_x = 0, refresh_w = 0;
88 int64_t index_zoom = 0;
90 //printf("ResourcePixmap::draw_data 1\n");
93 IndexFile indexfile(mwindow);
94 if(!indexfile.open_index(edit->asset))
96 index_zoom = edit->asset->index_zoom;
97 indexfile.close_index();
101 //printf("ResourcePixmap::draw_data 10\n");
103 if(mwindow->edl->session->show_titles) y += mwindow->theme->title_bg_data->get_h();
104 Track *track = edit->edits->track;
106 //printf("ResourcePixmap::draw_data 20\n");
110 if(edit->startsource != this->startsource ||
111 (data_type == TRACK_AUDIO &&
112 edit->asset->sample_rate != source_samplerate) ||
113 (data_type == TRACK_VIDEO &&
114 !EQUIV(edit->asset->frame_rate, source_framerate)) ||
115 mwindow->edl->session->sample_rate != project_samplerate ||
116 mwindow->edl->session->frame_rate != project_framerate ||
117 mwindow->edl->local_session->zoom_sample != zoom_sample ||
118 mwindow->edl->local_session->zoom_track != zoom_track ||
119 this->pixmap_h != pixmap_h ||
120 (data_type == TRACK_AUDIO &&
121 mwindow->edl->local_session->zoom_y != zoom_y) ||
123 (indexes_only && mwindow->edl->local_session->zoom_sample >= index_zoom))
126 refresh_w = pixmap_w;
130 // Start translated right
131 if(pixmap_w == this->pixmap_w && edit_x < this->edit_x && edit_w != pixmap_w)
133 refresh_w = this->edit_x - edit_x;
134 refresh_x = this->pixmap_w - refresh_w;
136 // Moved completely off the pixmap
137 if(refresh_w > this->pixmap_w)
139 refresh_w = this->pixmap_w;
147 mwindow->edl->local_session->zoom_track,
153 // Start translated left
154 if(pixmap_w == this->pixmap_w && edit_x > this->edit_x && edit_w != pixmap_w)
157 refresh_w = edit_x - this->edit_x;
159 // Moved completely off the pixmap
160 if(refresh_w > this->pixmap_w)
162 refresh_w = this->pixmap_w;
168 this->pixmap_w - refresh_w,
169 mwindow->edl->local_session->zoom_track,
175 // Start translated right and pixmap came off of right side
176 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x &&
177 this->edit_x + edit_w > this->pixmap_x + this->pixmap_w)
179 refresh_w = (this->edit_x + edit_w) - (this->pixmap_x + this->pixmap_w);
180 refresh_x = pixmap_w - refresh_w;
182 if(refresh_w >= pixmap_w)
185 refresh_w = pixmap_w;
189 copy_area(this->edit_x - edit_x,
191 pixmap_w - refresh_w,
192 mwindow->edl->local_session->zoom_track,
198 // Start translated right and reduced in size on the right.
199 if(pixmap_w < this->pixmap_w && edit_x < this->edit_x)
204 copy_area(this->pixmap_w - pixmap_w,
207 mwindow->edl->local_session->zoom_track,
212 // Start translated left and pixmap came off left side
213 if(edit_x >= 0 && this->edit_x < 0)
216 refresh_w = -this->edit_x;
218 if(refresh_w > pixmap_w)
220 refresh_w = pixmap_w;
227 mwindow->edl->local_session->zoom_track,
233 // Start translated left and reduced in size on the right
234 if(pixmap_w < this->pixmap_w && edit_x > this->edit_x)
240 // Start translated right and left went into left side.
241 if(pixmap_w > this->pixmap_w && edit_x < 0 && this->edit_x > 0)
243 refresh_w = pixmap_w - (edit_x + this->pixmap_w);
244 refresh_x = pixmap_w - refresh_w;
246 // Moved completely off new pixmap
247 if(refresh_w > pixmap_w)
249 refresh_w = pixmap_w;
257 mwindow->edl->local_session->zoom_track,
263 // Start translated right and increased in size on the right
264 if(pixmap_w > this->pixmap_w && edit_x <= this->edit_x)
266 refresh_w = pixmap_w - this->pixmap_w;
267 refresh_x = pixmap_w - refresh_w;
270 // Start translated left and increased in size on the right
271 if(pixmap_w > this->pixmap_w && edit_x > this->edit_x)
274 refresh_w = edit_x - this->edit_x;
276 // Moved completely off new pixmap
277 if(refresh_w > this->pixmap_w)
279 refresh_w = pixmap_w;
288 mwindow->edl->local_session->zoom_track,
295 //printf("ResourcePixmap::draw_data 50\n");
296 // Update pixmap settings
297 this->edit_id = edit->id;
298 this->startsource = edit->startsource;
299 this->source_framerate = edit->asset->frame_rate;
300 this->source_samplerate = edit->asset->sample_rate;
301 this->project_framerate = edit->edl->session->frame_rate;
302 this->project_samplerate = edit->edl->session->sample_rate;
303 this->edit_x = edit_x;
304 this->pixmap_x = pixmap_x;
305 this->pixmap_w = pixmap_w;
306 this->pixmap_h = pixmap_h;
307 this->zoom_sample = mwindow->edl->local_session->zoom_sample;
308 this->zoom_track = mwindow->edl->local_session->zoom_track;
309 this->zoom_y = mwindow->edl->local_session->zoom_y;
310 //printf("ResourcePixmap::draw_data 2 refresh_x1=%d refresh_w1=%d refresh_x2=%d refresh_w2=%d\n",
311 // refresh_x1, refresh_w1, refresh_x2, refresh_w2);
314 //printf("ResourcePixmap::draw_data 60\n");
316 // Draw in new background
318 mwindow->theme->draw_resource_bg(canvas,
325 refresh_x + refresh_w,
326 mwindow->edl->local_session->zoom_track + y);
327 //printf("ResourcePixmap::draw_data 70\n");
333 switch(track->data_type)
336 //printf("ResourcePixmap::draw_data 4\n");
337 draw_audio_resource(edit, refresh_x, refresh_w);
338 //printf("ResourcePixmap::draw_data 5\n");
342 //printf("ResourcePixmap::draw_data 6\n");
343 draw_video_resource(edit,
350 //printf("ResourcePixmap::draw_data 7\n");
356 if(mwindow->edl->session->show_titles)
357 draw_title(edit, edit_x, edit_w, pixmap_x, pixmap_w);
359 //printf("ResourcePixmap::draw_data 3 refresh_x=%d refresh_w=%d\n",
362 //printf("ResourcePixmap::draw_data 10\n");
365 void ResourcePixmap::draw_title(Edit *edit,
371 // coords relative to pixmap
372 int64_t total_x = edit_x - pixmap_x, total_w = edit_w;
373 int64_t x = total_x, w = total_w;
374 int left_margin = 10;
381 if(w > pixmap_w) w -= w - pixmap_w;
383 canvas->draw_3segmenth(x,
388 mwindow->theme->title_bg_data,
391 if(total_x > -BC_INFINITY)
393 char title[BCTEXTLEN], channel[BCTEXTLEN];
395 fs.extract_name(title, edit->asset->path);
397 sprintf(channel, " #%d", edit->channel + 1);
398 strcat(title, channel);
400 canvas->set_color(mwindow->theme->title_color);
401 canvas->set_font(mwindow->theme->title_font);
402 //printf("ResourcePixmap::draw_title 1 %d\n", total_x + 10);
404 // Justify the text on the left boundary of the edit if it is visible.
405 // Otherwise justify it on the left side of the screen.
406 int text_x = total_x + left_margin;
407 text_x = MAX(left_margin, text_x);
408 canvas->draw_text(text_x,
409 canvas->get_text_ascent(MEDIUMFONT_3D) + 2,
417 // Need to draw one more x
418 void ResourcePixmap::draw_audio_resource(Edit *edit, int x, int w)
421 double asset_over_session = (double)edit->asset->sample_rate /
422 mwindow->edl->session->sample_rate;
424 // Develop strategy for drawing
425 switch(edit->asset->index_status)
427 case INDEX_NOTTESTED:
430 // Disabled. Always draw from index.
432 draw_audio_source(edit, x, w);
437 IndexFile indexfile(mwindow);
438 if(!indexfile.open_index(edit->asset))
440 if(edit->asset->index_zoom >
441 mwindow->edl->local_session->zoom_sample *
443 draw_audio_source(edit, x, w);
445 indexfile.draw_index(this, edit, x, w);
446 indexfile.close_index();
470 void ResourcePixmap::draw_audio_source(Edit *edit, int x, int w)
472 File *source = mwindow->audio_cache->check_out(edit->asset);
476 printf(_("ResourcePixmap::draw_audio_source: failed to check out %s for drawing.\n"), edit->asset->path);
481 int64_t source_start = (pixmap_x - edit_x + x) * mwindow->edl->local_session->zoom_sample + edit->startsource;
482 int64_t source_len = w * mwindow->edl->local_session->zoom_sample;
483 int center_pixel = mwindow->edl->local_session->zoom_track / 2;
484 if(mwindow->edl->session->show_titles) center_pixel += mwindow->theme->title_bg_data->get_h();
485 double asset_over_session = (double)edit->asset->sample_rate /
486 mwindow->edl->session->sample_rate;
488 // Single sample zoom
489 if(mwindow->edl->local_session->zoom_sample == 1)
491 double oldsample, newsample;
492 int64_t total_source_samples = (int64_t)((double)(source_len + 1) *
494 double *buffer = new double[total_source_samples];
496 source->set_audio_position((int)((double)source_start *
498 edit->asset->sample_rate);
499 source->set_channel(edit->channel);
500 canvas->set_color(mwindow->theme->audio_color);
502 if(!source->read_samples(buffer,
503 total_source_samples,
504 edit->asset->sample_rate))
506 oldsample = newsample = *buffer;
507 for(int x1 = x, x2 = x + w, i = 0;
511 oldsample = newsample;
512 newsample = buffer[(int64_t)(i * asset_over_session)];
513 canvas->draw_line(x1 - 1,
514 (int)(center_pixel - oldsample * mwindow->edl->local_session->zoom_y / 2),
516 (int)(center_pixel - newsample * mwindow->edl->local_session->zoom_y / 2),
524 // Multiple sample zoom
526 int64_t fragmentsize;
527 int64_t buffersize = fragmentsize = 65536;
528 double *buffer = new double[buffersize + 1];
529 double highsample, lowsample;
530 float sample_of_pixel = 0;
531 int64_t total_source_samples = (int64_t)(source_len * asset_over_session);
532 double asset_samples_per_pixel =
533 mwindow->edl->local_session->zoom_sample *
541 source->set_audio_position((int64_t)(source_start * asset_over_session),
542 edit->asset->sample_rate);
543 source->set_channel(edit->channel);
544 canvas->set_color(mwindow->theme->audio_color);
546 for(int64_t source_sample = 0;
547 source_sample < total_source_samples;
548 source_sample += buffersize)
550 fragmentsize = buffersize;
551 if(total_source_samples - source_sample < buffersize)
552 fragmentsize = total_source_samples - source_sample;
554 if(source_sample == 0)
556 highsample = buffer[0];
557 lowsample = buffer[0];
560 if(!source->read_samples(buffer,
562 edit->asset->sample_rate))
566 // Draw samples for this buffer
567 for(int64_t bufferposition = 0;
568 bufferposition < fragmentsize;
572 if(asset_samples_per_pixel < 1)
575 int x2 = (int)(x + 1 / asset_samples_per_pixel);
577 highsample = lowsample = buffer[bufferposition];
578 y1 = (int)(center_pixel -
580 mwindow->edl->local_session->zoom_y /
582 y2 = (int)(center_pixel -
584 mwindow->edl->local_session->zoom_y /
594 if(asset_samples_per_pixel >= 1 &&
595 sample_of_pixel >= asset_samples_per_pixel)
597 // Draw column and reset
598 y1 = (int)(center_pixel -
600 mwindow->edl->local_session->zoom_y /
602 y2 = (int)(center_pixel -
604 mwindow->edl->local_session->zoom_y /
624 sample_of_pixel -= asset_samples_per_pixel;
626 lowsample = highsample = buffer[bufferposition];
631 if(sample_of_pixel >= 1)
633 // update lowsample and highsample
634 if(buffer[bufferposition] < lowsample)
635 lowsample = buffer[bufferposition];
637 if(buffer[bufferposition] > highsample)
638 highsample = buffer[bufferposition];
654 mwindow->audio_cache->check_in(edit->asset);
676 void ResourcePixmap::draw_video_resource(Edit *edit,
684 //printf("ResourcePixmap::draw_video_resource 1\n");
685 // pixels spanned by a picon
686 int64_t picon_w = Units::round(edit->picon_w());
687 int64_t picon_h = edit->picon_h();
689 //printf("ResourcePixmap::draw_video_resource 1\n");
690 // Don't draw video if picon is bigger than edit
691 if(picon_w > edit_w) return;
693 //printf("ResourcePixmap::draw_video_resource 1\n");
694 // pixels spanned by a frame
695 double frame_w = edit->frame_w();
697 //printf("ResourcePixmap::draw_video_resource 1\n");
698 // Frames spanned by a picon
699 double frames_per_picon = edit->frames_per_picon();
701 //printf("ResourcePixmap::draw_video_resource 1\n");
702 // Current pixel relative to pixmap
705 if(mwindow->edl->session->show_titles)
706 y += mwindow->theme->title_bg_data->get_h();
707 // Frame in project touched by current pixel
708 int64_t project_frame;
710 //printf("ResourcePixmap::draw_video_resource 1\n");
711 // Get first frame touched by x and fix x to start of frame
712 if(frames_per_picon > 1)
714 int picon = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) / picon_w);
715 x = picon_w * picon + edit_x - pixmap_x;
716 project_frame = Units::to_int64((double)picon * frames_per_picon);
720 project_frame = Units::to_int64((double)(refresh_x + pixmap_x - edit_x) /
722 x = Units::round((double)project_frame * frame_w + edit_x - pixmap_x);
725 //printf("ResourcePixmap::draw_video_resource 1 %s\n", edit->asset->path);
726 File *source = mwindow->video_cache->check_out(edit->asset);
727 //printf("ResourcePixmap::draw_video_resource 2\n");
731 //printf("ResourcePixmap::draw_video_resource 2 project_frame=%d frame_w=%f refresh_x=%d refresh_w=%d x=%d\n",
732 //project_frame, frame_w, refresh_x, refresh_w, x);
733 while(x < refresh_x + refresh_w)
735 int cache_hit; // so we know whether to relase a lock at the end or was it already
736 VFrame *final_picon_frame;
737 int64_t source_frame = project_frame + edit->startsource;
738 source->set_layer(edit->channel);
739 source->set_video_position(source_frame,
740 mwindow->edl->session->frame_rate);
741 //printf("ResourcePixmap::draw_video_resource 3 %p\n", source);
742 // VFrame *src = source->read_frame(BC_RGB888);
743 //printf("ResourcePixmap::draw_video_resource 4 %p\n", src);
744 source->frames_cache->enable_cache(); // we do enabling and disabling of cache
745 // on our own, so File doesn't use it's own caching
746 if ((final_picon_frame = source->frames_cache->get_frame(source->current_frame,
747 source->current_layer,
756 source->frames_cache->unlock_cache(); // implicitly locked
758 long now_current_frame = source->current_frame;
759 source->frames_cache->disable_cache();
760 VFrame *src = source->read_frame(BC_RGB888);
763 final_picon_frame = new VFrame (0,
767 cmodel_transfer(final_picon_frame->get_rows(),
769 final_picon_frame->get_y(),
770 final_picon_frame->get_u(),
771 final_picon_frame->get_v(),
783 src->get_color_model(),
789 source->frames_cache->enable_cache();
790 source->frames_cache->add_frame(now_current_frame,
791 source->current_layer,
793 1); // do not do a copy of frame. keep this one
794 source->frames_cache->disable_cache();
798 final_picon_frame = 0;
806 if(final_picon_frame)
807 draw_vframe(final_picon_frame,
816 source->frames_cache->unlock_cache(); // implicitly locked
821 if(frames_per_picon > 1)
823 x += Units::round(picon_w);
824 project_frame = Units::to_int64(frames_per_picon * (int64_t)((double)(x + pixmap_x - edit_x) / picon_w));
828 x += Units::round(frame_w);
829 project_frame = (int64_t)((double)(x + pixmap_x - edit_x) / frame_w);
835 mwindow->video_cache->check_in(edit->asset);
837 //printf("ResourcePixmap::draw_video_resource 5\n");
841 void ResourcePixmap::dump()
843 printf("ResourcePixmap %p\n", this);
844 printf(" edit %x edit_x %d pixmap_x %d pixmap_w %d visible %d\n", edit_id, edit_x, pixmap_x, pixmap_w, visible);