The following is a patch so that when loading and pasting / dragging
onto timeline, etc.. the length of the inserted material is the minimum
of all the the tracks rounded to the nearest frame. This fixes issues
I (and others) have when working with mpeg files that audio and video of
different lengths.
It introduces an annoyance (that is resolve by turning off "align
cursor to frame" ) where a clip having tracks of intentionally different
frame length (that is already cut properly) will be pasted incorrectly..
Can people test before committing?
pierre
diff --git a/cinelerra/asset.C b/cinelerra/asset.C
index 1610374..2fc4772 100644
--- a/cinelerra/asset.C
+++ b/cinelerra/asset.C
@@ -3,6 +3,7 @@ #include "asset.h"
#include "assets.h"
#include "bchash.h"
#include "bcsignals.h"
+#include "clip.h"
#include "edl.h"
#include "file.h"
#include "filesystem.h"
@@ -1200,6 +1201,21 @@ int Asset::update_path(char *new_path)
return 0;
}
+double Asset::total_length_framealigned(double fps)
+{
+ if (video_data && audio_data) {
+ double aud = floor(( (double)audio_length / sample_rate) * fps) / fps;
+ double vid = floor(( (double)video_length / frame_rate) * fps) / fps;
+ return MIN(aud,vid);
+ }
+
+ if (audio_data)
+ return (double)audio_length / sample_rate;
+
+ if (video_data)
+ return (double)video_length / frame_rate;
+}
+
void Asset::update_index(Asset *asset)
{
//printf("Asset::update_index 1 %d\n", index_status);
diff --git a/cinelerra/asset.h b/cinelerra/asset.h
index ee289fa..8e3fd49 100644
--- a/cinelerra/asset.h
+++ b/cinelerra/asset.h
@@ -101,6 +101,8 @@ public:
int write_index(FileXML *xml);
int update_path(char *new_path);
+ double total_length_framealigned(double fps);
+
// Path to file
char path[BCTEXTLEN];
diff --git a/cinelerra/edits.C b/cinelerra/edits.C
index 35956ac..f9d6fb7 100644
--- a/cinelerra/edits.C
+++ b/cinelerra/edits.C
@@ -701,6 +701,8 @@ void Edits::clear(int64_t start, int64_t
}
optimize();
+// Reset the loaded_length value. (the last edit should always be a silence going to infinityish)
+ loaded_length = last->startproject;
}
// Used by edit handle and plugin handle movement but plugin handle movement
diff --git a/cinelerra/mwindowedit.C b/cinelerra/mwindowedit.C
index bf5e2e0..c5b341a 100644
--- a/cinelerra/mwindowedit.C
+++ b/cinelerra/mwindowedit.C
@@ -1421,6 +1421,12 @@ SET_TRACE
edl->session->frame_rate,
TRACK_VIDEO);
+// Align cursor on frames:: clip the new edl to paste to the last joint frame.
+ if (edl->session->cursor_on_frames)
+ {
+ edl_length = new_edl->tracks->total_length_framealigned(edl->session->frame_rate);
+ new_edl->tracks->clear(edl_length, new_edl->tracks->total_length() + 100, 1);
+ }
SET_TRACE
diff --git a/cinelerra/track.C b/cinelerra/track.C
index 00e893f..4d8333b 100644
--- a/cinelerra/track.C
+++ b/cinelerra/track.C
@@ -1148,6 +1148,7 @@ int Track::clear(double start,
if(edit_edits)
edits->clear((int64_t)start, (int64_t)end);
+
return 0;
}
diff --git a/cinelerra/trackcanvas.C b/cinelerra/trackcanvas.C
index 04dad9a..56277df 100644
--- a/cinelerra/trackcanvas.C
+++ b/cinelerra/trackcanvas.C
@@ -1097,6 +1097,67 @@ void TrackCanvas::draw_paste_destination
mwindow->session->drag_clips->total)
clip = mwindow->session->drag_clips->values[0];
+// 'Align cursor of frame' lengths calculations
+ double paste_audio_length, paste_video_length;
+ int64_t asset_length;
+ double desta_position = 0;
+ double destv_position = 0;
+
+ if (asset)
+ {
+ double asset_length_ac = asset->total_length_framealigned(mwindow->edl->session->frame_rate);
+ if (mwindow->edl->session->cursor_on_frames)
+ {
+ paste_video_length = paste_audio_length = asset_length_ac;
+ }
+ else
+ {
+ paste_audio_length = (double)asset->audio_length / asset->sample_rate;
+ paste_video_length = (double)asset->video_length / asset->frame_rate;
+ }
+
+ // Images have length -1 (they are a single image!!)
+ if (asset->video_data && asset->video_length < 0)
+ {
+ if(mwindow->edl->session->si_useduration)
+ paste_video_length = mwindow->edl->session->si_duration / asset->frame_rate;
+ else
+ paste_video_length = 1.0 / asset->frame_rate; // bit confused!! (this is 1 frame)
+ }
+
+ int64_t asset_length = 0;
+
+ if(asset->audio_data)
+ {
+ // we use video if we are over video and audio if we are over audio
+ if(asset->video_data && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
+ asset_length = mwindow->session->track_highlighted->to_units(paste_video_length, 1);
+ else
+ asset_length = mwindow->session->track_highlighted->to_units(paste_audio_length, 1);
+
+ desta_position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+ }
+
+ if(asset->video_data)
+ {
+ asset_length = mwindow->session->track_highlighted->to_units((double)paste_video_length, 1);
+ destv_position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+ }
+ }
+
+ if(clip)
+ {
+ if(mwindow->edl->session->cursor_on_frames)
+ paste_audio_length = paste_video_length = clip->tracks->total_length_framealigned(mwindow->edl->session->frame_rate);
+ else
+ paste_audio_length = paste_video_length = clip->tracks->total_length();
+
+ int64_t asset_length;
+
+ asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 1);
+ desta_position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+ }
+
// Get destination track
for(Track *dest = mwindow->session->track_highlighted;
dest;
@@ -1119,51 +1180,14 @@ void TrackCanvas::draw_paste_destination
if(dest->data_type == TRACK_AUDIO)
{
- if(asset && current_atrack < asset->channels)
- {
- w = Units::to_int64((double)asset->audio_length /
- asset->sample_rate *
- mwindow->edl->session->sample_rate /
- mwindow->edl->local_session->zoom_sample);
-
- // FIXME: more obvious, get_drop_position should be called only ONCE - for highlighted track
- int64_t asset_length;
- // we use video if we are over video and audio if we are over audio
- if (asset->video_data && mwindow->session->track_highlighted->data_type == TRACK_VIDEO)
- {
- // Images have length -1
- double video_length = asset->video_length;
- if (video_length < 0)
- {
- if(mwindow->edl->session->si_useduration)
- video_length = mwindow->edl->session->si_duration;
- else
- video_length = 1.0 / mwindow->edl->session->frame_rate ;
- }
- asset_length = mwindow->session->track_highlighted->to_units(video_length / asset->frame_rate, 1);
- }
- else
- asset_length = mwindow->session->track_highlighted->to_units(asset->audio_length / asset->sample_rate, 1);
-
- position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
- if (position < 0)
- w = -1;
- else
- {
- current_atrack++;
- draw_box = 1;
- }
- }
- else
- if(clip && current_atrack < clip->tracks->total_audio_tracks())
+ if( (asset && current_atrack < asset->channels)
+ || (clip && current_atrack < clip->tracks->total_audio_tracks()) )
{
- w = Units::to_int64((double)clip->tracks->total_length() *
+ w = Units::to_int64(paste_audio_length *
mwindow->edl->session->sample_rate /
mwindow->edl->local_session->zoom_sample);
-//printf("draw_paste_destination %d\n", x);
- int64_t asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 1);
- position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+ position = desta_position;
if (position < 0)
w = -1;
else
@@ -1201,42 +1225,15 @@ void TrackCanvas::draw_paste_destination
if(dest->data_type == TRACK_VIDEO)
{
//printf("draw_paste_destination 1\n");
- if(asset && current_vtrack < asset->layers)
+ if( (asset && current_vtrack < asset->layers)
+ || (clip && current_vtrack < clip->tracks->total_video_tracks()) )
{
// Images have length -1
- double video_length = asset->video_length;
- if (video_length < 0)
- {
- if(mwindow->edl->session->si_useduration)
- video_length = mwindow->edl->session->si_duration;
- else
- video_length = 1.0 / mwindow->edl->session->frame_rate ;
- }
- w = Units::to_int64((double)video_length /
- asset->frame_rate *
+ w = Units::to_int64((double)paste_video_length *
mwindow->edl->session->sample_rate /
mwindow->edl->local_session->zoom_sample);
- int64_t asset_length = mwindow->session->track_highlighted->to_units((double)video_length /
- asset->frame_rate, 1);
-
- position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
- if (position < 0)
- w = -1;
- else
- {
- current_vtrack++;
- draw_box = 1;
- }
- }
- else
- if(clip && current_vtrack < clip->tracks->total_video_tracks())
- {
- w = Units::to_int64(clip->tracks->total_length() *
- mwindow->edl->session->sample_rate /
- mwindow->edl->local_session->zoom_sample);
- int64_t asset_length = mwindow->session->track_highlighted->to_units((double)clip->tracks->total_length(), 1);
- position = mwindow->session->track_highlighted->from_units(get_drop_position(&insertion, NULL, asset_length));
+ position = destv_position;
if (position < 0)
w = -1;
else
diff --git a/cinelerra/tracks.C b/cinelerra/tracks.C
index bf4d619..c9a8326 100644
--- a/cinelerra/tracks.C
+++ b/cinelerra/tracks.C
@@ -1,6 +1,7 @@
#include "atrack.h"
#include "automation.h"
#include "cursor.h"
+#include "clip.h"
#include "bchash.h"
#include "edit.h"
#include "edits.h"
@@ -442,6 +443,17 @@ double Tracks::total_length()
return total;
}
+double Tracks::total_audio_length()
+{
+ double total = 0;
+ for(Track *current = first; current; current = NEXT)
+ {
+ if(current->data_type == TRACK_AUDIO &&
+ current->get_length() > total) total = current->get_length();
+ }
+ return total;
+}
+
double Tracks::total_video_length()
{
double total = 0;
@@ -453,6 +465,19 @@ double Tracks::total_video_length()
return total;
}
+double Tracks::total_length_framealigned(double fps)
+{
+ if (total_audio_tracks() && total_video_tracks())
+ return MIN(floor(total_audio_length()*fps), floor(total_video_length()*fps))/ fps;
+
+ if (total_audio_tracks())
+ return floor(total_audio_length()*fps) / fps;
+
+ if (total_video_tracks())
+ return floor(total_video_length()*fps) / fps;
+
+ return 0;
+}
void Tracks::translate_camera(float offset_x, float offset_y)
{
diff --git a/cinelerra/tracks.h b/cinelerra/tracks.h
index 876140b..5c2abba 100644
--- a/cinelerra/tracks.h
+++ b/cinelerra/tracks.h
@@ -67,7 +67,9 @@ public:
int total_video_tracks();
// return the longest track in all the tracks in seconds
double total_length();
+ double total_audio_length();
double total_video_length();
+ double total_length_framealigned(double fps);
// Update y pixels after a zoom
void update_y_pixels(Theme *theme);
// Total number of tracks where the following toggles are selected