You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Adding new Clear() method to Timeline, to delete all allocated clips, effects, and frame mapeprs (freeing memory). Also, keep track of allocated clips and effects on timeline (when using SetJson to create them), so we can clean them up correctly on Clear() or RemoveClip()/RemoveEffect(). Added new test case for Clear().
This commit is contained in:
108
src/Timeline.cpp
108
src/Timeline.cpp
@@ -208,23 +208,14 @@ Timeline::~Timeline() {
|
||||
// Auto Close if not already
|
||||
Close();
|
||||
|
||||
// Free all allocated frame mappers
|
||||
std::set<FrameMapper *>::iterator it;
|
||||
for (it = allocated_frame_mappers.begin(); it != allocated_frame_mappers.end(); ) {
|
||||
// Dereference and clean up FrameMapper object
|
||||
FrameMapper *mapper = (*it);
|
||||
mapper->Reader(NULL);
|
||||
mapper->Close();
|
||||
delete mapper;
|
||||
// Remove reference and proceed to next element
|
||||
it = allocated_frame_mappers.erase(it);
|
||||
}
|
||||
// Remove all clips, effects, and frame mappers
|
||||
Clear();
|
||||
|
||||
// Destroy previous cache (if managed by timeline)
|
||||
if (managed_cache && final_cache) {
|
||||
delete final_cache;
|
||||
final_cache = NULL;
|
||||
}
|
||||
// Destroy previous cache (if managed by timeline)
|
||||
if (managed_cache && final_cache) {
|
||||
delete final_cache;
|
||||
final_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the tracked_objects map a pointer to a tracked object (TrackedObjectBBox)
|
||||
@@ -375,12 +366,26 @@ void Timeline::AddEffect(EffectBase* effect)
|
||||
void Timeline::RemoveEffect(EffectBase* effect)
|
||||
{
|
||||
effects.remove(effect);
|
||||
|
||||
// Delete effect object (if timeline allocated it)
|
||||
bool allocated = allocated_effects.count(effect);
|
||||
if (allocated) {
|
||||
delete effect;
|
||||
effect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove an openshot::Clip to the timeline
|
||||
void Timeline::RemoveClip(Clip* clip)
|
||||
{
|
||||
clips.remove(clip);
|
||||
|
||||
// Delete clip object (if timeline allocated it)
|
||||
bool allocated = allocated_clips.count(clip);
|
||||
if (allocated) {
|
||||
delete clip;
|
||||
clip = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Look up a clip
|
||||
@@ -473,6 +478,10 @@ void Timeline::apply_mapper_to_clip(Clip* clip)
|
||||
// Get the existing reader
|
||||
clip_reader = (ReaderBase*) clip->Reader();
|
||||
|
||||
// Update the mapping
|
||||
FrameMapper* clip_mapped_reader = (FrameMapper*) clip_reader;
|
||||
clip_mapped_reader->ChangeMapping(info.fps, PULLDOWN_NONE, info.sample_rate, info.channels, info.channel_layout);
|
||||
|
||||
} else {
|
||||
|
||||
// Create a new FrameMapper to wrap the current reader
|
||||
@@ -481,10 +490,6 @@ void Timeline::apply_mapper_to_clip(Clip* clip)
|
||||
clip_reader = (ReaderBase*) mapper;
|
||||
}
|
||||
|
||||
// Update the mapping
|
||||
FrameMapper* clip_mapped_reader = (FrameMapper*) clip_reader;
|
||||
clip_mapped_reader->ChangeMapping(info.fps, PULLDOWN_NONE, info.sample_rate, info.channels, info.channel_layout);
|
||||
|
||||
// Update clip reader
|
||||
clip->Reader(clip_reader);
|
||||
}
|
||||
@@ -763,6 +768,49 @@ void Timeline::sort_effects()
|
||||
effects.sort(CompareEffects());
|
||||
}
|
||||
|
||||
// Clear all clips from timeline
|
||||
void Timeline::Clear()
|
||||
{
|
||||
ZmqLogger::Instance()->AppendDebugMethod("Timeline::Clear");
|
||||
|
||||
// Close all open clips
|
||||
for (auto clip : clips)
|
||||
{
|
||||
update_open_clips(clip, false);
|
||||
|
||||
// Delete clip object (if timeline allocated it)
|
||||
bool allocated = allocated_clips.count(clip);
|
||||
if (allocated) {
|
||||
delete clip;
|
||||
clip = NULL;
|
||||
}
|
||||
}
|
||||
// Clear all clips
|
||||
clips.clear();
|
||||
|
||||
// Close all effects
|
||||
for (auto effect : effects)
|
||||
{
|
||||
// Delete effect object (if timeline allocated it)
|
||||
bool allocated = allocated_effects.count(effect);
|
||||
if (allocated) {
|
||||
delete effect;
|
||||
effect = NULL;
|
||||
}
|
||||
}
|
||||
// Clear all effects
|
||||
effects.clear();
|
||||
|
||||
// Delete all FrameMappers
|
||||
for (auto mapper : allocated_frame_mappers)
|
||||
{
|
||||
mapper->Reader(NULL);
|
||||
mapper->Close();
|
||||
delete mapper;
|
||||
}
|
||||
allocated_frame_mappers.clear();
|
||||
}
|
||||
|
||||
// Close the reader (and any resources it was consuming)
|
||||
void Timeline::Close()
|
||||
{
|
||||
@@ -1072,7 +1120,7 @@ void Timeline::SetJson(const std::string value) {
|
||||
// Load Json::Value into this object
|
||||
void Timeline::SetJsonValue(const Json::Value root) {
|
||||
|
||||
// Close timeline before we do anything (this also removes all open and closing clips)
|
||||
// Close timeline before we do anything (this closes all clips)
|
||||
bool was_open = is_open;
|
||||
Close();
|
||||
|
||||
@@ -1092,6 +1140,9 @@ void Timeline::SetJsonValue(const Json::Value root) {
|
||||
// Create Clip
|
||||
Clip *c = new Clip();
|
||||
|
||||
// Keep track of allocated clip objects
|
||||
allocated_clips.insert(c);
|
||||
|
||||
// When a clip is attached to an object, it searches for the object
|
||||
// on it's parent timeline. Setting the parent timeline of the clip here
|
||||
// allows attaching it to an object when exporting the project (because)
|
||||
@@ -1120,6 +1171,9 @@ void Timeline::SetJsonValue(const Json::Value root) {
|
||||
// Create instance of effect
|
||||
if ( (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) ) {
|
||||
|
||||
// Keep track of allocated effect objects
|
||||
allocated_effects.insert(e);
|
||||
|
||||
// Load Json into Effect
|
||||
e->SetJsonValue(existing_effect);
|
||||
|
||||
@@ -1255,9 +1309,14 @@ void Timeline::apply_json_to_clips(Json::Value change) {
|
||||
// Determine type of change operation
|
||||
if (change_type == "insert") {
|
||||
|
||||
// Create new clip
|
||||
// Create clip
|
||||
Clip *clip = new Clip();
|
||||
clip->SetJsonValue(change["value"]); // Set properties of new clip from JSON
|
||||
|
||||
// Keep track of allocated clip objects
|
||||
allocated_clips.insert(clip);
|
||||
|
||||
// Set properties of clip from JSON
|
||||
clip->SetJsonValue(change["value"]);
|
||||
AddClip(clip); // Add clip to timeline
|
||||
|
||||
// Apply framemapper (or update existing framemapper)
|
||||
@@ -1363,6 +1422,9 @@ void Timeline::apply_json_to_effects(Json::Value change, EffectBase* existing_ef
|
||||
// Init the matching effect object
|
||||
if ( (e = EffectInfo().CreateEffect(effect_type)) ) {
|
||||
|
||||
// Keep track of allocated effect objects
|
||||
allocated_effects.insert(e);
|
||||
|
||||
// Load Json into Effect
|
||||
e->SetJsonValue(change["value"]);
|
||||
|
||||
|
||||
@@ -154,7 +154,9 @@ namespace openshot {
|
||||
std::list<openshot::Clip*> clips; ///<List of clips on this timeline
|
||||
std::list<openshot::Clip*> closing_clips; ///<List of clips that need to be closed
|
||||
std::map<openshot::Clip*, openshot::Clip*> open_clips; ///<List of 'opened' clips on this timeline
|
||||
std::set<openshot::Clip*> allocated_clips; ///<List of clips that were allocated by this timeline
|
||||
std::list<openshot::EffectBase*> effects; ///<List of clips on this timeline
|
||||
std::set<openshot::EffectBase*> allocated_effects; ///<List of effects that were allocated by this timeline
|
||||
openshot::CacheBase *final_cache; ///<Final cache of timeline frames
|
||||
std::set<openshot::FrameMapper*> allocated_frame_mappers; ///< all the frame mappers we allocated and must free
|
||||
bool managed_cache; ///< Does this timeline instance manage the cache object
|
||||
@@ -258,6 +260,9 @@ namespace openshot {
|
||||
/// @brief Automatically map all clips to the timeline's framerate and samplerate
|
||||
void AutoMapClips(bool auto_map) { auto_map_clips = auto_map; };
|
||||
|
||||
/// Clear all clips, effects, and frame mappers from timeline (and free memory)
|
||||
void Clear();
|
||||
|
||||
/// Clear all cache for this timeline instance, including all clips' cache
|
||||
/// @param deep If True, clear all FrameMappers and nested Readers (QtImageReader, FFmpegReader, etc...)
|
||||
void ClearAllCache(bool deep=false);
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user