def test_delete_propetry(self): result_file = common.get_test_file('delete.aaf') with aaf2.open(result_file, 'w') as f: m = f.create.MasterMob() m['AppCode'].value = 14 m.usage = 'Usage_LowerLevel' f.content.mobs.append(m) with aaf2.open(result_file, 'rw') as f: mob = list(f.content.mobs)[0] assert 'AppCode' in mob assert 'UsageCode' in mob del mob['AppCode'] del mob['UsageCode'] assert 'AppCode' not in mob assert 'UsageCode' not in mob with self.assertRaises(KeyError): del mob['AppCode'] with aaf2.open(result_file, 'r') as f: mob = list(f.content.mobs)[0] assert 'AppCode' not in mob assert 'UsageCode' not in mob with self.assertRaises(KeyError): del mob['AppCode']
def test_add_extension_existing(self): test_file = common.get_test_file('extension_add_existing.aaf') shutil.copy(common.test_file_01(), test_file) original_pids = [] original_classdefs_count = None original_typedef_count = None with aaf2.open(test_file, 'r') as f: original_classdefs_count = len(f.metadict['ClassDefinitions']) original_typedef_count = len(f.metadict['TypeDefinitions']) for classdef in f.metadict['ClassDefinitions'].values(): # make sure non of the properties and dynamics for pdef in classdef['Properties'].values(): pid = pdef['LocalIdentification'].value if pdef['LocalIdentification'].value >= 0x8000: original_pids.append(pid) # open files 'rw' and add extensions with aaf2.open(test_file, 'rw', extensions=True) as f: pass all_pids = [] with aaf2.open(test_file, 'r') as f: new_classdefs_count = len(f.metadict['ClassDefinitions']) new_typedef_count = len(f.metadict['TypeDefinitions']) for classdef in f.metadict['ClassDefinitions'].values(): for pdef in classdef['Properties'].values(): pid = pdef['LocalIdentification'].value # make sure there are no duplicate pids self.assertTrue(pid not in all_pids) all_pids.append(pid) self.assertTrue(new_classdefs_count > original_classdefs_count) self.assertTrue(new_typedef_count > original_typedef_count)
def test_mobs(self): result_file = common.get_test_file('mobs.aaf') mobs = {} now = datetime.datetime.now() count = 100 with AAFFile(result_file, 'w') as f: for i in range(count): mob_id = MobID.new() m = f.create.MasterMob() m.name = "TestMob%d" % i m.mob_id = mob_id m['LastModified'].value = now m['CreationTime'].value = now m['Slots'].value = [] f.content.mobs.append(m) mobs[mob_id] = m.name with AAFFile(result_file, 'r') as f: # file_mobs = f.content['Mobs'].value for mob in f.content.mobs: assert mob.mob_id in mobs assert mob.name == mobs[mob.mob_id] assert len(list(f.content.mobs)) == count
def test_register(self): result_file = common.get_test_file('register_class.aaf') test_classdef_uuid = UUID(int=1) test_prop_uuid = UUID(int=42) test_prop_pid = 0xBEEF parent_class_name = 'EssenceDescriptor' with aaf2.open(result_file, 'w') as f: test_classdef = f.metadict.register_classdef( "TestClass", test_classdef_uuid, parent_class_name, True) assert isinstance(test_classdef, aaf2.metadict.ClassDef) p = test_classdef.register_propertydef("TheAnswer", test_prop_uuid, test_prop_pid, 'aafInt64', True, False) assert isinstance(p, aaf2.metadict.PropertyDef) with aaf2.open(result_file, 'r') as f: parent_classdef = f.metadict.lookup_classdef(parent_class_name) test_classdef = f.metadict.lookup_classdef('TestClass') self.assertTrue(test_classdef.uuid == test_classdef_uuid) self.assertTrue(test_classdef.class_name == "TestClass") self.assertTrue(test_classdef.parent is parent_classdef) p = test_classdef['Properties'].value[0] self.assertTrue(p.uuid == test_prop_uuid) self.assertTrue(p.pid == test_prop_pid) self.assertTrue(p.property_name == "TheAnswer") prop_typedef = f.metadict.lookup_typedef("aafInt64") self.assertTrue(p.typedef is prop_typedef)
def test_attach(self): result_file = common.get_test_file('attach.aaf') with aaf2.open(result_file, 'w') as f: mob = f.create.MasterMob() mob_id = mob.mob_id f.content.mobs.append(mob) with self.assertRaises(exceptions.AAFAttachError): f.content.mobs.append(mob) # dettach mob = f.content.mobs.pop(mob_id) assert mob assert len(f.content.mobs) == 0 f.content.mobs.append(mob) slot = mob.create_timeline_slot(25) slot.segment = f.create.Sequence() comp_paths = [] for i in range(10): filler = f.create.Filler() filler['DataDefinition'].value = f.dictionary.lookup_datadef( "picture") filler['Length'].value = i slot.segment['Components'].append(filler) comp_paths.append(filler.dir.path()) assert len(slot.segment['Components']) == 10 last = slot.segment['Components'].pop(-1) assert len(slot.segment['Components']) == 9 first = slot.segment['Components'].pop(0) assert len(slot.segment['Components']) == 8 for filler in slot.segment['Components']: assert filler.dir with self.assertRaises(exceptions.AAFAttachError): slot.segment['Components'][0] = slot.segment['Components'][1] mob = f.content.mobs.pop(mob_id) for filler in slot.segment['Components']: assert filler.dir is None assert slot.dir == None assert len(slot.segment['Components']) == 8 f.content.mobs.append(mob) slot.segment['Components'][0] = first assert slot.dir
def test_no_root_class(self): # make sure we don't write the root_class definition result_file = common.get_test_file('root_tess.aaf') with aaf2.open(result_file, 'w') as f: pass root_uuid = UUID('b3b398a5-1c90-11d4-8053-080036210804') with aaf2.open(result_file, 'r') as f: for classdef in f.metadict['ClassDefinitions'].value: self.assertFalse(classdef.class_name == "Root") self.assertFalse(classdef.uuid == root_uuid)
def test_empty_512(self): result_file = common.get_test_file("empty_512.aaf") with AAFFile(result_file, 'w', sector_size=512) as f: pass with AAFFile(result_file, 'r') as f: assert f.metadict assert f.content assert f.header['ObjectModelVersion'].value == 1 assert f.header['Version'].value == {u'major': 1, u'minor': 1}
def test_duplicate_pids_add(self): result_file = common.get_test_file('duplicate_pids_add.aaf') with aaf2.open(result_file, 'w', extensions=False) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'rw', extensions=True) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f))
def test_operationdef(self): result_file = common.get_test_file('operation_def.aaf') parm_id = uuid.uuid4() effect_id = uuid.uuid4() with aaf2.open(result_file, 'w') as f: typedef = f.dictionary.lookup_typedef("Rational") param = f.create.ParameterDef(parm_id, "AvidEffectID", "avid effect id", typedef) f.dictionary.register_def(param) op_def = f.create.OperationDef(effect_id, "MatteKey_2", "matte key def") op_def.media_kind = "Picture" f.dictionary.register_def(op_def) op_def['IsTimeWarp'].value = False op_def['Bypass'].value = 2 op_def['NumberInputs'].value = 3 op_def['OperationCategory'].value = "OperationCategory_Effect" op_def['ParametersDefined'].append(param) length = 100 operation = f.create.OperationGroup(op_def, length) mob = f.create.MasterMob() f.content.mobs.append(mob) slot = mob.create_picture_slot() slot.segment.components.append(operation) with aaf2.open(result_file, 'r') as f: param = f.dictionary.lookup_parameterdef('AvidEffectID') assert param.uuid == parm_id op_def = f.dictionary.lookup_operationdef("MatteKey_2") assert op_def.uuid == effect_id assert op_def.media_kind == 'Picture' assert op_def['IsTimeWarp'].value == False assert op_def['Bypass'].value == 2 assert op_def['NumberInputs'].value == 3 assert op_def[ 'OperationCategory'].value == "OperationCategory_Effect" assert param in op_def['ParametersDefined'].value mob = next(f.content.mobs.values()) slot = mob.slots.value[0] op = slot.segment.components.value[0] assert op.operation == op_def
def test_duplicate_pids_existing(self): result_file = common.get_test_file('duplicate_pids_existing.aaf') shutil.copy(common.test_file_01(), result_file) with aaf2.open(result_file, 'w', extensions=False) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'rw', extensions=True) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f))
def test_marker(self): result_file = common.get_test_file('descriptive_marker.aaf') described_slots = set([1, 2, 3, 4]) with aaf2.open(result_file, 'w') as f: ems = f.create.EventMobSlot() ems['EditRate'].value = '25' ems['SlotID'].value = 1000 # doesn't work in avid unless you specify # the same PhysicalTrackNumber as the target TimelineMobSlot. ems['PhysicalTrackNumber'].value = 1 sequence = f.create.Sequence("DescriptiveMetadata") marker = f.create.DescriptiveMarker() marker['DescribedSlots'].value = described_slots marker['Position'].value = 100 marker['Comment'].value = "This is a comment" marker['CommentMarkerUser'].value = "username" sequence.components.append(marker) ems.segment = sequence mob = f.create.CompositionMob() mob.name = "marker_sequence" p_slot = mob.create_picture_slot() filler = f.create.Filler() filler.media_kind = "picture" filler.length = 500 p_slot.segment.components.append(filler) p_slot['PhysicalTrackNumber'].value = 1 mob.slots.append(ems) f.content.mobs.append(mob) with aaf2.open(result_file, 'r') as f: mob = next(f.content.mobs.values()) slot = mob.slots.value[1] marker = slot.segment.components.value[0] assert marker['DescribedSlots'].value == described_slots assert marker['Position'].value == 100
def test_bad_timestamp(self): result_file = common.get_test_file('bad_timestamp.aaf') bad_timestamp = { u'date': { u'month': 0, u'day': 0, u'year': 0 }, u'time': datetime.time(0, 0) } # NOTE: in versions 1.1.0 and 1.0.2 of the AAF SDK it is # possible to have datetimes python cannot decode # SourceForge Bug ID #1191791 # https://sourceforge.net/p/aaf/bugs/90/ with aaf2.open(result_file, 'w') as f: f.header['LastModified'].value = bad_timestamp with aaf2.open(result_file, 'r') as f: assert f.header['LastModified'].value == bad_timestamp
def test_interpolationdef(self): result_file = common.get_test_file('interpolation_def.aaf') interpolation_id = uuid.uuid4() name = "TestInterp" with aaf2.open(result_file, 'w') as f: interpolation_id =interpolation_id interpolationdef = f.create.InterpolationDef(interpolation_id, name, "interpolation") f.dictionary.register_def(interpolationdef) varying_value = f.create.VaryingValue() varying_value['Interpolation'].value = interpolationdef assert interpolationdef is f.dictionary.lookup_interperlationdef(name) with aaf2.open(result_file, 'r') as f: interpolationdef = f.dictionary.lookup_interperlationdef(name) assert interpolationdef.auid == interpolation_id assert interpolationdef.name == name
def test_tagged_value(self): result_file = common.get_test_file('tagged_value.aaf') with aaf2.open(result_file, 'w') as f: t1 = f.create.TaggedValue("name1", 3221) typedef = f.dictionary.lookup_typedef("aafInt32") assert t1.value_typedef == typedef t2 = f.create.TaggedValue("name2", 45, 'aafInt64') typedef = f.dictionary.lookup_typedef("aafInt64") assert t2.value_typedef == typedef t3 = f.create.TaggedValue() t3.name = "name3" t3.encode_value("24000/10001", 'Rational') typedef = f.dictionary.lookup_typedef("Rational") assert t3.value_typedef == typedef
def test_add_extensions(self): result_file = common.get_test_file('basic_model.aaf') # create a file with basic model base_model_dynamic_pids = 0 with aaf2.open(result_file, 'w', extensions=False) as f: for classdef in f.metadict['ClassDefinitions'].values(): for pdef in classdef['Properties'].values(): if pdef['LocalIdentification'].value < 0x8000: base_model_dynamic_pids += 1 # check there are no extensions written_model_dynamic_pids = 0 with aaf2.open(result_file, 'r') as f: for classdef in f.metadict['ClassDefinitions'].values(): # make sure non of the properties and dynamics for pdef in classdef['Properties'].values(): if pdef['LocalIdentification'].value < 0x8000: written_model_dynamic_pids += 1 self.assertTrue(base_model_dynamic_pids == written_model_dynamic_pids) # open files 'rw' and add extensions with aaf2.open(result_file, 'rw', extensions=True) as f: pass dynamic_pids = set() # check that dynamic properties got added with aaf2.open(result_file, 'r') as f: for classdef in f.metadict['ClassDefinitions'].values(): for pdef in classdef['Properties'].values(): if pdef['LocalIdentification'].value >= 0x8000: pid = pdef['LocalIdentification'].value self.assertTrue(pid not in dynamic_pids) dynamic_pids.add(pid) assert len(dynamic_pids) > 0
def test_range_lock(self): frame_rate = '23.97' size = (960, 540) profile_name = 'dnxhr_lb' frames = 1600 overwrite = True sample = common.generate_dnxhd(profile_name, "%s-import.dnxhd" % profile_name, frames=frames, size=size, frame_rate=frame_rate, overwrite=overwrite) test_file = common.get_test_file("test-rangelock.aaf") with aaf2.open(test_file, 'wb+') as f: pass mobids = [] s = time.time() # generate a aaf file thats larger then 2gb with aaf2.open(test_file, 'rb+') as f: for v in range(30): start = time.time() mob = f.create.MasterMob("item-%d" % v) f.content.mobs.append(mob) mob.import_dnxhd_essence(sample, frame_rate) # print(v, time.time() - start) print('%d secs' % (time.time() - s)) with aaf2.open(test_file, 'r') as f: # print(RANGELOCKSECT) # print(len(f.cfb.fat)) # print(f.cfb.fat[RANGELOCKSECT]) assert f.cfb.fat[RANGELOCKSECT] == ENDOFCHAIN
def test_audio_transition(self): result_file = common.get_test_file('audio_transition.aaf') with aaf2.open(result_file, 'w') as f: register_definitions(f) comp = f.create.CompositionMob("Transition Timeline") comp.usage = 'Usage_TopLevel' f.content.mobs.append(comp) slot = comp.create_sound_slot() seq = f.create.Sequence('sound') slot.segment = seq filler = f.create.Filler('sound') filler.length = 50 seq.components.append(filler) t = create_audio_transition(f) seq.components.append(t) clip = create_audio_clip_import(f) clip.mob.name = "clip1" clip.length = 100 seq.components.append(clip) t = create_audio_transition(f) seq.components.append(t) filler = f.create.Filler('sound') filler.length = 50 seq.components.append(filler) with aaf2.open(result_file, 'r') as f: comp = next(f.content.toplevel()) slot = comp.slots[0] seq = slot.segment clip = seq.component_at_time(0) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(9) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(10) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(29) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(30) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(49) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(50) assert isinstance(clip, aaf2.components.SourceClip) assert clip.mob.name == 'clip1' clip = seq.component_at_time(69) assert isinstance(clip, aaf2.components.SourceClip) assert clip.mob.name == 'clip1' clip = seq.component_at_time(70) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(89) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(90) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(109) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(110) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(300) assert isinstance(clip, aaf2.components.Filler)
def test_create_sequence(self): result_file = common.get_test_file('create_sequence.aaf') mob_count = 0 components = 0 with aaf2.open(result_file, "w") as f: video_rate = " 30000/1001" comp_mob = f.create.CompositionMob() sequence = f.create.Sequence(media_kind="picture") timeline_slot = comp_mob.create_timeline_slot(video_rate) timeline_slot.segment = sequence f.content.mobs.append(comp_mob) length = 60 * 30 filler_len = 100 timecode_fps = 30 mob_count += 1 test_path = "some_path.mov" for i in range(10): # Make the Tape MOB tape_mob = f.create.SourceMob() tape_name = "tape_name" tape_slot, tape_timecode_slot = tape_mob.create_tape_slots( tape_name, video_rate, timecode_fps) tape_slot.segment.length = length f.content.mobs.append(tape_mob) mob_count += 1 # Make a FileMob file_mob = f.create.SourceMob() # Make a locator loc = f.create.NetworkLocator() loc['URLString'].value = test_path file_description = f.create.CDCIDescriptor() file_description.locator.append(loc) file_description['ComponentWidth'].value = 8 file_description['HorizontalSubsampling'].value = 4 file_description['ImageAspectRatio'].value = '16/9' file_description['StoredWidth'].value = 1920 file_description['StoredHeight'].value = 1080 file_description['FrameLayout'].value = 'FullFrame' file_description['VideoLineMap'].value = [42, 0] file_description['SampleRate'].value = video_rate file_description['Length'].value = 10 file_mob.descriptor = file_description clip = tape_mob.create_source_clip(slot_id=1, length=length) slot = file_mob.create_picture_slot(video_rate) slot.segment.components.append(clip) f.content.mobs.append(file_mob) mob_count += 1 # Make the Master MOB master_mob = f.create.MasterMob() master_mob.name = "Master Mob %i" % i master_mob.comments['Test'] = 'Value' master_mob.comments.append(f.create.TaggedValue("Test2", 42)) assert master_mob.comments['Test'] == "Value" assert master_mob.comments['Test2'] == 42 clip = file_mob.create_source_clip(slot_id=1) assert clip.length == length slot = master_mob.create_picture_slot(video_rate) slot.segment.components.append(clip) f.content.mobs.append(master_mob) mob_count += 1 # Create a SourceClip clip = master_mob.create_source_clip(slot_id=1) assert clip.length == length sequence.components.append(clip) components += 1 # Create a filler comp_fill = f.create.Filler("picture", filler_len) sequence.components.append(comp_fill) components += 1 with aaf2.open(result_file, "r") as f: assert len(f.content.mobs) == mob_count comp = next(f.content.compositionmobs()) slot = comp.slot_at(1) assert len(slot.segment.components) == components
def test_video_transition(self): result_file = common.get_test_file('video_transition.aaf') with aaf2.open(result_file, 'w') as f: register_definitions(f) comp = f.create.CompositionMob("Transition Timeline") comp.usage = 'Usage_TopLevel' f.content.mobs.append(comp) slot = comp.create_picture_slot() seq = f.create.Sequence() slot.segment = seq filler = f.create.Filler() filler.length = 50 seq.components.append(filler) transition = create_video_transition(f) seq.components.append(transition) clip = create_video_clip_import(f) clip.mob.name = "clip1" clip.length = 50 seq.components.append(clip) transition = create_video_transition(f) seq.components.append(transition) clip = create_video_clip_offline(f) clip.length = 50 clip.mob.name = "clip2" seq.components.append(clip) transition = create_video_transition(f) seq.components.append(transition) filler = f.create.Filler() filler.length = 50 seq.components.append(filler) with aaf2.open(result_file, 'r') as f: comp = next(f.content.toplevel()) slot = comp.slots[0] transitions = [] for item in slot.segment.components: if isinstance(item, aaf2.components.Transition): transitions.append(item) assert len(transitions) == 3 for t in transitions: op_group = t['OperationGroup'].value opacity_u = None for p in op_group.parameters: if p.name == 'AFX_FG_KEY_OPACITY_U': opacity_u = p break for point in opacity_u['PointList'].value: assert isinstance(point['Value'].value, aaf2.rational.AAFRational) seq = slot.segment clip = seq.component_at_time(0) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(29) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(30) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(39) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(40) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(49) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(50) assert isinstance(clip, aaf2.components.SourceClip) assert clip.mob.name == 'clip1' clip = seq.component_at_time(59) assert isinstance(clip, aaf2.components.SourceClip) assert clip.mob.name == 'clip1' clip = seq.component_at_time(60) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(69) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(70) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(79) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(80) assert isinstance(clip, aaf2.components.SourceClip) assert clip.mob.name == 'clip2' clip = seq.component_at_time(89) assert isinstance(clip, aaf2.components.SourceClip) assert clip.mob.name == 'clip2' clip = seq.component_at_time(90) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(99) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(109) assert isinstance(clip, aaf2.components.Transition) clip = seq.component_at_time(110) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(139) assert isinstance(clip, aaf2.components.Filler) clip = seq.component_at_time(150) assert isinstance(clip, aaf2.components.Filler)