Skip to content

Commit 266092e

Browse files
authored
Merge pull request #5205 from OpenShot/sentry-invalid-property-data
Prevent Crash in Object Detector and Tracker effects (due to child clip id)
2 parents 1e07ee3 + e0af3c5 commit 266092e

File tree

4 files changed

+153
-164
lines changed

4 files changed

+153
-164
lines changed

src/classes/timeline.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def changed(self, action):
7979
return
8080

8181
# Disable video caching temporarily
82+
caching_value = openshot.Settings.Instance().ENABLE_PLAYBACK_CACHING
8283
openshot.Settings.Instance().ENABLE_PLAYBACK_CACHING = False
8384

8485
try:
@@ -111,8 +112,8 @@ def changed(self, action):
111112
log.info("Error applying JSON to timeline object in libopenshot: %s. %s" %
112113
(e, action.json(is_array=True)))
113114

114-
# Enable video caching
115-
openshot.Settings.Instance().ENABLE_PLAYBACK_CACHING = True
115+
# Resume video caching original value
116+
openshot.Settings.Instance().ENABLE_PLAYBACK_CACHING = caching_value
116117

117118
def MaxSizeChangedCB(self, new_size):
118119
"""Callback for max sized change (i.e. max size of video widget)"""

src/windows/models/properties_model.py

+42-16
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,11 @@ def remove_keyframe(self, item):
208208
# Create reference
209209
clip_data = c.data
210210
if object_id:
211-
clip_data = c.data.get('objects').get(object_id)
211+
objects = c.data.get('objects', {})
212+
clip_data = objects.pop(object_id, {})
213+
if not clip_data:
214+
log.debug("No clip data found for this object id")
215+
return
212216

213217
if property_key in clip_data: # Update clip attribute
214218
log_id = "{}/{}".format(clip_id, object_id) if object_id else clip_id
@@ -281,13 +285,17 @@ def remove_keyframe(self, item):
281285
has_waveform = True
282286

283287
# Reduce # of clip properties we are saving (performance boost)
284-
clip_data = {property_key: clip_data[property_key]}
285-
if object_id:
286-
clip_data = {'objects': {object_id: clip_data}}
288+
if not object_id:
289+
clip_data = {property_key: clip_data.get(property_key)}
290+
else:
291+
# If objects dict detected - don't reduce the # of objects
292+
objects[object_id] = clip_data
293+
clip_data = {'objects': objects}
287294

288295
# Save changes
289296
if clip_updated:
290297
# Save
298+
c.data = clip_data
291299
c.save()
292300

293301
# Update waveforms (if needed)
@@ -331,7 +339,11 @@ def color_update(self, item, new_color, interpolation=-1, interpolation_details=
331339
# Create reference
332340
clip_data = c.data
333341
if object_id:
334-
clip_data = c.data.get('objects').get(object_id)
342+
objects = c.data.get('objects', {})
343+
clip_data = objects.pop(object_id, {})
344+
if not clip_data:
345+
log.debug("No clip data found for this object id")
346+
return
335347

336348
# Update clip attribute
337349
if property_key in clip_data:
@@ -403,13 +415,17 @@ def color_update(self, item, new_color, interpolation=-1, interpolation_details=
403415
})
404416

405417
# Reduce # of clip properties we are saving (performance boost)
406-
clip_data = {property_key: clip_data[property_key]}
407-
if object_id:
408-
clip_data = {'objects': {object_id: clip_data}}
418+
if not object_id:
419+
clip_data = {property_key: clip_data.get(property_key)}
420+
else:
421+
# If objects dict detected - don't reduce the # of objects
422+
objects[object_id] = clip_data
423+
clip_data = {'objects': objects}
409424

410425
# Save changes
411426
if clip_updated:
412427
# Save
428+
c.data = clip_data
413429
c.save()
414430

415431
# Update the preview
@@ -434,12 +450,15 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
434450
property_type = property[1]["type"]
435451
property_key = property[0]
436452
object_id = property[1]["object_id"]
453+
objects = {}
437454
clip_id, item_type = item.data()
438455

439456
# Get value (if any)
440-
if item.text():
457+
if item.text() or value:
441458
# Set and format value based on property type
442-
if value is not None:
459+
if value == "None":
460+
new_value = ""
461+
elif value is not None:
443462
# Override value
444463
new_value = value
445464
elif property_type == "string":
@@ -478,12 +497,16 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
478497
# Get effect object
479498
c = Effect.get(id=clip_id)
480499

481-
if c:
500+
if c and c.data:
482501

483502
# Create reference
484503
clip_data = c.data
485504
if object_id:
486-
clip_data = c.data.get('objects').get(object_id)
505+
objects = c.data.get('objects', {})
506+
clip_data = objects.pop(object_id, {})
507+
if not clip_data:
508+
log.debug("No clip data found for this object id")
509+
return
487510

488511
# Update clip attribute
489512
if property_key in clip_data:
@@ -616,9 +639,12 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
616639
has_waveform = True
617640

618641
# Reduce # of clip properties we are saving (performance boost)
619-
clip_data = {property_key: clip_data.get(property_key)}
620-
if object_id:
621-
clip_data = {'objects': {object_id: clip_data}}
642+
if not object_id:
643+
clip_data = {property_key: clip_data.get(property_key)}
644+
else:
645+
# If objects dict detected - don't reduce the # of objects
646+
objects[object_id] = clip_data
647+
clip_data = {'objects': objects}
622648

623649
# Save changes
624650
if clip_updated:
@@ -766,7 +792,7 @@ def set_property(self, property, filter, c, item_type, object_id=None):
766792
# Append ROW to MODEL (if does not already exist in model)
767793
self.model.appendRow(row)
768794

769-
else:
795+
elif name in self.items and self.items[name]["row"]:
770796
# Update the value of the existing model
771797
# Get 1st Column
772798
col = self.items[name]["row"][0]

src/windows/video_widget.py

+27-22
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ def paintEvent(self, event, *args):
381381

382382
# Set scale as STRETCH if the clip is attached to an object
383383
if (
384-
raw_properties.get('parentObjectId').get('memo') != 'None'
384+
raw_properties.get('parentObjectId').get('memo') != ''
385385
and len(raw_properties.get('parentObjectId').get('memo')) > 0
386386
):
387387
scale = openshot.SCALE_STRETCH
@@ -475,25 +475,26 @@ def paintEvent(self, event, *args):
475475
raw_properties_effect = json.loads(self.transforming_effect_object.PropertiesJSON(clip_frame_number))
476476
# Get properties for the first object in dict. PropertiesJSON should return one object at the time
477477
tmp = raw_properties_effect.get('objects')
478-
obj_id = list(tmp.keys())[0]
479-
raw_properties_effect = raw_properties_effect.get('objects').get(obj_id)
480-
481-
# Check if the tracked object is visible in this frame
482-
if raw_properties_effect.get('visible'):
483-
if raw_properties_effect.get('visible').get('value') == 1:
484-
# Get the selected bounding box values
485-
rotation = raw_properties_effect['rotation']['value']
486-
x1 = raw_properties_effect['x1']['value']
487-
y1 = raw_properties_effect['y1']['value']
488-
x2 = raw_properties_effect['x2']['value']
489-
y2 = raw_properties_effect['y2']['value']
490-
self.drawTransformHandler(
491-
painter,
492-
sx, sy,
493-
source_width, source_height,
494-
origin_x, origin_y,
495-
x1, y1, x2, y2,
496-
rotation)
478+
if tmp:
479+
obj_id = list(tmp.keys())[0]
480+
raw_properties_effect = raw_properties_effect.get('objects').get(obj_id)
481+
482+
# Check if the tracked object is visible in this frame
483+
if raw_properties_effect.get('visible'):
484+
if raw_properties_effect.get('visible').get('value') == 1:
485+
# Get the selected bounding box values
486+
rotation = raw_properties_effect['rotation']['value']
487+
x1 = raw_properties_effect['x1']['value']
488+
y1 = raw_properties_effect['y1']['value']
489+
x2 = raw_properties_effect['x2']['value']
490+
y2 = raw_properties_effect['y2']['value']
491+
self.drawTransformHandler(
492+
painter,
493+
sx, sy,
494+
source_width, source_height,
495+
origin_x, origin_y,
496+
x1, y1, x2, y2,
497+
rotation)
497498
else:
498499
self.drawTransformHandler(
499500
painter,
@@ -1055,10 +1056,14 @@ def mouseMoveEvent(self, event):
10551056
if self.transforming_effect_object.info.has_tracked_object:
10561057
# Get properties of effect at current frame
10571058
raw_properties = json.loads(self.transforming_effect_object.PropertiesJSON(clip_frame_number))
1059+
objects = raw_properties.get('objects', {})
1060+
if not objects:
1061+
return
1062+
10581063
# Get properties for the first object in dict.
10591064
# PropertiesJSON should return one object at the time
1060-
obj_id = list(raw_properties.get('objects').keys())[0]
1061-
raw_properties = raw_properties.get('objects').get(obj_id)
1065+
obj_id = list(objects.keys())[0]
1066+
raw_properties = objects.get(obj_id)
10621067

10631068
if not raw_properties.get('visible'):
10641069
self.mouse_position = event.pos()

0 commit comments

Comments
 (0)