diff --git a/libs/aaf/AAFClass.c b/libs/aaf/AAFClass.c index 351627051b..211ab5431c 100644 --- a/libs/aaf/AAFClass.c +++ b/libs/aaf/AAFClass.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -38,31 +38,31 @@ #include "aaf/AAFDefs/AAFPropertyIDs.h" #include "aaf/AAFDefs/AAFTypeDefUIDs.h" -#include "aaf/debug.h" +#include "aaf/log.h" #include "aaf/AAFClass.h" #define debug(...) \ - _dbg (aafd->dbg, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (aafd->dbg, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (aafd->dbg, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_ERROR, __VA_ARGS__) + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_ERROR, __VA_ARGS__) -#define attachNewProperty(aafd, Class, Prop, Pid, IsReq) \ - Prop = calloc (sizeof (aafPropertyDef), sizeof (unsigned char)); \ - if (Prop == NULL) { \ - error ("%s.", strerror (errno)); \ - return -1; \ - } \ - Prop->pid = Pid; \ - Prop->name = NULL; \ - Prop->isReq = IsReq; \ - Prop->meta = 0; \ - Prop->next = Class->Properties; \ - memset (&Prop->type, 0x00, sizeof (aafUID_t)); \ +#define attachNewProperty(aafd, Class, Prop, Pid, IsReq) \ + Prop = calloc (1, sizeof (aafPropertyDef)); \ + if (!Prop) { \ + error ("Out of memory"); \ + return -1; \ + } \ + Prop->pid = Pid; \ + Prop->name = NULL; \ + Prop->isReq = IsReq; \ + Prop->meta = 0; \ + Prop->next = Class->Properties; \ + memset (&Prop->type, 0x00, sizeof (aafUID_t)); \ Class->Properties = Prop; int @@ -72,7 +72,7 @@ aafclass_classExists (AAF_Data* aafd, aafUID_t* ClassID) foreachClass (Class, aafd->Classes) if (aafUIDCmp (Class->ID, ClassID)) break; - if (Class == NULL) + if (!Class) return 0; return 1; @@ -95,8 +95,8 @@ aafclass_defineNewClass (AAF_Data* aafd, const aafUID_t* id, uint8_t isConcrete, { aafClass* Class = malloc (sizeof (aafClass)); - if (Class == NULL) { - error ("%s.", strerror (errno)); + if (!Class) { + error ("Out of memory"); return NULL; } diff --git a/libs/aaf/AAFCore.c b/libs/aaf/AAFCore.c index f4947fabb8..e8532bb9db 100644 --- a/libs/aaf/AAFCore.c +++ b/libs/aaf/AAFCore.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -33,38 +33,19 @@ #include "aaf/AAFDefs/AAFPropertyIDs.h" #include "aaf/AAFDefs/AAFTypeDefUIDs.h" -#include "aaf/debug.h" +#include "aaf/log.h" #include "aaf/AAFClass.h" #include "aaf/utils.h" #define debug(...) \ - _dbg (aafd->dbg, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (aafd->dbg, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (aafd->dbg, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_ERROR, __VA_ARGS__) - -/** - * Loops through each aafPropertyIndexEntry_t of a "properties" node stream. - * - * @param Header Pointer to the stream's aafPropertyIndexHeader_t struct. - * @param Entry Pointer that will receive each aafPropertyIndexEntry_t struct. - * @param Value Pointer to each property's data value, of aafPropertyIndexEntry_t._length - * bytes length. - * @param i uint32_t iterator. - */ - -#define foreachPropertyEntry(propStream, Header, Entry, Value, valueOffset, i) \ - for (valueOffset = sizeof (aafPropertyIndexHeader_t) + (Header._entryCount * sizeof (aafPropertyIndexEntry_t)), \ - i = 0; \ - i < Header._entryCount && \ - memcpy (&Entry, (propStream + ((sizeof (aafPropertyIndexHeader_t)) + (sizeof (aafPropertyIndexEntry_t) * i))), sizeof (aafPropertyIndexEntry_t)) && \ - (Value = propStream + valueOffset); \ - valueOffset += Entry._length, \ - i++) + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_ERROR, __VA_ARGS__) /** * Loops through each aafStrongRefSetEntry_t of a StrongRefSet Index node stream. @@ -93,17 +74,17 @@ memcpy (&Entry, (vectorStream + (sizeof (aafStrongRefVectorHeader_t) + (sizeof (aafStrongRefVectorEntry_t) * i))), sizeof (aafStrongRefVectorEntry_t)); \ i++) -#define attachNewProperty(Class, PDef, Pid, IsReq) \ - PDef = calloc (sizeof (aafPropertyDef), sizeof (unsigned char)); \ - if (PDef == NULL) { \ - error ("%s.", strerror (errno)); \ - return NULL; \ - } \ - PDef->pid = Pid; \ - PDef->isReq = IsReq; \ - PDef->meta = 0; \ - PDef->name = NULL; \ - PDef->next = Class->Properties; \ +#define attachNewProperty(Class, PDef, Pid, IsReq) \ + PDef = calloc (1, sizeof (aafPropertyDef)); \ + if (!PDef) { \ + error ("Out of memory"); \ + return NULL; \ + } \ + PDef->pid = Pid; \ + PDef->isReq = IsReq; \ + PDef->meta = 0; \ + PDef->name = NULL; \ + PDef->next = Class->Properties; \ Class->Properties = PDef; /* @@ -267,7 +248,7 @@ setObjectStrongRefVector (aafObject* Obj, aafStrongRefVectorHeader_t* Header, aa */ static int -retrieveStrongReference (AAF_Data* aafd, aafProperty* Prop, aafObject* parent); +retrieveStrongReference (AAF_Data* aafd, aafProperty* Prop, aafObject* Parent); /** * Retrieves and parses StrongReferenceSet Objects. This function is called by @@ -291,7 +272,7 @@ retrieveStrongReferenceSet (AAF_Data* aafd, aafProperty* Prop, aafObject* parent */ static int -retrieveStrongReferenceVector (AAF_Data* aafd, aafProperty* Prop, aafObject* parent); +retrieveStrongReferenceVector (AAF_Data* aafd, aafProperty* Prop, aafObject* Parent); /** * Adds a new aafProperty to an Object->properties list. If the property Stored Form is @@ -337,7 +318,7 @@ retrieveObjectProperties (AAF_Data* aafd, aafObject* Obj); */ static cfbNode* -getStrongRefIndexNode (AAF_Data* aafd, aafObject* parent, const wchar_t* refName); +getStrongRefIndexNode (AAF_Data* aafd, aafObject* Parent, const char* refName); /** * Retrieves a StrongRef Set or Vector Entry Node in the Compound File Tree. This @@ -353,7 +334,7 @@ getStrongRefIndexNode (AAF_Data* aafd, aafObject* parent, const wchar_t* refName */ static cfbNode* -getStrongRefEntryNode (AAF_Data* aafd, aafObject* parent, const wchar_t* baseName, uint16_t index); +getStrongRefEntryNode (AAF_Data* aafd, aafObject* Parent, const char* refName, uint32_t index); /** * Retrieves and returns a list of aafPropertyIndexHeader_t. @@ -385,7 +366,7 @@ getNodeProperties (AAF_Data* aafd, cfbNode* node); */ static aafStrongRefSetHeader_t* -getStrongRefSetList (AAF_Data* aafd, cfbNode* node, aafObject* parent); +getStrongRefSetList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent); /** * Retrieves and returns a list of StrongReferenceVectors. @@ -402,18 +383,18 @@ getStrongRefSetList (AAF_Data* aafd, cfbNode* node, aafObject* parent); */ static aafByte_t* -getStrongRefVectorList (AAF_Data* aafd, cfbNode* node, aafObject* parent); +getStrongRefVectorList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent); AAF_Data* -aaf_alloc (struct dbg* dbg) +aaf_alloc (struct aafLog* log) { - AAF_Data* aafd = calloc (sizeof (AAF_Data), sizeof (unsigned char)); + AAF_Data* aafd = calloc (1, sizeof (AAF_Data)); - if (aafd == NULL) - error ("%s.", strerror (errno)); + if (!aafd) { + goto err; + } aafd->cfbd = NULL; - // aafd->verb = VERB_QUIET; aafd->Identification.CompanyName = NULL; aafd->Identification.ProductName = NULL; @@ -422,24 +403,32 @@ aaf_alloc (struct dbg* dbg) aafd->Classes = NULL; aafd->Objects = NULL; - // aafd->debug_callback = &laaf_debug_callback; - aafd->dbg = dbg; + aafd->log = log; - aafd->cfbd = cfb_alloc (dbg); + aafd->cfbd = cfb_alloc (log); - if (aafd->cfbd == NULL) { - return NULL; + if (!aafd->cfbd) { + goto err; } - // aafd->cfbd->verb = aafd->verb; - return aafd; + +err: + + if (aafd) { + if (aafd->cfbd) { + cfb_release (&aafd->cfbd); + } + free (aafd); + } + + return NULL; } int aaf_load_file (AAF_Data* aafd, const char* file) { - if (file == NULL) + if (!aafd || !file) return 1; aafd->Objects = NULL; @@ -481,7 +470,7 @@ aaf_load_file (AAF_Data* aafd, const char* file) void aaf_release (AAF_Data** aafd) { - if (aafd == NULL || *aafd == NULL) + if (!aafd || !(*aafd)) return; if ((*aafd)->cfbd != NULL) @@ -496,18 +485,12 @@ aaf_release (AAF_Data** aafd) aafPropertyDef* PDef = NULL; aafPropertyDef* tmpPDef = NULL; - if (Class->name != NULL) { - free (Class->name); - } + free (Class->name); for (PDef = Class->Properties; PDef != NULL; PDef = tmpPDef) { tmpPDef = PDef->next; - // if ( PDef->meta ) { - if (PDef->name != NULL) - free (PDef->name); - // } - + free (PDef->name); free (PDef); } @@ -520,11 +503,9 @@ aaf_release (AAF_Data** aafd) for (Object = (*aafd)->Objects; Object != NULL; Object = tmpObject) { tmpObject = Object->nextObj; - if (Object->Header != NULL) - free (Object->Header); - - if (Object->Entry != NULL) - free (Object->Entry); + free (Object->Header); + free (Object->Entry); + free (Object->Name); aafProperty* Prop = NULL; aafProperty* tmpProp = NULL; @@ -548,42 +529,26 @@ aaf_release (AAF_Data** aafd) free (Object); } - if ((*aafd)->Identification.CompanyName != NULL) { - free ((*aafd)->Identification.CompanyName); - } - - if ((*aafd)->Identification.ProductName != NULL) { - free ((*aafd)->Identification.ProductName); - } - - if ((*aafd)->Identification.ProductVersionString != NULL) { - free ((*aafd)->Identification.ProductVersionString); - } - - if ((*aafd)->Identification.Platform != NULL) { - free ((*aafd)->Identification.Platform); - } - - /* free once in AAFIface */ - // if ( (*aafd)->dbg ) { - // laaf_free_debug( (*aafd)->dbg ); - // } + free ((*aafd)->Identification.CompanyName); + free ((*aafd)->Identification.ProductName); + free ((*aafd)->Identification.ProductVersionString); + free ((*aafd)->Identification.Platform); free (*aafd); *aafd = NULL; } -wchar_t* +char* aaf_get_ObjectPath (aafObject* Obj) { - static wchar_t path[CFB_PATH_NAME_SZ]; + static char path[CFB_PATH_NAME_SZ]; uint32_t offset = CFB_PATH_NAME_SZ; - path[--offset] = 0x0000; // NULL terminating byte + path[--offset] = '\0'; while (Obj != NULL) { - for (int i = wcslen (Obj->Name) - 1; i >= 0 && offset > 0; i--) { + for (int i = (int)strlen (Obj->Name) - 1; i >= 0 && offset > 0; i--) { path[--offset] = Obj->Name[i]; } @@ -601,7 +566,7 @@ aaf_get_ObjectPath (aafObject* Obj) int _aaf_foreach_ObjectInSet (aafObject** Obj, aafObject* head, const aafUID_t* filter) { - if (*Obj == NULL) + if (!(*Obj)) *Obj = head; else *Obj = (*Obj)->next; @@ -611,15 +576,13 @@ _aaf_foreach_ObjectInSet (aafObject** Obj, aafObject* head, const aafUID_t* filt if (aafUIDCmp ((*Obj)->Class->ID, filter)) break; - return (*Obj == NULL) ? 0 : 1; + return (!(*Obj)) ? 0 : 1; } aafObject* aaf_get_ObjectByWeakRef (aafObject* list, aafWeakRef_t* ref) { - if (ref == NULL || - list == NULL || - list->Entry == NULL) { + if (!ref || !list || !list->Entry) { return NULL; } @@ -655,19 +618,141 @@ aaf_get_ObjectByWeakRef (aafObject* list, aafWeakRef_t* ref) return NULL; } +aafUID_t* +aaf_get_InterpolationIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* InterpolationDefWeakRef) +{ + aafObject* InterpolationDefinition = aaf_get_ObjectByWeakRef (aafd->InterpolationDefinition, InterpolationDefWeakRef); + + if (!InterpolationDefinition) { + error ("Could not find InterpolationDefinition."); + return NULL; + } + + aafUID_t* InterpolationIdentification = aaf_get_propertyValue (InterpolationDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); + + if (!InterpolationIdentification) { + error ("Missing DefinitionObject::Identification."); + return NULL; + } + + return InterpolationIdentification; +} + +aafUID_t* +aaf_get_OperationIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* OperationDefWeakRef) +{ + aafObject* OperationDefinition = aaf_get_ObjectByWeakRef (aafd->OperationDefinition, OperationDefWeakRef); + + if (!OperationDefinition) { + error ("Could not retrieve OperationDefinition from dictionary."); + return NULL; + } + + aafUID_t* OperationIdentification = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); + + if (!OperationIdentification) { + error ("Missing DefinitionObject::Identification."); + return NULL; + } + + return OperationIdentification; +} + +aafUID_t* +aaf_get_ContainerIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* ContainerDefWeakRef) +{ + aafObject* ContainerDefinition = aaf_get_ObjectByWeakRef (aafd->ContainerDefinition, ContainerDefWeakRef); + + if (!ContainerDefinition) { + warning ("Could not retrieve WeakRef from Dictionary::ContainerDefinitions."); + return NULL; + } + + aafUID_t* ContainerIdentification = aaf_get_propertyValue (ContainerDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); + + if (!ContainerIdentification) { + warning ("Missing ContainerDefinition's DefinitionObject::Identification."); + return NULL; + } + + return ContainerIdentification; +} + +aafUID_t* +aaf_get_DataIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* DataDefWeakRef) +{ + aafObject* DataDefinition = aaf_get_ObjectByWeakRef (aafd->DataDefinition, DataDefWeakRef); + + if (!DataDefinition) { + warning ("Could not retrieve WeakRef from Dictionary::DataDefinition."); + return NULL; + } + + aafUID_t* DataIdentification = aaf_get_propertyValue (DataDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); + + if (!DataIdentification) { + warning ("Missing DataDefinition's DefinitionObject::Identification."); + return NULL; + } + + return DataIdentification; +} + +aafObject* +aaf_get_ObjectAncestor (aafObject* Obj, const aafUID_t* ClassID) +{ + /* + * NOTE : AAFClassID_ContentStorage is the container of Mob and EssenceData, + * not of Identification, Dictionary and MetaDictionary. If needed, the func + * should work for them too thanks to Obj != NULL. + */ + + while (Obj != NULL && !aafUIDCmp (Obj->Class->ID, &AAFClassID_ContentStorage)) { + if (aafUIDCmp (ClassID, Obj->Class->ID)) { + return Obj; + } + + if (aaf_ObjectInheritsClass (Obj, ClassID)) { + return Obj; + } + + Obj = Obj->Parent; + } + + return NULL; +} + +int +aaf_ObjectInheritsClass (aafObject* Obj, const aafUID_t* classID) +{ + // AAF_Data *aafd = Obj->aafd; + + aafClass* classObj = NULL; + foreachClassInheritance (classObj, Obj->Class) + { + if (aafUIDCmp (classObj->ID, classID)) { + // debug( "%s is a parent of class %s", + // aaft_ClassIDToText( aafd, classObj->ID ), + // aaft_ClassIDToText( aafd, Obj->Class->ID ) ); + return 1; + } + } + return 0; +} + aafObject* aaf_get_MobByID (aafObject* Mobs, aafMobID_t* MobID) { aafObject* Mob = NULL; - if (MobID == NULL) + if (!MobID) return NULL; - aaf_foreach_ObjectInSet (&Mob, Mobs, NULL) + AAF_foreach_ObjectInSet (&Mob, Mobs, NULL) { aafMobID_t* Current = aaf_get_propertyValue (Mob, PID_Mob_MobID, &AAFTypeID_MobIDType); - if (Current == NULL || aafMobIDCmp (Current, MobID)) + if (!Current || aafMobIDCmp (Current, MobID)) break; } @@ -679,23 +764,124 @@ aaf_get_MobSlotBySlotID (aafObject* MobSlots, aafSlotID_t SlotID) { aafObject* MobSlot = NULL; - aaf_foreach_ObjectInSet (&MobSlot, MobSlots, NULL) + AAF_foreach_ObjectInSet (&MobSlot, MobSlots, NULL) { aafSlotID_t* CurrentSlotID = aaf_get_propertyValue (MobSlot, PID_MobSlot_SlotID, &AAFTypeID_UInt32); - if (CurrentSlotID == NULL || *CurrentSlotID == SlotID) + if (!CurrentSlotID || *CurrentSlotID == SlotID) break; } return MobSlot; } +aafObject* +aaf_get_EssenceDataByMobID (AAF_Data* aafd, aafMobID_t* MobID) +{ + aafMobID_t* DataMobID = NULL; + aafObject* EssenceData = NULL; + + for (EssenceData = aafd->EssenceData; EssenceData != NULL; EssenceData = EssenceData->next) { + DataMobID = aaf_get_propertyValue (EssenceData, PID_EssenceData_MobID, &AAFTypeID_MobIDType); + + if (aafMobIDCmp (DataMobID, MobID)) + break; + } + + return EssenceData; +} + +aafUID_t* +aaf_get_ParamDefIDByName (AAF_Data* aafd, const char* name) +{ + aafUID_t* ParamDefIdent = NULL; + aafObject* ParameterDefinitions = aaf_get_propertyValue (aafd->Dictionary, PID_Dictionary_ParameterDefinitions, &AAFTypeID_ParameterDefinitionStrongReferenceSet); + aafObject* ParameterDefinition = NULL; + + AAF_foreach_ObjectInSet (&ParameterDefinition, ParameterDefinitions, NULL) + { + char* paramName = aaf_get_propertyValue (ParameterDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); + + if (!paramName) { + continue; + } + + if (strcmp (paramName, name) == 0) { + ParamDefIdent = aaf_get_propertyValue (ParameterDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); + free (paramName); + break; + } + + free (paramName); + } + + return ParamDefIdent; +} + +void* +aaf_get_TaggedValueByName (AAF_Data* aafd, aafObject* TaggedValueVector, const char* name, const aafUID_t* type) +{ + struct aafLog* log = aafd->log; + + aafObject* TaggedValue = NULL; + + AAF_foreach_ObjectInSet (&TaggedValue, TaggedValueVector, NULL) + { + if (!aafUIDCmp (TaggedValue->Class->ID, &AAFClassID_TaggedValue)) { + LOG_BUFFER_WRITE (log, " %sObject > %s\n", + ANSI_COLOR_RESET (log), + aaft_ClassIDToText (aafd, TaggedValue->Class->ID)); + continue; + } + + char* taggedName = aaf_get_propertyValue (TaggedValue, PID_TaggedValue_Name, &AAFTypeID_String); + aafIndirect_t* taggedIndirect = aaf_get_propertyValue (TaggedValue, PID_TaggedValue_Value, &AAFTypeID_Indirect); + + if (strcmp (taggedName, name) == 0) { + if (aafUIDCmp (&taggedIndirect->TypeDef, type)) { + debug ("Found TaggedValue \"%s\" of type %s", + taggedName, + aaft_TypeIDToText (&taggedIndirect->TypeDef)); + + free (taggedName); + + void* value = aaf_get_indirectValue (aafd, taggedIndirect, type); + + return value; + } + + debug ("Got TaggedValue \"%s\" but of type %s instead of %s", + taggedName, + aaft_TypeIDToText (&taggedIndirect->TypeDef), + aaft_TypeIDToText (type)); + } + // LOG_BUFFER_WRITE( log, " %sTagged > Name: %s%s%s%*s Value: %s(%s)%s %s%s%s", + // ANSI_COLOR_RESET(log), + // ANSI_COLOR_DARKGREY(log), + // (name) ? name : "", + // ANSI_COLOR_RESET(log), + // (name) ? (size_t)(24-(int)strlen(name)) : (size_t)(24-strlen("")), " ", + // ANSI_COLOR_DARKGREY(log), + // aaft_TypeIDToText( &taggedIndirect->TypeDef ), + // ANSI_COLOR_RESET(log), + // ANSI_COLOR_DARKGREY(log), + // aaft_IndirectValueToText( aafd, taggedIndirect ), + // ANSI_COLOR_RESET(log) ); + + free (taggedName); + } + + debug ("TaggedValue not found \"%s\"", name); + + return NULL; +} + /* * TODO Works when the property was retrieved from MetaDictionary. What if the property is standard ? */ aafPID_t -aaf_get_PropertyIDByName (AAF_Data* aafd, const wchar_t* name) +aaf_get_PropertyIDByName (AAF_Data* aafd, const char* name) { aafClass* Class = NULL; @@ -705,7 +891,7 @@ aaf_get_PropertyIDByName (AAF_Data* aafd, const wchar_t* name) foreachPropertyDefinition (PDef, Class->Properties) { - if (PDef->name != NULL && wcscmp (PDef->name, name) == 0) { + if (PDef->name != NULL && strcmp (PDef->name, name) == 0) { return PDef->pid; } } @@ -714,10 +900,32 @@ aaf_get_PropertyIDByName (AAF_Data* aafd, const wchar_t* name) return 0; } +aafUID_t* +aaf_get_OperationDefIDByName (AAF_Data* aafd, const char* OpDefName) +{ + aafObject* OperationDefinitions = aaf_get_propertyValue (aafd->Dictionary, PID_Dictionary_OperationDefinitions, &AAFTypeID_OperationDefinitionStrongReferenceSet); + aafObject* OperationDefinition = NULL; + + while (_aaf_foreach_ObjectInSet (&OperationDefinition, OperationDefinitions, NULL)) { + aafUID_t* OpDefIdent = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); + + char* name = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); + + if (strcmp (name, OpDefName) == 0) { + free (name); + return OpDefIdent; + } + + free (name); + } + + return NULL; +} + aafProperty* aaf_get_property (aafObject* Obj, aafPID_t pid) { - if (Obj == NULL) + if (!Obj) return NULL; AAF_Data* aafd = Obj->aafd; @@ -728,18 +936,27 @@ aaf_get_property (aafObject* Obj, aafPID_t pid) if (Prop->pid == pid) break; - if (Prop == NULL) { + if (!Prop) { aafPropertyDef* PDef = aafclass_getPropertyDefinitionByID (Obj->Class, pid); - if (PDef == NULL) { - warning ("Unknown property 0x%04x (%ls) of Class %ls", pid, aaft_PIDToText (aafd, pid), aaft_ClassIDToText (aafd, Obj->Class->ID)); + if (!PDef) { + warning ("Could not retrieve 0x%04x (%s) of Class %s", + pid, + aaft_PIDToText (aafd, pid), + aaft_ClassIDToText (aafd, Obj->Class->ID)); return NULL; } if (PDef->isReq) { - error ("Could not retrieve %ls required property 0x%04x (%ls)", aaft_ClassIDToText (aafd, Obj->Class->ID), pid, aaft_PIDToText (aafd, pid)); + error ("Could not retrieve %s required property 0x%04x (%s)", + aaft_ClassIDToText (aafd, Obj->Class->ID), + pid, + aaft_PIDToText (aafd, pid)); } else { - debug ("Could not retrieve %ls optional property 0x%04x (%ls)", aaft_ClassIDToText (aafd, Obj->Class->ID), pid, aaft_PIDToText (aafd, pid)); + debug ("Could not retrieve %s optional property 0x%04x (%s)", + aaft_ClassIDToText (aafd, Obj->Class->ID), + pid, + aaft_PIDToText (aafd, pid)); } } @@ -749,14 +966,14 @@ aaf_get_property (aafObject* Obj, aafPID_t pid) void* aaf_get_propertyValue (aafObject* Obj, aafPID_t pid, const aafUID_t* typeID) { - if (Obj == NULL) { + if (!Obj) { return NULL; } AAF_Data* aafd = Obj->aafd; aafProperty* Prop = aaf_get_property (Obj, pid); - if (Prop == NULL) { + if (!Prop) { return NULL; } @@ -774,11 +991,14 @@ aaf_get_propertyValue (aafObject* Obj, aafPID_t pid, const aafUID_t* typeID) if (aafUIDCmp (typeID, &AAFTypeID_String)) { if (((uint16_t*)value)[(len / 2) - 1] != 0x0000) { - error ("Object %ls string property 0x%04x (%ls) does not end with NULL", aaft_ClassIDToText (aafd, Obj->Class->ID), pid, aaft_PIDToText (aafd, pid)); + error ("Object %s string property 0x%04x (%s) does not end with NULL", + aaft_ClassIDToText (aafd, Obj->Class->ID), + pid, + aaft_PIDToText (aafd, pid)); return NULL; } - return cfb_w16towchar (NULL, value, len); + return cfb_w16toUTF8 (value, len); } if (aafUIDCmp (typeID, &AAFTypeID_Indirect)) { @@ -791,7 +1011,10 @@ aaf_get_propertyValue (aafObject* Obj, aafPID_t pid, const aafUID_t* typeID) aafIndirect_t* Indirect = value; if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_String) && ((uint16_t*)value)[(len / 2) - 1] != 0x0000) { - error ("Object %ls Indirect::string property 0x%04x (%ls) does not end with NULL", aaft_ClassIDToText (aafd, Obj->Class->ID), pid, aaft_PIDToText (aafd, pid)); + error ("Object %s Indirect::string property 0x%04x (%s) does not end with NULL", + aaft_ClassIDToText (aafd, Obj->Class->ID), + pid, + aaft_PIDToText (aafd, pid)); return NULL; } } @@ -814,7 +1037,12 @@ aaf_get_propertyValue (aafObject* Obj, aafPID_t pid, const aafUID_t* typeID) (aafUIDCmp (typeID, &AAFTypeID_UsageType) && len != sizeof (aafUID_t)) || (aafUIDCmp (typeID, &AAFTypeID_AUID) && len != sizeof (aafUID_t)) || (aafUIDCmp (typeID, &AAFTypeID_MobIDType) && len != sizeof (aafMobID_t))) { - error ("Object %ls property 0x%04x (%ls) size (%u) does not match type %ls", aaft_ClassIDToText (aafd, Obj->Class->ID), pid, aaft_PIDToText (aafd, pid), len, aaft_TypeIDToText (typeID)); + error ("Object %s property 0x%04x (%s) size (%u) does not match type %s", + aaft_ClassIDToText (aafd, Obj->Class->ID), + pid, + aaft_PIDToText (aafd, pid), + len, + aaft_TypeIDToText (typeID)); return NULL; } @@ -824,13 +1052,15 @@ aaf_get_propertyValue (aafObject* Obj, aafPID_t pid, const aafUID_t* typeID) void* aaf_get_indirectValue (AAF_Data* aafd, aafIndirect_t* Indirect, const aafUID_t* typeDef) { - if (Indirect == NULL) { + if (!Indirect) { error ("Indirect is NULL"); return NULL; } if (typeDef && aafUIDCmp (&Indirect->TypeDef, typeDef) == 0) { - error ("Requested Indirect value of type %ls but has type %ls", aaft_TypeIDToText (typeDef), aaft_TypeIDToText (&Indirect->TypeDef)); + error ("Requested Indirect value of type %s but has type %s", + aaft_TypeIDToText (typeDef), + aaft_TypeIDToText (&Indirect->TypeDef)); return NULL; } @@ -849,14 +1079,14 @@ aaf_get_indirectValue (AAF_Data* aafd, aafIndirect_t* Indirect, const aafUID_t* uint16_t* w16 = malloc (indirectValueSize); - if (w16 == NULL) { - error ("%s.", strerror (errno)); + if (!w16) { + error ("Out of memory"); return NULL; } memcpy (w16, Indirect->Value, indirectValueSize); - wchar_t* str = cfb_w16towchar (NULL, w16, indirectValueSize); + char* str = cfb_w16toUTF8 (w16, indirectValueSize); free (w16); @@ -871,14 +1101,14 @@ parse_Header (AAF_Data* aafd) { aafObject* Header = aafd->Header.obj; - if (Header == NULL) { + if (!Header) { error ("Missing Header Object."); return -1; } int16_t* ByteOrder = aaf_get_propertyValue (Header, PID_Header_ByteOrder, &AAFTypeID_Int16); - if (ByteOrder == NULL) { + if (!ByteOrder) { warning ("Missing Header::ByteOrder."); } else { aafd->Header.ByteOrder = *ByteOrder; @@ -886,7 +1116,7 @@ parse_Header (AAF_Data* aafd) aafTimeStamp_t* LastModified = aaf_get_propertyValue (Header, PID_Header_LastModified, &AAFTypeID_TimeStamp); - if (LastModified == NULL) { + if (!LastModified) { warning ("Missing Header::LastModified."); } else { aafd->Header.LastModified = LastModified; @@ -894,7 +1124,7 @@ parse_Header (AAF_Data* aafd) aafVersionType_t* Version = aaf_get_propertyValue (Header, PID_Header_Version, &AAFTypeID_VersionType); - if (Version == NULL) { + if (!Version) { warning ("Missing Header::Version."); } else { aafd->Header.Version = Version; @@ -902,7 +1132,7 @@ parse_Header (AAF_Data* aafd) uint32_t* ObjectModelVersion = aaf_get_propertyValue (Header, PID_Header_ObjectModelVersion, &AAFTypeID_UInt32); - if (ObjectModelVersion == NULL) { + if (!ObjectModelVersion) { warning ("Missing Header::ObjectModelVersion."); } else { aafd->Header.ObjectModelVersion = *ObjectModelVersion; @@ -910,7 +1140,7 @@ parse_Header (AAF_Data* aafd) const aafUID_t* OperationalPattern = aaf_get_propertyValue (Header, PID_Header_OperationalPattern, &AAFTypeID_AUID); - if (OperationalPattern == NULL) { + if (!OperationalPattern) { warning ("Missing Header::OperationalPattern."); aafd->Header.OperationalPattern = (const aafUID_t*)&AUID_NULL; } else { @@ -925,22 +1155,22 @@ parse_Identification (AAF_Data* aafd) { aafObject* Identif = aafd->Identification.obj; - if (Identif == NULL) { + if (!Identif) { error ("Missing Identification Object."); return -1; } - wchar_t* Company = aaf_get_propertyValue (Identif, PID_Identification_CompanyName, &AAFTypeID_String); + char* Company = aaf_get_propertyValue (Identif, PID_Identification_CompanyName, &AAFTypeID_String); - if (Company == NULL) { + if (!Company) { warning ("Missing Identification::CompanyName."); } else { aafd->Identification.CompanyName = Company; } - wchar_t* ProductName = aaf_get_propertyValue (Identif, PID_Identification_ProductName, &AAFTypeID_String); + char* ProductName = aaf_get_propertyValue (Identif, PID_Identification_ProductName, &AAFTypeID_String); - if (ProductName == NULL) { + if (!ProductName) { warning ("Missing Identification::ProductName."); } else { aafd->Identification.ProductName = ProductName; @@ -948,15 +1178,15 @@ parse_Identification (AAF_Data* aafd) aafProductVersion_t* ProductVersion = aaf_get_propertyValue (Identif, PID_Identification_ProductVersion, &AAFTypeID_ProductVersion); - if (ProductVersion == NULL) { + if (!ProductVersion) { warning ("Missing Identification::ProductVersion."); } else { aafd->Identification.ProductVersion = ProductVersion; } - wchar_t* ProductVersionString = aaf_get_propertyValue (Identif, PID_Identification_ProductVersionString, &AAFTypeID_String); + char* ProductVersionString = aaf_get_propertyValue (Identif, PID_Identification_ProductVersionString, &AAFTypeID_String); - if (ProductVersionString == NULL) { + if (!ProductVersionString) { warning ("Missing Identification::ProductVersionString."); } else { aafd->Identification.ProductVersionString = ProductVersionString; @@ -964,7 +1194,7 @@ parse_Identification (AAF_Data* aafd) aafUID_t* ProductID = aaf_get_propertyValue (Identif, PID_Identification_ProductID, &AAFTypeID_AUID); - if (ProductID == NULL) { + if (!ProductID) { warning ("Missing Identification::ProductID."); } else { aafd->Identification.ProductID = ProductID; @@ -972,7 +1202,7 @@ parse_Identification (AAF_Data* aafd) aafTimeStamp_t* Date = aaf_get_propertyValue (Identif, PID_Identification_Date, &AAFTypeID_TimeStamp); - if (Date == NULL) { + if (!Date) { warning ("Missing Identification::Date."); } else { aafd->Identification.Date = Date; @@ -980,15 +1210,15 @@ parse_Identification (AAF_Data* aafd) aafProductVersion_t* ToolkitVersion = aaf_get_propertyValue (Identif, PID_Identification_ToolkitVersion, &AAFTypeID_ProductVersion); - if (ToolkitVersion == NULL) { + if (!ToolkitVersion) { warning ("Missing Identification::ToolkitVersion."); } else { aafd->Identification.ToolkitVersion = ToolkitVersion; } - wchar_t* Platform = aaf_get_propertyValue (Identif, PID_Identification_Platform, &AAFTypeID_String); + char* Platform = aaf_get_propertyValue (Identif, PID_Identification_Platform, &AAFTypeID_String); - if (Platform == NULL) { + if (!Platform) { warning ("Missing Identification::Platform."); } else { aafd->Identification.Platform = Platform; @@ -996,7 +1226,7 @@ parse_Identification (AAF_Data* aafd) aafUID_t* GenerationAUID = aaf_get_propertyValue (Identif, PID_Identification_GenerationAUID, &AAFTypeID_AUID); - if (GenerationAUID == NULL) { + if (!GenerationAUID) { warning ("Missing Identification::GenerationAUID."); } else { aafd->Identification.GenerationAUID = GenerationAUID; @@ -1013,7 +1243,7 @@ parse_Identification (AAF_Data* aafd) // aafUIDCmp( hdrClsID, &AAFFileKind_Aaf4KBinary ) ) // return 1; // -// // warning( "Unsuported AAF encoding (%ls).", aaft_FileKindToText( hdrClsID ) ); +// // warning( "Unsuported AAF encoding (%s).", aaft_FileKindToText( hdrClsID ) ); // // return 0; // } @@ -1057,23 +1287,21 @@ retrieveObjectTree (AAF_Data* aafd) aafClass* Class = aafclass_getClassByID (aafd, (aafUID_t*)&Node->_clsId); - if (Class == NULL && aafUIDCmp (Class->ID, (aafUID_t*)&Node->_clsId) != 0) { - error ("Looks like the fist Object is not the Root Class : %ls.", aaft_ClassIDToText (aafd, Class->ID)); + if (!Class) { + error ("Could not retrieve class by id"); goto err; } aafd->Root = newObject (aafd, Node, Class, NULL); - if (aafd->Root == NULL) { + if (!aafd->Root) { goto err; } - /* retrieveObjectProperties() */ - propStream = getNodeProperties (aafd, aafd->Root->Node); - if (propStream == NULL) { - error ("Could not retrieve properties for %ls.", aaf_get_ObjectPath (aafd->Root)); + if (!propStream) { + error ("Could not retrieve properties for %s.", aaf_get_ObjectPath (aafd->Root)); goto err; } @@ -1093,7 +1321,7 @@ retrieveObjectTree (AAF_Data* aafd) aafPropertyDef* PDef = NULL; uint32_t i = 0; - int valueOffset = 0; + size_t valueOffset = 0; foreachPropertyEntry (propStream, Header, Prop, value, valueOffset, i) { @@ -1115,7 +1343,7 @@ retrieveObjectTree (AAF_Data* aafd) rc = retrieveProperty (aafd, aafd->Root, PDef, &AAFMetaDcProp, AAFMetaDcVal, Header._byteOrder); if (rc < 0) { - error ("Could not retrieve property %ls.", aaft_PIDToText (aafd, PDef->pid)); + error ("Could not retrieve property %s.", aaft_PIDToText (aafd, PDef->pid)); goto err; } @@ -1125,21 +1353,21 @@ retrieveObjectTree (AAF_Data* aafd) aafObject* MetaDic = aaf_get_propertyValue (aafd->Root, PID_Root_MetaDictionary, &AAFUID_NULL); - if (MetaDic == NULL) { + if (!MetaDic) { error ("Missing PID_Root_MetaDictionary."); goto err; } aafObject* ClassDefs = aaf_get_propertyValue (MetaDic, PID_MetaDictionary_ClassDefinitions, &AAFTypeID_ClassDefinitionStrongReferenceSet); - if (ClassDefs == NULL) { + if (!ClassDefs) { error ("Missing PID_MetaDictionary_ClassDefinitions."); goto err; } aafObject* ClassDef = NULL; - aaf_foreach_ObjectInSet (&ClassDef, ClassDefs, NULL) + AAF_foreach_ObjectInSet (&ClassDef, ClassDefs, NULL) { retrieveMetaDictionaryClass (aafd, ClassDef); } @@ -1151,7 +1379,7 @@ retrieveObjectTree (AAF_Data* aafd) rc = retrieveProperty (aafd, aafd->Root, PDef, &AAFHeaderProp, AAFHeaderVal, Header._byteOrder); if (rc < 0) { - error ("Could not retrieve property %ls.", aaft_PIDToText (aafd, PDef->pid)); + error ("Could not retrieve property %s.", aaft_PIDToText (aafd, PDef->pid)); goto err; } @@ -1165,8 +1393,7 @@ err: end: - if (propStream) - free (propStream); + free (propStream); return rc; } @@ -1176,29 +1403,50 @@ retrieveMetaDictionaryClass (AAF_Data* aafd, aafObject* TargetClassDef) { aafObject* MetaDic = aaf_get_propertyValue (aafd->Root, PID_Root_MetaDictionary, &AAFUID_NULL); - aafObject* ClassDefs = aaf_get_propertyValue (MetaDic, PID_MetaDictionary_ClassDefinitions, &AAFTypeID_ClassDefinitionStrongReferenceSet); - aafObject* ClassDef = NULL; - - if (ClassDefs == NULL) { - error ("Could not retrieve PID_MetaDictionary_ClassDefinitions property from MetaDic."); + if (!MetaDic) { /* req */ + debug ("Could not retrieve PID_Root_MetaDictionary property from Root."); return NULL; } - aaf_foreach_ObjectInSet (&ClassDef, ClassDefs, NULL) + aafObject* ClassDefs = aaf_get_propertyValue (MetaDic, PID_MetaDictionary_ClassDefinitions, &AAFTypeID_ClassDefinitionStrongReferenceSet); + aafObject* ClassDef = NULL; + + if (!ClassDefs) { /* opt */ + debug ("Could not retrieve PID_MetaDictionary_ClassDefinitions property from MetaDic."); + return NULL; + } + + AAF_foreach_ObjectInSet (&ClassDef, ClassDefs, NULL) { if (ClassDef == TargetClassDef) break; } - if (ClassDef == NULL) { - error ("Could not retrieve ClassDefinition %p.", (void*)TargetClassDef); + if (!ClassDef) { + error ("Could not retrieve ClassDefinition %p", (void*)TargetClassDef); return NULL; } aafUID_t* ClassID = aaf_get_propertyValue (ClassDef, PID_MetaDefinition_Identification, &AAFTypeID_AUID); + if (!ClassID) { /* req */ + error ("Could not retrieve PID_MetaDefinition_Identification property from ClassDef."); + return NULL; + } + aafWeakRef_t* parent = aaf_get_propertyValue (ClassDef, PID_ClassDefinition_ParentClass, &AAFTypeID_ClassDefinitionWeakReference); - aafObject* Parent = aaf_get_ObjectByWeakRef (ClassDefs, parent); + + if (!parent) { + error ("Could not retrieve PID_ClassDefinition_ParentClass property from ClassDef."); + return NULL; + } + + aafObject* Parent = aaf_get_ObjectByWeakRef (ClassDefs, parent); + + if (!Parent) { + error ("Could not retrieve object by weakRef (PID_ClassDefinition_ParentClass)"); + return NULL; + } aafClass* ParentClass = NULL; @@ -1210,45 +1458,64 @@ retrieveMetaDictionaryClass (AAF_Data* aafd, aafObject* TargetClassDef) /* * TODO: what is this ? when does it happen ? */ - error ("Parent's Class equals Child's : %ls.", aaft_ClassIDToText (aafd, ClassID)); + error ("Parent's Class equals Child's : %s.", aaft_ClassIDToText (aafd, ClassID)); return NULL; } aafClass* Class = aafclass_getClassByID (aafd, ClassID); - if (Class == NULL) { + if (!Class) { aafBoolean_t* isCon = aaf_get_propertyValue (ClassDef, PID_ClassDefinition_IsConcrete, &AAFTypeID_Boolean); - if (isCon == NULL) { + if (!isCon) { error ("Missing ClassDefinition::IsConcrete."); return NULL; } Class = aafclass_defineNewClass (aafd, ClassID, *isCon, ParentClass); - Class->name = aaf_get_propertyValue (ClassDef, PID_MetaDefinition_Name, &AAFTypeID_String); + if (!Class) { + error ("Could set new class"); + return NULL; + } + Class->meta = 1; - } else { // if class is standard, we only set its name - if (Class->name == NULL) { + Class->name = aaf_get_propertyValue (ClassDef, PID_MetaDefinition_Name, &AAFTypeID_String); + + if (!Class->name) { + debug ("Could not retrieve PID_MetaDefinition_Name property from ClassDef (%s)", aaft_ClassIDToText (aafd, ClassID)); + } + } else { + /* if class is standard, we only set its name */ + if (!Class->name) { Class->name = aaf_get_propertyValue (ClassDef, PID_MetaDefinition_Name, &AAFTypeID_String); + + if (!Class->name) { + debug ("Could not retrieve PID_MetaDefinition_Name property from ClassDef (%s)", aaft_ClassIDToText (aafd, ClassID)); + } } } aafObject* Props = aaf_get_propertyValue (ClassDef, PID_ClassDefinition_Properties, &AAFTypeID_PropertyDefinitionStrongReferenceSet); - aafObject* Prop = NULL; - aaf_foreach_ObjectInSet (&Prop, Props, NULL) + if (!Props) { /* opt */ + debug ("Could not retrieve PID_ClassDefinition_Properties property from ClassDef (%s)", aaft_ClassIDToText (aafd, ClassID)); + } + + aafObject* Prop = NULL; + + AAF_foreach_ObjectInSet (&Prop, Props, NULL) { aafPID_t* Pid = aaf_get_propertyValue (Prop, PID_PropertyDefinition_LocalIdentification, &AAFTypeID_UInt16); - if (Pid == NULL) { + if (!Pid) { error ("Missing PropertyDefinition::LocalIdentification."); return NULL; } aafBoolean_t* isOpt = aaf_get_propertyValue (Prop, PID_PropertyDefinition_IsOptional, &AAFTypeID_Boolean); - if (isOpt == NULL) { + if (!isOpt) { error ("Missing PropertyDefinition::IsOptional."); return NULL; } @@ -1257,9 +1524,9 @@ retrieveMetaDictionaryClass (AAF_Data* aafd, aafObject* TargetClassDef) * We skip all the properties that were already defined in aafclass_setDefaultClasses(). */ - aafPropertyDef* PDef = NULL; + aafPropertyDef* PDef = propertyIdExistsInClass (Class, *Pid); - if (!(PDef = propertyIdExistsInClass (Class, *Pid))) { + if (!PDef) { attachNewProperty (Class, PDef, *Pid, (*isOpt) ? 0 : 1); PDef->meta = 1; } else { @@ -1269,45 +1536,48 @@ retrieveMetaDictionaryClass (AAF_Data* aafd, aafObject* TargetClassDef) PDef->name = aaf_get_propertyValue (Prop, PID_MetaDefinition_Name, &AAFTypeID_String); + if (!PDef->name) { + warning ("Could not retrieve PID_MetaDefinition_Name property from PropertyDefinition."); + } + aafObject* TypeDefs = aaf_get_propertyValue (MetaDic, PID_MetaDictionary_TypeDefinitions, &AAFTypeID_TypeDefinitionStrongReferenceSet); - if (TypeDefs == NULL) { + if (!TypeDefs) { error ("Missing TypeDefinitions from MetaDictionary"); return NULL; } aafWeakRef_t* WeakRefToType = aaf_get_propertyValue (Prop, PID_PropertyDefinition_Type, &AAFTypeID_PropertyDefinitionWeakReference); - if (WeakRefToType == NULL) { + if (!WeakRefToType) { error ("Missing PID_PropertyDefinition_Type"); return NULL; } aafObject* TypeDef = aaf_get_ObjectByWeakRef (TypeDefs, WeakRefToType); - if (TypeDef == NULL) { + if (!TypeDef) { error ("Could not retrieve TypeDefinition from dictionary."); return NULL; } aafUID_t* typeUID = aaf_get_propertyValue (TypeDef, PID_MetaDefinition_Identification, &AAFTypeID_AUID); - if (typeUID == NULL) { + if (!typeUID) { /* req */ error ("Missing PID_MetaDefinition_Identification"); return NULL; } /* - * Looks like nobody cares about AAF standard TypeDefinition. All observed files + * Looks like nobody cares about AAF standard TypeDefinition. All observed files * had incorrect values for Type Name and Identification, even Avid's files. So... */ memcpy (&PDef->type, typeUID, sizeof (aafUID_t)); - // wchar_t *typeName = aaf_get_propertyValue( TypeDef, PID_MetaDefinition_Name, &AAFTypeID_String ); + // char *typeName = aaf_get_propertyValue( TypeDef, PID_MetaDefinition_Name, &AAFTypeID_String ); // - // debug( "TypeName : %ls (%ls) | name : %ls.", - // // AUIDToText(typeUID), + // debug( "TypeName : %s (%s) | name : %s.", // typeName, // aaft_TypeIDToText( typeUID ), // PDef->name ); @@ -1321,15 +1591,14 @@ retrieveMetaDictionaryClass (AAF_Data* aafd, aafObject* TargetClassDef) static aafObject* newObject (AAF_Data* aafd, cfbNode* Node, aafClass* Class, aafObject* Parent) { - aafObject* Obj = calloc (sizeof (aafObject), sizeof (unsigned char)); + aafObject* Obj = calloc (1, sizeof (aafObject)); - if (Obj == NULL) { - error ("%s.", strerror (errno)); + if (!Obj) { + error ("Out of memory"); return NULL; } - cfb_w16towchar (Obj->Name, Node->_ab, Node->_cb); - + Obj->Name = cfb_w16toUTF8 (Node->_ab, Node->_cb); Obj->aafd = aafd; Obj->Class = Class; Obj->Node = Node; @@ -1349,10 +1618,10 @@ newObject (AAF_Data* aafd, cfbNode* Node, aafClass* Class, aafObject* Parent) static aafProperty* newProperty (AAF_Data* aafd, aafPropertyDef* Def) { - aafProperty* Prop = calloc (sizeof (aafProperty), sizeof (unsigned char)); + aafProperty* Prop = calloc (1, sizeof (aafProperty)); - if (Prop == NULL) { - error ("%s.", strerror (errno)); + if (!Prop) { + error ("Out of memory"); return NULL; } @@ -1379,8 +1648,8 @@ setObjectStrongRefSet (aafObject* Obj, aafStrongRefSetHeader_t* Header, aafStron Obj->Header = malloc (sizeof (aafStrongRefSetHeader_t)); - if (Obj->Header == NULL) { - error ("%s.", strerror (errno)); + if (!Obj->Header) { + error ("Out of memory"); return -1; } @@ -1391,8 +1660,8 @@ setObjectStrongRefSet (aafObject* Obj, aafStrongRefSetHeader_t* Header, aafStron Obj->Entry = malloc (entrySize); - if (Obj->Entry == NULL) { - error ("%s.", strerror (errno)); + if (!Obj->Entry) { + error ("Out of memory"); return -1; } @@ -1413,19 +1682,19 @@ setObjectStrongRefVector (aafObject* Obj, aafStrongRefVectorHeader_t* Header, aa AAF_Data* aafd = Obj->aafd; - Obj->Header = calloc (sizeof (aafStrongRefSetHeader_t), sizeof (unsigned char)); + Obj->Header = calloc (1, sizeof (aafStrongRefSetHeader_t)); - if (Obj->Header == NULL) { - error ("%s.", strerror (errno)); + if (!Obj->Header) { + error ("Out of memory"); return -1; } memcpy (Obj->Header, Header, sizeof (aafStrongRefVectorHeader_t)); - Obj->Entry = calloc (sizeof (aafStrongRefSetEntry_t), sizeof (unsigned char)); + Obj->Entry = calloc (1, sizeof (aafStrongRefSetEntry_t)); - if (Obj->Entry == NULL) { - error ("%s.", strerror (errno)); + if (!Obj->Entry) { + error ("Out of memory"); return -1; } @@ -1438,35 +1707,37 @@ static int retrieveStrongReference (AAF_Data* aafd, aafProperty* Prop, aafObject* Parent) { /* - * Initial property value is a wchar string holding the name of a child node. - * This child node being the object referenced, we store that object dirctly + * Initial property value is a unicode string holding the name of a child node. + * This child node being the object referenced, we store that object directly * as the property value, instead of the initial child node name. */ - wchar_t name[CFB_NODE_NAME_SZ]; - - cfb_w16towchar (name, Prop->val, Prop->len); + char* name = cfb_w16toUTF8 (Prop->val, Prop->len); free (Prop->val); Prop->val = NULL; cfbNode* Node = cfb_getChildNode (aafd->cfbd, name, Parent->Node); - if (Node == NULL) { + free (name); + + if (!Node) { error ("Could not find child node."); return -1; } aafClass* Class = aafclass_getClassByID (aafd, (aafUID_t*)&Node->_clsId); - if (Class == NULL) { - error ("Could not retrieve Class %ls @ \"%ls\".", aaft_ClassIDToText (aafd, (aafUID_t*)&Node->_clsId), aaf_get_ObjectPath (Parent)); + if (!Class) { + error ("Could not retrieve Class %s @ \"%s\".", + aaft_ClassIDToText (aafd, (aafUID_t*)&Node->_clsId), + aaf_get_ObjectPath (Parent)); return -1; } Prop->val = newObject (aafd, Node, Class, Parent); - if (Prop->val == NULL) { + if (!Prop->val) { return -1; } @@ -1485,31 +1756,29 @@ retrieveStrongReferenceSet (AAF_Data* aafd, aafProperty* Prop, aafObject* Parent aafStrongRefSetHeader_t* Header = NULL; aafStrongRefSetEntry_t* Entry = NULL; - wchar_t refName[CFB_NODE_NAME_SZ]; - - cfb_w16towchar (refName, Prop->val, Prop->len); + char* refName = cfb_w16toUTF8 (Prop->val, Prop->len); free (Prop->val); Prop->val = NULL; cfbNode* Node = getStrongRefIndexNode (aafd, Parent, refName); - if (Node == NULL) { + if (!Node) { error ("Could not retrieve StrongReferenceSet's Index node."); goto err; } Header = getStrongRefSetList (aafd, Node, Parent); - if (Header == NULL) { + if (!Header) { error ("Could not retrieve StrongReferenceSet's CFB Stream."); goto err; } Entry = malloc (sizeof (aafStrongRefSetEntry_t) + Header->_identificationSize); - if (Entry == NULL) { - error ("%s.", strerror (errno)); + if (!Entry) { + error ("Out of memory"); goto err; } @@ -1522,20 +1791,21 @@ retrieveStrongReferenceSet (AAF_Data* aafd, aafProperty* Prop, aafObject* Parent { Node = getStrongRefEntryNode (aafd, Parent, refName, Entry->_localKey); - if (Node == NULL) { + if (!Node) { continue; } aafClass* Class = aafclass_getClassByID (aafd, (aafUID_t*)&Node->_clsId); - if (Class == NULL) { - error ("Could not retrieve Class %ls.", aaft_ClassIDToText (aafd, (aafUID_t*)&Node->_clsId)); + if (!Class) { + error ("Could not retrieve Class %s.", + aaft_ClassIDToText (aafd, (aafUID_t*)&Node->_clsId)); continue; } aafObject* Obj = newObject (aafd, Node, Class, Parent); - if (Obj == NULL) { + if (!Obj) { goto err; } @@ -1563,11 +1833,9 @@ err: end: - if (Header) - free (Header); - - if (Entry) - free (Entry); + free (refName); + free (Header); + free (Entry); return rc; } @@ -1578,22 +1846,20 @@ retrieveStrongReferenceVector (AAF_Data* aafd, aafProperty* Prop, aafObject* Par int rc = 0; aafByte_t* vectorStream = NULL; - wchar_t refName[CFB_NODE_NAME_SZ]; - - cfb_w16towchar (refName, Prop->val, Prop->len); + char* refName = cfb_w16toUTF8 (Prop->val, Prop->len); free (Prop->val); Prop->val = NULL; cfbNode* Node = getStrongRefIndexNode (aafd, Parent, refName); - if (Node == NULL) { + if (!Node) { goto err; } vectorStream = getStrongRefVectorList (aafd, Node, Parent); - if (vectorStream == NULL) { + if (!vectorStream) { error ("Could not retrieve StrongRefVectorList"); goto err; } @@ -1609,20 +1875,21 @@ retrieveStrongReferenceVector (AAF_Data* aafd, aafProperty* Prop, aafObject* Par { Node = getStrongRefEntryNode (aafd, Parent, refName, Entry._localKey); - if (Node == NULL) { + if (!Node) { continue; } aafClass* Class = aafclass_getClassByID (aafd, (aafUID_t*)&Node->_clsId); - if (Class == NULL) { - warning ("Could not retrieve Class ID %ls.", aaft_ClassIDToText (aafd, (aafUID_t*)&Node->_clsId)); + if (!Class) { + warning ("Could not retrieve Class ID %s.", + aaft_ClassIDToText (aafd, (aafUID_t*)&Node->_clsId)); continue; } aafObject* Obj = newObject (aafd, Node, Class, Parent); - if (Obj == NULL) { + if (!Obj) { goto err; } @@ -1646,7 +1913,7 @@ retrieveStrongReferenceVector (AAF_Data* aafd, aafProperty* Prop, aafObject* Par aafObject* tmp = Prop->val; for (; tmp != NULL; tmp = tmp->next) - if (tmp->next == NULL) + if (!tmp->next) break; Obj->prev = tmp; @@ -1664,9 +1931,8 @@ err: rc = -1; end: - - if (vectorStream) - free (vectorStream); + free (refName); + free (vectorStream); return rc; } @@ -1678,7 +1944,7 @@ retrieveProperty (AAF_Data* aafd, aafObject* Obj, aafPropertyDef* Def, aafProper aafProperty* Prop = newProperty (aafd, Def); - if (Prop == NULL) { + if (!Prop) { return -1; } @@ -1693,8 +1959,9 @@ retrieveProperty (AAF_Data* aafd, aafObject* Obj, aafPropertyDef* Def, aafProper Prop->val = malloc (p->_length); - if (Prop->val == NULL) { - error ("%s.", strerror (errno)); + if (!Prop->val) { + error ("Out of memory"); + free (Prop); return -1; } @@ -1727,8 +1994,10 @@ retrieveObjectProperties (AAF_Data* aafd, aafObject* Obj) aafByte_t* propStream = getNodeProperties (aafd, Obj->Node); - if (propStream == NULL) { - error ("Could not retrieve object %ls properties : %ls", aaft_ClassIDToText (aafd, Obj->Class->ID), aaf_get_ObjectPath (Obj)); + if (!propStream) { + error ("Could not retrieve object %s properties : %s", + aaft_ClassIDToText (aafd, Obj->Class->ID), + aaf_get_ObjectPath (Obj)); goto err; } @@ -1740,7 +2009,7 @@ retrieveObjectProperties (AAF_Data* aafd, aafObject* Obj) aafByte_t* value = NULL; aafPropertyDef* PDef = NULL; - int valueOffset = 0; + size_t valueOffset = 0; uint32_t i = 0; @@ -1748,15 +2017,20 @@ retrieveObjectProperties (AAF_Data* aafd, aafObject* Obj) { PDef = aafclass_getPropertyDefinitionByID (Obj->Class, Prop._pid); - if (PDef == NULL) { - warning ("Unknown property 0x%04x (%ls) of object %ls", Prop._pid, aaft_PIDToText (aafd, Prop._pid), aaft_ClassIDToText (aafd, Obj->Class->ID)); + if (!PDef) { + warning ("Unknown property 0x%04x (%s) of object %s", + Prop._pid, + aaft_PIDToText (aafd, Prop._pid), + aaft_ClassIDToText (aafd, Obj->Class->ID)); continue; } rc = retrieveProperty (aafd, Obj, PDef, &Prop, value, Header._byteOrder); if (rc < 0) { - error ("Could not retrieve property %ls of object %ls", aaft_PIDToText (aafd, PDef->pid), aaft_ClassIDToText (aafd, Obj->Class->ID)); + error ("Could not retrieve property %s of object %s", + aaft_PIDToText (aafd, PDef->pid), + aaft_ClassIDToText (aafd, Obj->Class->ID)); goto err; } } @@ -1769,23 +2043,29 @@ err: end: - if (propStream) - free (propStream); + free (propStream); return rc; } static cfbNode* -getStrongRefIndexNode (AAF_Data* aafd, aafObject* Parent, const wchar_t* refName) +getStrongRefIndexNode (AAF_Data* aafd, aafObject* Parent, const char* refName) { - wchar_t name[CFB_NODE_NAME_SZ]; + char name[CFB_NODE_NAME_SZ]; - swprintf (name, CFB_NODE_NAME_SZ, L"%" WPRIws L" index", refName); + int rc = snprintf (name, CFB_NODE_NAME_SZ, "%s index", refName); + + if (rc < 0 || (size_t)rc >= CFB_NODE_NAME_SZ) { + error ("snprintf() error"); + return NULL; + } cfbNode* Node = cfb_getChildNode (aafd->cfbd, name, Parent->Node); - if (Node == NULL) { - error ("Could not retrieve Reference Set/Vector Index Node @ \"%ls/%ls index\"", aaf_get_ObjectPath (Parent), refName); + if (!Node) { + error ("Could not retrieve Reference Set/Vector Index Node @ \"%s/%s index\"", + aaf_get_ObjectPath (Parent), + refName); return NULL; } @@ -1793,16 +2073,23 @@ getStrongRefIndexNode (AAF_Data* aafd, aafObject* Parent, const wchar_t* refName } static cfbNode* -getStrongRefEntryNode (AAF_Data* aafd, aafObject* Parent, const wchar_t* refName, uint16_t index) +getStrongRefEntryNode (AAF_Data* aafd, aafObject* Parent, const char* refName, uint32_t index) { - wchar_t name[CFB_NODE_NAME_SZ]; + char name[CFB_NODE_NAME_SZ]; - swprintf (name, CFB_NODE_NAME_SZ, L"%" WPRIws L"{%x}", refName, index); + int rc = snprintf (name, CFB_NODE_NAME_SZ, "%s{%x}", refName, index); + + if (rc < 0 || (size_t)rc >= CFB_NODE_NAME_SZ) { + error ("snprintf() error"); + return NULL; + } cfbNode* Node = cfb_getChildNode (aafd->cfbd, name, Parent->Node); - if (Node == NULL) { - error ("Could not retrieve Reference Set/vector Entry Node @ \"%ls/%ls index\"", aaf_get_ObjectPath (Parent), refName); + if (!Node) { + error ("Could not retrieve Reference Set/vector Entry Node @ \"%s/%s index\"", + aaf_get_ObjectPath (Parent), + refName); return NULL; } @@ -1812,7 +2099,7 @@ getStrongRefEntryNode (AAF_Data* aafd, aafObject* Parent, const wchar_t* refName static aafByte_t* getNodeProperties (AAF_Data* aafd, cfbNode* Node) { - if (Node == NULL) { + if (!Node) { error ("Node is NULL"); return NULL; } @@ -1820,16 +2107,16 @@ getNodeProperties (AAF_Data* aafd, cfbNode* Node) uint64_t stream_sz = 0; aafByte_t* stream = NULL; - cfbNode* propNode = cfb_getChildNode (aafd->cfbd, L"properties", Node); + cfbNode* propNode = cfb_getChildNode (aafd->cfbd, "properties", Node); - if (propNode == NULL) { + if (!propNode) { error ("Could not retrieve Property Node"); return NULL; } cfb_getStream (aafd->cfbd, propNode, &stream, &stream_sz); - if (stream == NULL) { + if (!stream) { error ("Could not retrieve Property Stream"); return NULL; } @@ -1848,7 +2135,7 @@ getNodeProperties (AAF_Data* aafd, cfbNode* Node) prop_sz += (((aafPropertyIndexEntry_t*)(stream+((sizeof(aafPropertyIndexEntry_t)*i)+sizeof(aafPropertyIndexHeader_t))))->_length) + sizeof(aafPropertyIndexEntry_t); if ( prop_sz != stream_sz ) - warning( "Stream length (%lu Bytes) does not match property length (%u Bytes).", + warning( L"Stream length (%lu Bytes) does not match property length (%u Bytes).", stream_sz, prop_sz ); */ @@ -1859,7 +2146,7 @@ getNodeProperties (AAF_Data* aafd, cfbNode* Node) static aafStrongRefSetHeader_t* getStrongRefSetList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent) { - if (Node == NULL) + if (!Node) return NULL; aafByte_t* stream = NULL; @@ -1867,12 +2154,14 @@ getStrongRefSetList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent) cfb_getStream (aafd->cfbd, Node, &stream, &stream_sz); - if (stream == NULL) { - wchar_t refName[CFB_NODE_NAME_SZ]; + if (!stream) { + char* refName = cfb_w16toUTF8 (Node->_ab, Node->_cb); - cfb_w16towchar (refName, Node->_ab, Node->_cb); + error ("Could not retrieve StrongReferenceSet Index Stream @ \"%s/%s index\"", + aaf_get_ObjectPath (Parent), + refName); - error ("Could not retrieve StrongReferenceSet Index Stream @ \"%ls/%ls index\"", aaf_get_ObjectPath (Parent), refName); + free (refName); return NULL; } @@ -1883,7 +2172,7 @@ getStrongRefSetList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent) static aafByte_t* getStrongRefVectorList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent) { - if (Node == NULL) + if (!Node) return NULL; aafByte_t* stream = NULL; @@ -1891,12 +2180,13 @@ getStrongRefVectorList (AAF_Data* aafd, cfbNode* Node, aafObject* Parent) cfb_getStream (aafd->cfbd, Node, &stream, &stream_sz); - if (stream == NULL) { - wchar_t refName[CFB_NODE_NAME_SZ]; + if (!stream) { + char* refName = cfb_w16toUTF8 (Node->_ab, Node->_cb); - cfb_w16towchar (refName, Node->_ab, Node->_cb); + error ("Could not retrieve StrongReferenceVector Index Stream \"%s/%s index\"", + aaf_get_ObjectPath (Parent), + refName); - error ("Could not retrieve StrongReferenceVector Index Stream \"%ls/%ls index\"", aaf_get_ObjectPath (Parent), refName); return NULL; } diff --git a/libs/aaf/AAFDump.c b/libs/aaf/AAFDump.c index 3a49397839..7b77441df4 100644 --- a/libs/aaf/AAFDump.c +++ b/libs/aaf/AAFDump.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -21,68 +21,134 @@ #include #include +#include "aaf/AAFDefs/AAFClassDefUIDs.h" +#include "aaf/AAFDefs/AAFPropertyIDs.h" +#include "aaf/AAFDefs/AAFTypeDefUIDs.h" #include "aaf/AAFDump.h" #include "aaf/AAFToText.h" #include "aaf/AAFTypes.h" -#include "aaf/AAFClass.h" #include "aaf/utils.h" +#include "aaf/AAFClass.h" + void -aaf_dump_Header (AAF_Data* aafd) +aaf_dump_Header (AAF_Data* aafd, const char* padding) { - struct dbg* dbg = aafd->dbg; + struct aafLog* log = aafd->log; - DBG_BUFFER_WRITE (dbg, " ByteOrder : %ls (0x%04x)\n", aaft_ByteOrderToText (aafd->Header.ByteOrder), aafd->Header.ByteOrder); - DBG_BUFFER_WRITE (dbg, " LastModified : %ls\n", aaft_TimestampToText (aafd->Header.LastModified)); - DBG_BUFFER_WRITE (dbg, " AAF ObjSpec Version : %ls\n", aaft_VersionToText (aafd->Header.Version)); - DBG_BUFFER_WRITE (dbg, " ObjectModel Version : %u\n", aafd->Header.ObjectModelVersion); - DBG_BUFFER_WRITE (dbg, " Operational Pattern : %ls\n", aaft_OPDefToText (aafd->Header.OperationalPattern)); + LOG_BUFFER_WRITE (log, "%sByteOrder : %s%s (0x%04x)%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_ByteOrderToText (aafd->Header.ByteOrder), aafd->Header.ByteOrder, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sLastModified : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_TimestampToText (aafd->Header.LastModified), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sAAF ObjSpec Version : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_VersionToText (aafd->Header.Version), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sObjectModel Version : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), aafd->Header.ObjectModelVersion, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sOperational Pattern : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_OPDefToText (aafd->Header.OperationalPattern), ANSI_COLOR_RESET (log)); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -aaf_dump_Identification (AAF_Data* aafd) +aaf_dump_Identification (AAF_Data* aafd, const char* padding) { - struct dbg* dbg = aafd->dbg; + struct aafLog* log = aafd->log; - DBG_BUFFER_WRITE (dbg, " CompanyName : %ls\n", (aafd->Identification.CompanyName) ? aafd->Identification.CompanyName : L"n/a"); - DBG_BUFFER_WRITE (dbg, " ProductName : %ls\n", (aafd->Identification.ProductName) ? aafd->Identification.ProductName : L"n/a"); - DBG_BUFFER_WRITE (dbg, " ProductVersion : %ls\n", aaft_ProductVersionToText (aafd->Identification.ProductVersion)); - DBG_BUFFER_WRITE (dbg, " ProductVersionString : %ls\n", (aafd->Identification.ProductVersionString) ? aafd->Identification.ProductVersionString : L"n/a"); - DBG_BUFFER_WRITE (dbg, " ProductID : %ls\n", AUIDToText (aafd->Identification.ProductID)); - DBG_BUFFER_WRITE (dbg, " Date : %ls\n", aaft_TimestampToText (aafd->Identification.Date)); - DBG_BUFFER_WRITE (dbg, " ToolkitVersion : %ls\n", aaft_ProductVersionToText (aafd->Identification.ToolkitVersion)); - DBG_BUFFER_WRITE (dbg, " Platform : %ls\n", (aafd->Identification.Platform) ? aafd->Identification.Platform : L"n/a"); - DBG_BUFFER_WRITE (dbg, " GenerationAUID : %ls\n", AUIDToText (aafd->Identification.GenerationAUID)); + LOG_BUFFER_WRITE (log, "%sCompanyName : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), (aafd->Identification.CompanyName) ? aafd->Identification.CompanyName : "n/a", ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sProductName : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), (aafd->Identification.ProductName) ? aafd->Identification.ProductName : "n/a", ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sProductVersion : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_ProductVersionToText (aafd->Identification.ProductVersion), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sProductVersionString : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), (aafd->Identification.ProductVersionString) ? aafd->Identification.ProductVersionString : "n/a", ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sProductID : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), AUIDToText (aafd->Identification.ProductID), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sDate : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_TimestampToText (aafd->Identification.Date), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sToolkitVersion : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), aaft_ProductVersionToText (aafd->Identification.ToolkitVersion), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sPlatform : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), (aafd->Identification.Platform) ? aafd->Identification.Platform : "n/a", ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%sGenerationAUID : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), AUIDToText (aafd->Identification.GenerationAUID), ANSI_COLOR_RESET (log)); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -aaf_dump_ObjectProperty (AAF_Data* aafd, aafProperty* Prop) +aaf_dump_ObjectProperty (AAF_Data* aafd, aafProperty* Prop, const char* padding) { - struct dbg* dbg = aafd->dbg; + struct aafLog* log = aafd->log; if (Prop->def->meta) { - DBG_BUFFER_WRITE (dbg, " :.: %s(0x%04x) %ls%s (%ls)\n", ANSI_COLOR_YELLOW (dbg), Prop->pid, aaft_PIDToText (aafd, Prop->pid), ANSI_COLOR_RESET (dbg), aaft_StoredFormToText (Prop->sf) /*AUIDToText( &Prop->def->type ),*/ /*aaft_TypeIDToText( &(Prop->def->type) )*/); + LOG_BUFFER_WRITE (log, "%s%s[%s0x%04x%s] %s (%s)\n", + padding, + ANSI_COLOR_RESET (log), + ANSI_COLOR_MAGENTA (log), + Prop->pid, + ANSI_COLOR_RESET (log), + aaft_PIDToText (aafd, Prop->pid), + aaft_StoredFormToText (Prop->sf)); } else { - DBG_BUFFER_WRITE (dbg, " :.: (0x%04x) %ls (%ls)\n", Prop->pid, aaft_PIDToText (aafd, Prop->pid), aaft_StoredFormToText (Prop->sf) /*AUIDToText( &Prop->def->type ),*/ /*aaft_TypeIDToText( &(Prop->def->type) )*/); + LOG_BUFFER_WRITE (log, "%s%s[%s0x%04x%s] %s (%s)\n", + padding, + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + Prop->pid, + ANSI_COLOR_RESET (log), + aaft_PIDToText (aafd, Prop->pid), + aaft_StoredFormToText (Prop->sf)); } - // WARNING : Wont print strong references (set/vector) corectly. - aafd->dbg->_dbg_msg_pos += laaf_util_dump_hex (Prop->val, Prop->len, &aafd->dbg->_dbg_msg, &aafd->dbg->_dbg_msg_size, aafd->dbg->_dbg_msg_pos); + int rc = laaf_util_dump_hex (Prop->val, Prop->len, &aafd->log->_msg, &aafd->log->_msg_size, aafd->log->_msg_pos, padding); - dbg->debug_callback (dbg, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + if (rc > 0) { + aafd->log->_msg_pos += (size_t)rc; + } + + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -aaf_dump_ObjectProperties (AAF_Data* aafd, aafObject* Obj) +aaf_dump_TaggedValueSet (AAF_Data* aafd, aafObject* ObjCollection, const char* padding) +{ + struct aafLog* log = aafd->log; + + aafObject* Obj = NULL; + + int i = 0; + AAF_foreach_ObjectInSet (&Obj, ObjCollection, NULL) + { + i++; + + if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_TaggedValue)) { + LOG_BUFFER_WRITE (log, "%s%sObject > %s\n", + padding, + ANSI_COLOR_RESET (log), + aaft_ClassIDToText (aafd, Obj->Class->ID)); + continue; + } + + char* name = aaf_get_propertyValue (Obj, PID_TaggedValue_Name, &AAFTypeID_String); + aafIndirect_t* indirect = aaf_get_propertyValue (Obj, PID_TaggedValue_Value, &AAFTypeID_Indirect); + + LOG_BUFFER_WRITE (log, "%s%sTagged > Name: %s%s%s%*s Value: %s(%s)%s %s%s%s%s%s\n", + padding, + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + (name) ? name : "", + ANSI_COLOR_RESET (log), + (name) ? (size_t) (34 - (int)strlen (name)) : (size_t) (34 - strlen ("")), " ", + ANSI_COLOR_DARKGREY (log), + aaft_TypeIDToText (&indirect->TypeDef), + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + (aafUIDCmp (&indirect->TypeDef, &AAFTypeID_String)) ? "\"" : "", + aaft_IndirectValueToText (aafd, indirect), + (aafUIDCmp (&indirect->TypeDef, &AAFTypeID_String)) ? "\"" : "", + ANSI_COLOR_RESET (log)); + + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); + + free (name); + } +} + +void +aaf_dump_ObjectProperties (AAF_Data* aafd, aafObject* Obj, const char* padding) { /* * List the properties once they have been parsed and interpreted by AAFCore. @@ -91,20 +157,23 @@ aaf_dump_ObjectProperties (AAF_Data* aafd, aafObject* Obj) aafProperty* Prop = NULL; for (Prop = Obj->Properties; Prop != NULL; Prop = Prop->next) { - aaf_dump_ObjectProperty (aafd, Prop); + aaf_dump_ObjectProperty (aafd, Prop, padding); } } void -aaf_dump_rawProperties (AAF_Data* aafd, aafByte_t* propStream) +aaf_dump_rawProperties (AAF_Data* aafd, aafByte_t* propStream, const char* padding) { - struct dbg* dbg = aafd->dbg; + struct aafLog* log = aafd->log; if (propStream == NULL) { - DBG_BUFFER_WRITE (dbg, - " ## Property_Header____________________________________________________\n\n" - " aafPropertyIndexHeader_t is NULL\n" - " ======================================================================\n\n"); + LOG_BUFFER_WRITE (log, + "%s## Property_Header____________________________________________________\n\n" + "%saafPropertyIndexHeader_t is NULL\n" + "%s======================================================================\n\n", + padding, + padding, + padding); return; } @@ -115,53 +184,52 @@ aaf_dump_rawProperties (AAF_Data* aafd, aafByte_t* propStream) memcpy (&Header, propStream, sizeof (aafPropertyIndexHeader_t)); uint32_t i = 0; - uint32_t valueOffset = 0; + size_t valueOffset = 0; - DBG_BUFFER_WRITE (dbg, - " ## Property_Header____________________________________________________\n\n" - " _byteOrder : 0x%02x\n" - " _formatVersion : 0x%02x\n" - " _entryCount : %u\n\n" - " ======================================================================\n\n", - Header._byteOrder, - Header._formatVersion, - Header._entryCount); + LOG_BUFFER_WRITE (log, + "%s## Property_Header____________________________________________________\n\n" + "%s_byteOrder : %s0x%02x%s\n" + "%s_formatVersion : %s0x%02x%s\n" + "%s_entryCount : %s%u%s\n\n" + "%s======================================================================\n\n", + padding, + padding, ANSI_COLOR_DARKGREY (log), Header._byteOrder, ANSI_COLOR_RESET (log), + padding, ANSI_COLOR_DARKGREY (log), Header._formatVersion, ANSI_COLOR_RESET (log), + padding, ANSI_COLOR_DARKGREY (log), Header._entryCount, ANSI_COLOR_RESET (log), + padding); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); /* * Since the following for-loop macro is not intended to be user * accessible, it has been defined as a local macro in AAFCore.c. */ + foreachPropertyEntry (propStream, Header, Prop, value, valueOffset, i) + { + LOG_BUFFER_WRITE (log, + "%s#%u Property_Entry_____________________________________________________\n" + "%s_pid : %s0x%04x (%s)%s\n" + "%s_storedForm : %s%s%s\n" + "%s_length : %s%u bytes%s\n", + padding, i, + padding, ANSI_COLOR_DARKGREY (log), Prop._pid, aaft_PIDToText (aafd, Prop._pid), ANSI_COLOR_RESET (log), + padding, ANSI_COLOR_DARKGREY (log), aaft_StoredFormToText (Prop._storedForm), ANSI_COLOR_RESET (log), + padding, ANSI_COLOR_DARKGREY (log), Prop._length, ANSI_COLOR_RESET (log)); - // foreachPropertyEntry( Header, Prop, value, i ) - for (valueOffset = sizeof (aafPropertyIndexHeader_t) + (Header._entryCount * sizeof (aafPropertyIndexEntry_t)), - i = 0; - i < Header._entryCount && - memcpy (&Prop, (propStream + ((sizeof (aafPropertyIndexHeader_t)) + (sizeof (aafPropertyIndexEntry_t) * i))), sizeof (aafPropertyIndexEntry_t)) && - (value = propStream + valueOffset); - valueOffset += Prop._length, - i++) { - DBG_BUFFER_WRITE (dbg, - " #%u Property_Entry_____________________________________________________\n" - " _pid : 0x%04x (%ls)\n" - " _storedForm : %ls\n" - " _length : %u bytes\n", - i, - Prop._pid, aaft_PIDToText (aafd, Prop._pid), - aaft_StoredFormToText (Prop._storedForm), - Prop._length); + int rc = laaf_util_dump_hex (value, Prop._length, &aafd->log->_msg, &aafd->log->_msg_size, aafd->log->_msg_pos, padding); - aafd->dbg->_dbg_msg_pos += laaf_util_dump_hex (value, Prop._length, &aafd->dbg->_dbg_msg, &aafd->dbg->_dbg_msg_size, aafd->dbg->_dbg_msg_pos); + if (rc > 0) { + aafd->log->_msg_pos += (size_t)rc; + } - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); } - dbg->debug_callback (dbg, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -aaf_dump_nodeStreamProperties (AAF_Data* aafd, cfbNode* node) +aaf_dump_nodeStreamProperties (AAF_Data* aafd, cfbNode* node, const char* padding) { /* * List the raw properties directly from a CFB Node's stream. @@ -171,13 +239,13 @@ aaf_dump_nodeStreamProperties (AAF_Data* aafd, cfbNode* node) cfb_getStream (aafd->cfbd, node, &propStream, NULL); - aaf_dump_rawProperties (aafd, propStream); + aaf_dump_rawProperties (aafd, propStream, padding); free (propStream); } void -aaf_dump_MetaDictionary (AAF_Data* aafd) +aaf_dump_MetaDictionary (AAF_Data* aafd, const char* padding) { /* * NOTE Only dumps the "custom" classes/properties, since those are the only @@ -185,7 +253,7 @@ aaf_dump_MetaDictionary (AAF_Data* aafd) * wont be printed out. */ - struct dbg* dbg = aafd->dbg; + struct aafLog* log = aafd->log; aafClass* Class = NULL; @@ -198,42 +266,42 @@ aaf_dump_MetaDictionary (AAF_Data* aafd) foreachPropertyDefinition (PDef, Class->Properties) { if (Class->meta) { - DBG_BUFFER_WRITE (dbg, "%s%ls::%ls (0x%04x)%s\n", - ANSI_COLOR_YELLOW (dbg), + LOG_BUFFER_WRITE (log, "%s%s%s::%s (0x%04x)%s\n", + padding, + ANSI_COLOR_MAGENTA (log), Class->name, PDef->name, PDef->pid, - ANSI_COLOR_RESET (dbg)); + ANSI_COLOR_RESET (log)); print++; } else if (PDef->meta) { - DBG_BUFFER_WRITE (dbg, "%ls::%s%ls (0x%04x)%s\n", + LOG_BUFFER_WRITE (log, "%s%s::%s%s (0x%04x)%s\n", + padding, aaft_ClassIDToText (aafd, Class->ID), - ANSI_COLOR_YELLOW (dbg), + ANSI_COLOR_MAGENTA (log), PDef->name, PDef->pid, - ANSI_COLOR_RESET (dbg)); + ANSI_COLOR_RESET (log)); print++; } } if (print) { - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); } - - print = 1; } - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -aaf_dump_Classes (AAF_Data* aafd) +aaf_dump_Classes (AAF_Data* aafd, const char* padding) { - struct dbg* dbg = aafd->dbg; + struct aafLog* log = aafd->log; aafClass* ConcreteClass = NULL; aafClass* Class = NULL; @@ -242,19 +310,21 @@ aaf_dump_Classes (AAF_Data* aafd) { foreachClassInheritance (Class, ConcreteClass) { - DBG_BUFFER_WRITE (dbg, "%s%ls%s", - (Class->meta) ? ANSI_COLOR_YELLOW (dbg) : "", + LOG_BUFFER_WRITE (log, "%s%s%s%s", + padding, + (Class->meta) ? ANSI_COLOR_MAGENTA (log) : "", aaft_ClassIDToText (aafd, Class->ID), - (Class->meta) ? ANSI_COLOR_RESET (dbg) : ""); + (Class->meta) ? ANSI_COLOR_RESET (log) : ""); - if (Class->Parent != NULL) - DBG_BUFFER_WRITE (dbg, " > "); + if (Class->Parent != NULL) { + LOG_BUFFER_WRITE (log, " > "); + } } - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); } - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)aafd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } diff --git a/libs/aaf/AAFIAudioFiles.c b/libs/aaf/AAFIAudioFiles.c deleted file mode 100644 index 5018a8d7a4..0000000000 --- a/libs/aaf/AAFIAudioFiles.c +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright (C) 2017-2023 Adrien Gesta-Fline - * - * This file is part of libAAF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include - -#include "aaf/AAFIAudioFiles.h" -#include "aaf/AAFIface.h" -#include "aaf/debug.h" - -#include "aaf/RIFFParser.h" -#include "aaf/URIParser.h" - -#include "aaf/utils.h" - -#if defined(__linux__) -#include -#include -#include -#include /* access() */ -#elif defined(__APPLE__) -#include -#include /* access() */ -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) -#include -#define R_OK 4 /* Test for read permission. */ -#define W_OK 2 /* Test for write permission. */ -#define F_OK 0 /* Test for existence. */ -#ifndef _MSC_VER -#include // access() -#endif -#endif - -#define WAV_FILE_EXT "wav" -#define AIFF_FILE_EXT "aif" - -#define debug(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) - -#define warning(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) - -#define error(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) - -static size_t -embeddedAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3); -static size_t -externalAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3); - -wchar_t* -aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_filepath, const char* search_location) -{ - /* - * Absolute Uniform Resource Locator (URL) complying with RFC 1738 or relative - * Uniform Resource Identifier (URI) complying with RFC 2396 for file containing - * the essence. If it is a relative URI, the base URI is determined from the URI - * of the AAF file itself. - * - * Informative note: A valid URL or URI uses a constrained character set and - * uses the / character as the path separator. - */ - - char* uri_filepath = NULL; - char* local_filepath = NULL; - char* aaf_path = NULL; - char* foundpath = NULL; - wchar_t* retpath = NULL; - - struct uri* uri = NULL; - - if (original_uri_filepath == NULL) { - error ("Cant locate a NULL filepath"); - goto err; - } - - uri_filepath = laaf_util_wstr2str (original_uri_filepath); - - if (uri_filepath == NULL) { - error ("Could not convert original_uri_filepath from wstr to str : %ls", original_uri_filepath); - goto err; - } - - // debug( "Original URI : %s", uri_filepath ); - - uri = uriParse (uri_filepath, URI_OPT_DECODE_ALL, aafi->dbg); - - if (uri == NULL) { - error ("Could not parse URI"); - goto err; - } - - if (uri->path == NULL) { - error ("Could not retrieve out of URI"); - goto err; - } - - // debug( "Decoded URI's path : %s", uri->path ); - - /* extract relative path to essence file : "/" */ - - char* relativeEssencePath = NULL; - char* p = uri->path + strlen (uri->path); - - int sepcount = 0; - - while (p > uri->path) { - if (*p == '/') { /* parsing URI, so will always be '/' as separator character */ - sepcount++; - if (sepcount == 2) { - relativeEssencePath = (p + 1); - break; - } - } - p--; - } - - const char* essenceFileName = laaf_util_fop_get_file (uri->path); - - // debug( "Essence filename : %s", essenceFileName ); - - if (search_location) { - /* - * "/" - */ - - local_filepath = laaf_util_build_path (DIR_SEP_STR, search_location, essenceFileName, NULL); - - if (local_filepath == NULL) { - error ("Could not build search filepath"); - goto err; - } - - // debug( "Search filepath : %s", local_filepath ); - - if (access (local_filepath, F_OK) != -1) { - // debug( "FOUND: %s", local_filepath ); - foundpath = local_filepath; - goto found; - } - - free (local_filepath); - local_filepath = NULL; - - /* - * "//" - */ - - local_filepath = laaf_util_build_path (DIR_SEP_STR, search_location, relativeEssencePath, NULL); - - if (local_filepath == NULL) { - error ("Could not build search filepath"); - goto err; - } - - // debug( "Search filepath : %s", local_filepath ); - - if (access (local_filepath, F_OK) != -1) { - // debug( "FOUND: %s", local_filepath ); - foundpath = local_filepath; - goto found; - } - - free (local_filepath); - local_filepath = NULL; - } - - /* Try AAF essence's URI */ - - if (access (uri_filepath, F_OK) != -1) { - // debug( "FOUND: %s", uri_filepath ); - foundpath = uri_filepath; - goto found; - } - - /* Try part of URI */ - - if (access (uri->path, F_OK) != -1) { - // debug( "FOUND: %s", uri->path ); - foundpath = uri->path; - goto found; - } - - if (uri->flags & URI_T_LOCALHOST) { - // debug( "URI targets localhost : %s", uri_filepath ); - } else { - if (uri->flags & URI_T_HOST_IPV4) { - // debug( "URI targets IPV4 : %s", uri_filepath ); - } else if (uri->flags & URI_T_HOST_IPV6) { - // debug( "URI targets IPV6 : %s", uri_filepath ); - } else if (uri->flags & URI_T_HOST_REGNAME) { - // debug( "URI targets hostname : %s", uri_filepath ); - } - } - - /* - * Try to locate essence file from the AAF file location. - * - * e.g. - * - AAF filepath : /home/user/AAFFile.aaf - * - Essence URI : file://localhost/C:/Users/user/Desktop/AudioFiles/essence.wav - * = /home/user/AudioFiles/essence.file - */ - - /* extract path to AAF file */ - - aaf_path = laaf_util_c99strdup (aafi->aafd->cfbd->file); - - if (aaf_path == NULL) { - error ("Could not duplicate AAF filepath"); - goto err; - } - - p = aaf_path + strlen (aaf_path); - - while (p > aaf_path) { - if (IS_DIR_SEP (*p)) { - *p = 0x00; - break; - } - p--; - } - - /* - * "/" - */ - - local_filepath = laaf_util_build_path (DIR_SEP_STR, aaf_path, essenceFileName, NULL); - - if (local_filepath == NULL) { - error ("Could not build filepath"); - goto err; - } - - // debug( "AAF relative filepath : %s", local_filepath ); - - if (access (local_filepath, F_OK) != -1) { - // debug( "FOUND: %s", filepath ); - foundpath = local_filepath; - goto found; - } - - free (local_filepath); - local_filepath = NULL; - - /* - * "//" - */ - - local_filepath = laaf_util_build_path (DIR_SEP_STR, aaf_path, relativeEssencePath, NULL); - - if (local_filepath == NULL) { - error ("Could not build filepath"); - goto err; - } - - // debug( "AAF relative filepath : %s", local_filepath ); - - if (access (local_filepath, F_OK) != -1) { - // debug( "FOUND: %s", filepath ); - foundpath = local_filepath; - goto found; - } - - free (local_filepath); - local_filepath = NULL; - - // debug("File not found"); - -found: - if (foundpath) { - retpath = laaf_util_str2wstr (foundpath); - - if (retpath == NULL) { - error ("Could not convert foundpath from str to wstr : %s", foundpath); - goto err; - } - } - - goto end; - -err: - retpath = NULL; - -end: - if (uri) - uriFree (uri); - - if (uri_filepath) - free (uri_filepath); - - if (local_filepath) - free (local_filepath); - - if (aaf_path) - free (aaf_path); - - return retpath; - - /* - * AAFInfo --aaf-clips ../libaaf_testfiles/fonk_2.AAF - file://localhost/Users/horlaprod/Music/Logic/fonk_2/Audio Files_1/fonk_2_3#04.wav - - * AAFInfo --aaf-clips ../libaaf_testfiles/ADP/ADP3_51-ST-MONO-NOBREAKOUT.aaf - file:///C:/Users/Loviniou/Downloads/ChID-BLITS-EBU-Narration441-16b.wav - - * AAFInfo --aaf-clips ../libaaf_testfiles/ADP/ADP2_SEQ-FULL.aaf - file://?/E:/Adrien/ADPAAF/Sequence A Rendu.mxf - - * AAFInfo --aaf-clips ../libaaf_testfiles/TEST-AVID_COMP2977052\ \ -\ \ OFF\ PODIUM\ ETAPE\ 2.aaf - file:////C:/Users/mix_limo/Desktop/TEST2977052 - OFF PODIUM ETAPE 2.aaf - - * AAFInfo --aaf-clips ../ardio/watchfolder/3572607_RUGBY_F_1_1.aaf - file://10.87.230.71/mixage/DR2/Avid MediaFiles/MXF/1/3572607_RUGBY_F2_S65CFA3D0V.mxf - - * AAFInfo --aaf-clips ../libaaf_testfiles/ProTools/pt2MCC.aaf - file:///_system/Users/horlaprod/pt2MCCzmhsFRHQgdgsTMQX.mxf - */ -} - -int -aafi_extract_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence, const char* outfilepath, const wchar_t* forcedFileName) -{ - int rc = 0; - int reqlen = 0; - FILE* fp = NULL; - char* filename = NULL; - char* filepath = NULL; - - unsigned char* data = NULL; - uint64_t datasz = 0; - - if (audioEssence->is_embedded == 0) { - warning ("Audio essence is not embedded : nothing to extract"); - return -1; - } - - /* Retrieve stream from CFB */ - - cfb_getStream (aafi->aafd->cfbd, audioEssence->node, &data, &datasz); - - if (data == NULL) { - error ("Could not retrieve audio essence stream from CFB"); - goto err; - } - - /* Build file path */ - - reqlen = snprintf (NULL, 0, "%ls.%s", (forcedFileName != NULL) ? forcedFileName : audioEssence->unique_file_name, (audioEssence->type == AAFI_ESSENCE_TYPE_AIFC) ? AIFF_FILE_EXT : WAV_FILE_EXT); - - if (reqlen < 0) { - error ("Failed to build filename"); - goto err; - } - - int filenamelen = reqlen + 1; - - filename = malloc (filenamelen); - - if (filename == NULL) { - error ("Could not allocate memory : %s", strerror (errno)); - goto err; - } - - rc = snprintf (filename, filenamelen, "%ls.%s", (forcedFileName != NULL) ? forcedFileName : audioEssence->unique_file_name, (audioEssence->type == AAFI_ESSENCE_TYPE_AIFC) ? AIFF_FILE_EXT : WAV_FILE_EXT); - - if (rc < 0 || (unsigned)rc >= (unsigned)filenamelen) { - error ("Failed to build filename"); - goto err; - } - - filepath = laaf_util_build_path (DIR_SEP_STR, outfilepath, laaf_util_clean_filename (filename), NULL); - - if (filepath == NULL) { - error ("Could not build filepath"); - goto err; - } - - fp = fopen (filepath, "wb"); - - if (fp == NULL) { - error ("Could not open '%s' for writing : %s", filepath, strerror (errno)); - goto err; - } - - if (audioEssence->type == AAFI_ESSENCE_TYPE_PCM) { - struct wavFmtChunk wavFmt; - wavFmt.channels = audioEssence->channels; - wavFmt.samples_per_sec = audioEssence->samplerate; - wavFmt.bits_per_sample = audioEssence->samplesize; - - struct wavBextChunk wavBext; - memset (&wavBext, 0x00, sizeof (wavBext)); - memcpy (wavBext.umid, audioEssence->sourceMobID, sizeof (aafMobID_t)); - if (audioEssence->mobSlotEditRate) { - wavBext.time_reference = laaf_util_converUnit (audioEssence->timeReference, audioEssence->mobSlotEditRate, audioEssence->samplerateRational); - } - - if (datasz >= (uint32_t)-1) { - // TODO RF64 support ? - error ("Audio essence is bigger than maximum wav file size (2^32 bytes) : %" PRIu64 " bytes", datasz); - goto err; - } - - if (riff_writeWavFileHeader (fp, &wavFmt, &wavBext, (uint32_t)datasz, aafi->dbg) < 0) { - error ("Could not write wav audio header : %s", filepath); - goto err; - } - } - - uint64_t writtenBytes = fwrite (data, sizeof (unsigned char), datasz, fp); - - if (writtenBytes < datasz) { - error ("Could not write audio file (%" PRIu64 " bytes written out of %" PRIu64 " bytes) : %s", writtenBytes, datasz, filepath); - goto err; - } - - audioEssence->usable_file_path = malloc ((strlen (filepath) + 1) * sizeof (wchar_t)); - - if (audioEssence->usable_file_path == NULL) { - error ("Could not allocate memory : %s", strerror (errno)); - goto err; - } - - audioEssence->usable_file_path = laaf_util_str2wstr (filepath); - - if (audioEssence->usable_file_path == NULL) { - error ("Could not convert usable_file_path from str to wstr : %s", filepath); - goto err; - } - - rc = 0; - goto end; - -err: - rc = -1; - -end: - if (filename) - free (filename); - - if (filepath) - free (filepath); - - if (data) - free (data); - - if (fp) - fclose (fp); - - return rc; -} - -int -aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence) -{ - // aafi->dbg->_dbg_msg_pos += laaf_util_dump_hex( audioEssence->summary->val, audioEssence->summary->len, &aafi->dbg->_dbg_msg, &aafi->dbg->_dbg_msg_size, aafi->dbg->_dbg_msg_pos ); - - int rc = 0; - char* externalFilePath = NULL; - FILE* fp = NULL; - struct RIFFAudioFile RIFFAudioFile; - - /* try audioEssence->summary first, for both embedded and external */ - - if (audioEssence->summary) { - rc = riff_parseAudioFile (&RIFFAudioFile, RIFF_PARSE_AAF_SUMMARY, &embeddedAudioDataReaderCallback, audioEssence->summary->val, &audioEssence->summary->len, aafi, aafi->dbg); - - if (rc < 0) { - warning ("Could not parse essence summary of %ls", audioEssence->file_name); - - if (audioEssence->is_embedded) { - return -1; - } - } else { - audioEssence->channels = RIFFAudioFile.channels; - audioEssence->samplerate = RIFFAudioFile.sampleRate; - audioEssence->samplesize = RIFFAudioFile.sampleSize; - audioEssence->length = RIFFAudioFile.sampleCount; - - audioEssence->samplerateRational->numerator = audioEssence->samplerate; - audioEssence->samplerateRational->denominator = 1; - - return 0; - } - } else if (audioEssence->is_embedded) { - if (audioEssence->type != AAFI_ESSENCE_TYPE_PCM) { - warning ("TODO: Embedded audio essence has no summary. Should we try essence data stream ?"); - } - - return -1; - } else if (!audioEssence->usable_file_path) { - // warning( "Can't parse a missing external essence file" ); - return -1; - } - - if (laaf_util_fop_is_wstr_fileext (audioEssence->usable_file_path, L"wav") || - laaf_util_fop_is_wstr_fileext (audioEssence->usable_file_path, L"wave") || - laaf_util_fop_is_wstr_fileext (audioEssence->usable_file_path, L"aif") || - laaf_util_fop_is_wstr_fileext (audioEssence->usable_file_path, L"aiff") || - laaf_util_fop_is_wstr_fileext (audioEssence->usable_file_path, L"aifc")) { - externalFilePath = laaf_util_wstr2str (audioEssence->usable_file_path); - - if (externalFilePath == NULL) { - error ("Could not convert usable_file_path from wstr to str : %ls", audioEssence->usable_file_path); - goto err; - } - - fp = fopen (externalFilePath, "rb"); - - if (fp == NULL) { - error ("Could not open external audio essence file for reading : %s", externalFilePath); - goto err; - } - - rc = riff_parseAudioFile (&RIFFAudioFile, 0, &externalAudioDataReaderCallback, fp, externalFilePath, aafi, aafi->dbg); - - if (rc < 0) { - error ("Failed parsing external audio essence file : %s", externalFilePath); - goto err; - } - - if (audioEssence->channels > 0 && audioEssence->channels != RIFFAudioFile.channels) { - warning ("%ls : summary channel count (%i) mismatch located file (%i)", audioEssence->usable_file_path, audioEssence->channels, RIFFAudioFile.channels); - } - - if (audioEssence->samplerate > 0 && audioEssence->samplerate != RIFFAudioFile.sampleRate) { - warning ("%ls : summary samplerate (%i) mismatch located file (%i)", audioEssence->usable_file_path, audioEssence->samplerate, RIFFAudioFile.sampleRate); - } - - if (audioEssence->samplesize > 0 && audioEssence->samplesize != RIFFAudioFile.sampleSize) { - warning ("%ls : summary samplesize (%i) mismatch located file (%i)", audioEssence->usable_file_path, audioEssence->samplesize, RIFFAudioFile.sampleSize); - } - - if (audioEssence->length > 0 && audioEssence->length != RIFFAudioFile.sampleCount) { - warning ("%ls : summary samplecount (%" PRIi64 ") mismatch located file (%" PRIi64 ")", audioEssence->usable_file_path, audioEssence->length, RIFFAudioFile.sampleCount); - } - - audioEssence->channels = RIFFAudioFile.channels; - audioEssence->samplerate = RIFFAudioFile.sampleRate; - audioEssence->samplesize = RIFFAudioFile.sampleSize; - audioEssence->length = RIFFAudioFile.sampleCount; - - audioEssence->samplerateRational->numerator = audioEssence->samplerate; - audioEssence->samplerateRational->denominator = 1; - } else { - /* - * should be considered as a non-pcm audio format - * -│ 04317│├──◻ AAFClassID_TimelineMobSlot [slot:6 track:4] (DataDef : AAFDataDef_Sound) : Audio 4 - Layered Audio Editing -│ 01943││ └──◻ AAFClassID_Sequence -│ 02894││ └──◻ AAFClassID_SourceClip -│ 02899││ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : speech-sample -│ 04405││ └──◻ AAFClassID_TimelineMobSlot [slot:1 track:1] (DataDef : AAFDataDef_Sound) -│ 03104││ └──◻ AAFClassID_SourceClip -│ 04140││ └──◻ AAFClassID_SourceMob (UsageCode: n/a) : speech-sample -│ 01287││ └──◻ AAFClassID_PCMDescriptor -│ 01477││ └──◻ AAFClassID_NetworkLocator : file:///C:/Users/user/Desktop/libAAF/test/res/speech-sample.mp3 - * - */ - - audioEssence->type = AAFI_ESSENCE_TYPE_UNK; - - // /* clears any wrong data previously retrieved out of AAFClassID_PCMDescriptor */ - // audioEssence->samplerate = 0; - // audioEssence->samplesize = 0; - } - - rc = 0; - goto end; - -err: - rc = -1; - -end: - if (fp) - fclose (fp); - - if (externalFilePath) - free (externalFilePath); - - return rc; -} - -static size_t -embeddedAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3) -{ - unsigned char* data = user1; - size_t datasz = *(size_t*)user2; - AAF_Iface* aafi = (AAF_Iface*)user3; - - if (offset > datasz) { - error ("Requested data starts beyond data length"); - return -1; - } - - if (offset + reqLen > datasz) { - reqLen = datasz - (offset + reqLen); - } - - memcpy (buf, data + offset, reqLen); - - return reqLen; -} - -static size_t -externalAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3) -{ - FILE* fp = (FILE*)user1; - const char* filename = (const char*)user2; - AAF_Iface* aafi = (AAF_Iface*)user3; - - if (fseek (fp, offset, SEEK_SET) < 0) { - error ("Could not seek to %zu in file '%s' : %s", offset, filename, strerror (errno)); - return -1; - } - - size_t read = fread (buf, sizeof (unsigned char), reqLen, fp); - - if (read < reqLen) { - error ("File read failed at %zu (expected %zu, read %zu) in file '%s' : %s", offset, reqLen, read, filename, strerror (errno)); - return -1; - } - - return read; -} diff --git a/libs/aaf/AAFIEssenceFile.c b/libs/aaf/AAFIEssenceFile.c new file mode 100644 index 0000000000..be32f942fe --- /dev/null +++ b/libs/aaf/AAFIEssenceFile.c @@ -0,0 +1,941 @@ +/* + * Copyright (C) 2017-2024 Adrien Gesta-Fline + * + * This file is part of libAAF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include "aaf/AAFIEssenceFile.h" +#include "aaf/AAFIface.h" +#include "aaf/log.h" +#include "aaf/version.h" + +#include "aaf/MediaComposer.h" +#include "aaf/utils.h" + +#include "aaf/RIFFParser.h" +#include "aaf/URIParser.h" + +#define debug(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + +#define success(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_SUCCESS, __VA_ARGS__) + +#define warning(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + +#define error(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) + +static int +set_audioEssenceWithRIFF (AAF_Iface* aafi, const char* filename, aafiAudioEssenceFile* audioEssenceFile, struct RIFFAudioFile* RIFFAudioFile, int isExternalFile); +static size_t +embeddedAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3); +static size_t +externalAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3); + +int +aafi_build_unique_audio_essence_name (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFile) +{ + if (audioEssenceFile->unique_name) { + debug ("Unique name was already set"); + return -1; + } + + if (aafi->ctx.options.mobid_essence_filename) { + aafUID_t* uuid = &(audioEssenceFile->sourceMobID->material); + + int rc = laaf_util_snprintf_realloc (&audioEssenceFile->unique_name, 0, 0, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", + uuid->Data1, + uuid->Data2, + uuid->Data3, + uuid->Data4[0], + uuid->Data4[1], + uuid->Data4[2], + uuid->Data4[3], + uuid->Data4[4], + uuid->Data4[5], + uuid->Data4[6], + uuid->Data4[7]); + + if (rc < 0) { + error ("Failed to set unique filename with SourceMobID UID"); + free (audioEssenceFile->unique_name); + return -1; + } + + return 0; + } else { + audioEssenceFile->unique_name = laaf_util_c99strdup ((audioEssenceFile->name) ? audioEssenceFile->name : "unknown"); + + if (!audioEssenceFile->unique_name) { + error ("Could not duplicate essence name : %s", (audioEssenceFile->name) ? audioEssenceFile->name : "unknown"); + return -1; + } + } + + size_t unique_size = strlen (audioEssenceFile->unique_name) + 1; + + int index = 0; + aafiAudioEssenceFile* ae = NULL; + + AAFI_foreachAudioEssenceFile (aafi, ae) + { + if (ae != audioEssenceFile && ae->unique_name != NULL && strcmp (ae->unique_name, audioEssenceFile->unique_name) == 0) { + if (laaf_util_snprintf_realloc (&audioEssenceFile->unique_name, &unique_size, 0, "%s_%i", (audioEssenceFile->name) ? audioEssenceFile->name : "unknown", ++index) < 0) { + error ("Failed to increment unique filename"); + return -1; + } + + /* recheck entire essence list */ + ae = aafi->Audio->essenceFiles; + } + } + + return 0; +} + +char* +aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_filepath, const char* search_location) +{ + /* + * Absolute Uniform Resource Locator (URL) complying with RFC 1738 or relative + * Uniform Resource Identifier (URI) complying with RFC 2396 for file containing + * the essence. If it is a relative URI, the base URI is determined from the URI + * of the AAF file itself. + * + * Informative note: A valid URL or URI uses a constrained character set and + * uses the / character as the path separator. + */ + + char* local_filepath = NULL; + char* aaf_path = NULL; + const char* foundpath = NULL; + char* retpath = NULL; + + struct uri* uri = NULL; + + if (original_uri_filepath == NULL) { + error ("Cant locate a NULL filepath"); + goto err; + } + + debug ("Original URI : %s", original_uri_filepath); + + uri = laaf_uri_parse (original_uri_filepath, URI_OPT_DECODE_ALL, aafi->log); + + if (uri == NULL) { + error ("Could not parse URI"); + goto err; + } + + if (uri->path == NULL) { + error ("Could not retrieve out of URI"); + goto err; + } + + debug ("Decoded URI's path : %s", uri->path); + + /* extract relative path to essence file : "/" */ + + const char* relativeEssencePath = NULL; + const char* essenceFileName = NULL; + + int sepcount = 0; + char* p = uri->path + strlen (uri->path); + + while (p > uri->path) { + if (*p == '/') { /* parsing URI, so will always be '/' as separator character */ + sepcount++; + if (sepcount == 1) { + essenceFileName = (p + 1); + } else if (sepcount == 2) { + relativeEssencePath = (p + 1); + break; + } + } + p--; + } + + if (!relativeEssencePath) { + error ("Could not retrieve relative file path out of URI : %s", uri->path); + goto err; + } + + if (!essenceFileName) { + error ("Could not retrieve file name out of URI : %s", uri->path); + goto err; + } + + debug ("Essence filename : %s", essenceFileName); + + if (search_location) { + /* + * "/" + */ + + local_filepath = laaf_util_build_path ("/", search_location, essenceFileName, NULL); + + if (!local_filepath) { + error ("Could not build search filepath"); + goto err; + } + + debug ("Search filepath : %s", local_filepath); + + if (laaf_util_file_exists (local_filepath) == 1) { + foundpath = local_filepath; + goto found; + } + + free (local_filepath); + local_filepath = NULL; + + /* + * "//" + */ + + local_filepath = laaf_util_build_path ("/", search_location, relativeEssencePath, NULL); + + if (!local_filepath) { + error ("Could not build search filepath"); + goto err; + } + + debug ("Search filepath : %s", local_filepath); + + if (laaf_util_file_exists (local_filepath) == 1) { + foundpath = local_filepath; + goto found; + } + + free (local_filepath); + local_filepath = NULL; + } + + /* Try AAF essence's URI */ + + if (laaf_util_file_exists (original_uri_filepath) == 1) { + foundpath = original_uri_filepath; + goto found; + } + + /* Try part of URI */ + + if (laaf_util_file_exists (uri->path) == 1) { + foundpath = uri->path; + goto found; + } + + if (uri->flags & URI_T_LOCALHOST) { + // debug( "URI targets localhost : %s", uri_filepath ); + } else { + if (uri->flags & URI_T_HOST_IPV4) { + // debug( "URI targets IPV4 : %s", uri_filepath ); + } else if (uri->flags & URI_T_HOST_IPV6) { + // debug( "URI targets IPV6 : %s", uri_filepath ); + } else if (uri->flags & URI_T_HOST_REGNAME) { + // debug( "URI targets hostname : %s", uri_filepath ); + } + } + + /* + * Try to locate essence file from the AAF file location. + * + * e.g. + * - AAF filepath : /home/user/AAFFile.aaf + * - Essence URI : file://localhost/C:/Users/user/Desktop/AudioFiles/essence.wav + * = /home/user/AudioFiles/essence.file + */ + + /* extract path to AAF file */ + + aaf_path = laaf_util_c99strdup (aafi->aafd->cfbd->file); + + if (!aaf_path) { + error ("Could not duplicate AAF filepath : %s", aafi->aafd->cfbd->file); + goto err; + } + + p = aaf_path + strlen (aaf_path); + + while (p > aaf_path) { + if (IS_DIR_SEP (*p)) { + *p = 0x00; + break; + } + p--; + } + + /* + * "/" + */ + + local_filepath = laaf_util_build_path (DIR_SEP_STR, aaf_path, essenceFileName, NULL); + + if (!local_filepath) { + error ("Could not build filepath"); + goto err; + } + + debug ("AAF relative filepath : %s", local_filepath); + + if (laaf_util_file_exists (local_filepath) == 1) { + foundpath = local_filepath; + goto found; + } + + free (local_filepath); + local_filepath = NULL; + + /* + * "//" + */ + + local_filepath = laaf_util_build_path (DIR_SEP_STR, aaf_path, relativeEssencePath, NULL); + + if (!local_filepath) { + error ("Could not build filepath"); + goto err; + } + + debug ("AAF relative sub filepath : %s", local_filepath); + + if (laaf_util_file_exists (local_filepath) == 1) { + foundpath = local_filepath; + goto found; + } + + free (local_filepath); + local_filepath = NULL; + + debug ("File not found"); + +found: + if (foundpath) { + /* + * When runing through wine, computing absolute path adds a Z:/ drive letter. + * This causes issue when trying to make relative essence path from the AAF + * file path, since it also went through laaf_util_absolute_path(). + * So even if foundpath is already absolute, we need that drive letter at it + * start. + */ + // retpath = laaf_util_c99strdup(foundpath); + retpath = laaf_util_absolute_path (foundpath); + + if (!retpath) { + error ("Could not make absolute path to located file : %s", foundpath); + goto err; + } + + debug ("File found at : %s", foundpath); + } + + goto end; + +err: + retpath = NULL; + +end: + laaf_uri_free (uri); + + free (local_filepath); + free (aaf_path); + + return retpath; + + /* + * AAFInfo --aaf-clips ../libaaf_testfiles/fonk_2.AAF + file://localhost/Users/horlaprod/Music/Logic/fonk_2/Audio Files_1/fonk_2_3#04.wav + + * AAFInfo --aaf-clips ../libaaf_testfiles/ADP/ADP3_51-ST-MONO-NOBREAKOUT.aaf + file:///C:/Users/Loviniou/Downloads/ChID-BLITS-EBU-Narration441-16b.wav + + * AAFInfo --aaf-clips ../libaaf_testfiles/ADP/ADP2_SEQ-FULL.aaf + file://?/E:/Adrien/ADPAAF/Sequence A Rendu.mxf + + * AAFInfo --aaf-clips ../libaaf_testfiles/TEST-AVID_COMP2977052\ \ -\ \ OFF\ PODIUM\ ETAPE\ 2.aaf + file:////C:/Users/mix_limo/Desktop/TEST2977052 - OFF PODIUM ETAPE 2.aaf + + * AAFInfo --aaf-clips ../ardio/watchfolder/3572607_RUGBY_F_1_1.aaf + file://10.87.230.71/mixage/DR2/Avid MediaFiles/MXF/1/3572607_RUGBY_F2_S65CFA3D0V.mxf + + * AAFInfo --aaf-clips ../libaaf_testfiles/ProTools/pt2MCC.aaf + file:///_system/Users/horlaprod/pt2MCCzmhsFRHQgdgsTMQX.mxf + */ +} + +int +aafi_extractAudioEssenceFile (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFile, enum aafiExtractFormat extractFormat, const char* outpath, uint64_t sampleOffset, uint64_t sampleLength, const char* forcedFileName, char** usable_file_path) +{ + int rc = 0; + int tmp = 0; + FILE* fp = NULL; + char* filename = NULL; + char* filepath = NULL; + + int write_header = 0; + int extracting_clip = 0; + + unsigned char* data = NULL; + uint64_t datasz = 0; + + if (audioEssenceFile->is_embedded == 0) { + error ("Audio essence is not embedded : nothing to extract"); + goto err; + } + + if (!outpath) { + error ("Missing output path"); + goto err; + } + + if (audioEssenceFile->usable_file_path) { + debug ("usable_file_path was already set"); + free (audioEssenceFile->usable_file_path); + audioEssenceFile->usable_file_path = NULL; + } + + uint64_t pcmByteOffset = sampleOffset * audioEssenceFile->channels * (audioEssenceFile->samplesize / 8); + uint64_t pcmByteLength = sampleLength * audioEssenceFile->channels * (audioEssenceFile->samplesize / 8); + + /* Retrieve stream from CFB */ + + cfb_getStream (aafi->aafd->cfbd, audioEssenceFile->node, &data, &datasz); + + if (data == NULL) { + error ("Could not retrieve audio essence stream from CFB"); + goto err; + } + + /* Calculate offset and length */ + + debug ("Requesting extract of essence \"%s\"", audioEssenceFile->name); + debug (" - ReqSampleOffset: %" PRIu64 " samples (%" PRIu64 " bytes)", sampleOffset, pcmByteOffset); + debug (" - ReqSampleLength: %" PRIu64 " samples (%" PRIu64 " bytes)", sampleLength, pcmByteLength); + debug (" - FileHeaderOffset: %" PRIu64 " bytes (0x%04" PRIx64 ")", + audioEssenceFile->pcm_audio_start_offset, + audioEssenceFile->pcm_audio_start_offset); + debug (" - EssenceTotalLength: %" PRIu64 " bytes", datasz); + + uint64_t sourceFileOffset = 0; + + if (pcmByteOffset || + pcmByteLength || + extractFormat != AAFI_EXTRACT_DEFAULT) { + if (audioEssenceFile->type != AAFI_ESSENCE_TYPE_PCM) { + sourceFileOffset += audioEssenceFile->pcm_audio_start_offset; + } + write_header = 1; + } + + if (pcmByteOffset || pcmByteLength) { + extracting_clip = 1; + } + + sourceFileOffset += pcmByteOffset; + + if ((datasz - audioEssenceFile->pcm_audio_start_offset) < (pcmByteLength + sourceFileOffset)) { + error ("Requested audio range (%" PRIi64 " bytes) is bigger than source audio size (%" PRIu64 " bytes)", + (pcmByteLength + sourceFileOffset), + datasz - audioEssenceFile->pcm_audio_start_offset); + goto err; + } + + datasz = (pcmByteLength) ? pcmByteLength : (datasz - sourceFileOffset); + + if (datasz >= (uint32_t)-1) { + error ("Audio essence is bigger than maximum wav file size (2^32 bytes) : %" PRIu64 " bytes", datasz); + goto err; + } + + debug (" - Calculated Offset: %" PRIu64 " bytes", sourceFileOffset); + debug (" - Calculated Length: %" PRIu64 " bytes", datasz); + + if (audioEssenceFile->type != AAFI_ESSENCE_TYPE_PCM) { + if (!write_header) { + debug ("Writting exact copy of embedded file."); + } else { + debug ("Rewriting file header."); + } + } + + /* Build file path */ + const char* name = NULL; + + if (forcedFileName) { + name = forcedFileName; + } else { + name = audioEssenceFile->unique_name; + } + + const char* fileext = NULL; + + if (write_header || + audioEssenceFile->type == AAFI_ESSENCE_TYPE_WAVE || + audioEssenceFile->type == AAFI_ESSENCE_TYPE_PCM) { + if (!laaf_util_is_fileext (name, "wav") && + !laaf_util_is_fileext (name, "wave")) { + fileext = "wav"; + } + } else if (!write_header && + audioEssenceFile->type == AAFI_ESSENCE_TYPE_AIFC) { + if (!laaf_util_is_fileext (name, "aif") && + !laaf_util_is_fileext (name, "aiff") && + !laaf_util_is_fileext (name, "aifc")) { + fileext = "aif"; + } + } + + if (fileext) { + if (laaf_util_snprintf_realloc (&filename, NULL, 0, "%s.%s", name, fileext) < 0) { + error ("Could not concat filename + fileext"); + goto err; + } + } else { + filename = laaf_util_c99strdup (name); + + if (!filename) { + error ("Could not duplicate filename : %s", name); + goto err; + } + } + + filepath = laaf_util_build_path (DIR_SEP_STR, outpath, laaf_util_clean_filename (filename), NULL); + + if (!filepath) { + error ("Could not build filepath."); + goto err; + } + + fp = fopen (filepath, "wb"); + + if (!fp) { + error ("Could not open '%s' for writing : %s", filepath, strerror (errno)); + goto err; + } + + if (write_header || + audioEssenceFile->type == AAFI_ESSENCE_TYPE_PCM) { + struct wavFmtChunk wavFmt; + wavFmt.channels = audioEssenceFile->channels; + wavFmt.samples_per_sec = audioEssenceFile->samplerate; + wavFmt.bits_per_sample = audioEssenceFile->samplesize; + + struct wavBextChunk wavBext; + memset (&wavBext, 0x00, sizeof (wavBext)); + + memcpy (wavBext.umid, audioEssenceFile->sourceMobID, sizeof (aafMobID_t)); + + tmp = snprintf (wavBext.originator, sizeof (((struct wavBextChunk*)0)->originator), "%s %s", aafi->aafd->Identification.ProductName, (mediaComposer_AAF (aafi)) ? "" : aafi->aafd->Identification.ProductVersionString); + + assert (tmp > 0 && (size_t)tmp < sizeof (((struct wavBextChunk*)0)->originator)); + + // if ( tmp < 0 || (size_t)tmp >= sizeof(((struct wavBextChunk *)0)->originator) ) { + // fprintf( stderr, "snprintf() error" ); + // goto err; + // } + + tmp = snprintf (wavBext.originator_reference, sizeof (((struct wavBextChunk*)0)->originator_reference), "libAAF %s", LIBAAF_VERSION); + + assert (tmp > 0 && (size_t)tmp < sizeof (((struct wavBextChunk*)0)->originator_reference)); + + // if ( tmp < 0 || (size_t)tmp >= sizeof(((struct wavBextChunk *)0)->originator_reference) ) { + // fprintf( stderr, "snprintf() error" ); + // goto err; + // } + + tmp = snprintf (wavBext.description, sizeof (((struct wavBextChunk*)0)->description), "%s\n%s.aaf", audioEssenceFile->name, aafi->compositionName); + + assert (tmp > 0 && (size_t)tmp < sizeof (((struct wavBextChunk*)0)->description)); + + // if ( tmp < 0 || (size_t)tmp >= sizeof(((struct wavBextChunk *)0)->description) ) { + // fprintf( stderr, "snprintf() error" ); + // goto err; + // } + + memcpy (wavBext.origination_date, audioEssenceFile->originationDate, sizeof (((struct wavBextChunk*)0)->origination_date)); + memcpy (wavBext.origination_time, audioEssenceFile->originationTime, sizeof (((struct wavBextChunk*)0)->origination_time)); + + wavBext.time_reference = aafi_convertUnitUint64 (audioEssenceFile->sourceMobSlotOrigin, audioEssenceFile->sourceMobSlotEditRate, audioEssenceFile->samplerateRational); + + if (laaf_riff_writeWavFileHeader (fp, &wavFmt, (extractFormat != AAFI_EXTRACT_WAV) ? &wavBext : NULL, (uint32_t)datasz, aafi->log) < 0) { + error ("Could not write wav audio header : %s", filepath); + goto err; + } + } + + uint64_t writtenBytes = 0; + + if (write_header && audioEssenceFile->type == AAFI_ESSENCE_TYPE_AIFC && audioEssenceFile->samplesize > 8) { + unsigned char sample[4]; + uint16_t samplesize = (audioEssenceFile->samplesize >> 3); + + for (uint64_t i = 0; i < datasz; i += samplesize) { + if (samplesize == 2) { + sample[0] = *(unsigned char*)(data + pcmByteOffset + i + 1); + sample[1] = *(unsigned char*)(data + pcmByteOffset + i); + } else if (samplesize == 3) { + sample[0] = *(unsigned char*)(data + pcmByteOffset + i + 2); + sample[1] = *(unsigned char*)(data + pcmByteOffset + i + 1); + sample[2] = *(unsigned char*)(data + pcmByteOffset + i); + } else if (samplesize == 4) { + sample[0] = *(unsigned char*)(data + pcmByteOffset + i + 3); + sample[1] = *(unsigned char*)(data + pcmByteOffset + i + 2); + sample[2] = *(unsigned char*)(data + pcmByteOffset + i + 1); + sample[3] = *(unsigned char*)(data + pcmByteOffset + i); + } + + writtenBytes += fwrite (sample, samplesize, 1, fp); + } + + writtenBytes *= samplesize; + } else { + writtenBytes = fwrite (data + sourceFileOffset, sizeof (unsigned char), datasz, fp); + } + + if (writtenBytes < datasz) { + error ("Could not write audio file (%" PRIu64 " bytes written out of %" PRIu64 " bytes) : %s", writtenBytes, datasz, filepath); + goto err; + } + + if (!extracting_clip) { + /* + * Set audioEssenceFile->usable_file_path only if we axtract essence, not if we + * extract clip (subset of an essence), as a single essence can have multiple + * clips using it. Otherwise, we would reset audioEssenceFile->usable_file_path + * as many times as there are clips using the same essence. + */ + audioEssenceFile->usable_file_path = laaf_util_c99strdup (filepath); + + if (!audioEssenceFile->usable_file_path) { + error ("Could not duplicate usable filepath : %s", filepath); + goto err; + } + } + + if (usable_file_path) { + *usable_file_path = laaf_util_c99strdup (filepath); + + if (!(*usable_file_path)) { + error ("Could not duplicate usable filepath : %s", filepath); + goto err; + } + } + + rc = 0; + goto end; + +err: + rc = -1; + +end: + free (filename); + free (filepath); + free (data); + + if (fp) + fclose (fp); + + return rc; +} + +int +aafi_extractAudioClip (AAF_Iface* aafi, aafiAudioClip* audioClip, enum aafiExtractFormat extractFormat, const char* outpath) +{ + int rc = 0; + + for (aafiAudioEssencePointer* audioEssencePtr = audioClip->essencePointerList; audioEssencePtr; audioEssencePtr = audioEssencePtr->next) { + aafiAudioEssenceFile* audioEssenceFile = audioClip->essencePointerList->essenceFile; + + uint64_t sampleOffset = aafi_convertUnitUint64 (audioClip->essence_offset, audioClip->track->edit_rate, audioEssenceFile->samplerateRational); + uint64_t sampleLength = aafi_convertUnitUint64 (audioClip->len, audioClip->track->edit_rate, audioEssenceFile->samplerateRational); + + char* name = NULL; + char* usable_file_path = NULL; + + laaf_util_snprintf_realloc (&name, NULL, 0, "%i_%i_%s", audioClip->track->number, aafi_get_clipIndex (audioClip), audioClip->essencePointerList->essenceFile->unique_name); + + if ((rc += aafi_extractAudioEssenceFile (aafi, audioEssenceFile, extractFormat, outpath, sampleOffset, sampleLength, name, &usable_file_path)) == 0) { + success ("Audio clip file extracted to %s\"%s\"%s", + ANSI_COLOR_DARKGREY (aafi->log), + usable_file_path, + ANSI_COLOR_RESET (aafi->log)); + } else { + error ("Audio clip file extraction failed : %s\"%s\"%s", ANSI_COLOR_DARKGREY (aafi->log), name, ANSI_COLOR_RESET (aafi->log)); + } + + free (usable_file_path); + free (name); + + usable_file_path = NULL; + name = NULL; + } + + return rc; +} + +static int +set_audioEssenceWithRIFF (AAF_Iface* aafi, const char* filename, aafiAudioEssenceFile* audioEssenceFile, struct RIFFAudioFile* RIFFAudioFile, int isExternalFile) +{ + if (RIFFAudioFile->sampleCount >= INT64_MAX) { + error ("%s : summary sample count is bigger than INT64_MAX (%" PRIu64 ")", audioEssenceFile->usable_file_path, RIFFAudioFile->sampleCount); + return -1; + } + + if (RIFFAudioFile->sampleRate >= INT_MAX) { + error ("%s : summary sample rate is bigger than INT_MAX (%li)", audioEssenceFile->usable_file_path, RIFFAudioFile->sampleRate); + return -1; + } + + if (audioEssenceFile->channels > 0 && audioEssenceFile->channels != RIFFAudioFile->channels) { + warning ("%s : summary channel count (%i) mismatch %s (%i)", filename, audioEssenceFile->channels, ((isExternalFile) ? "located file" : "previously retrieved data"), RIFFAudioFile->channels); + } + // else { + // /* In Davinci Resolve embedded multichannel WAV, summary channel is always 1 */ + // audioEssenceFile->channels = RIFFAudioFile->channels; + // } + + if (audioEssenceFile->samplerate > 0 && audioEssenceFile->samplerate != RIFFAudioFile->sampleRate) { + warning ("%s : summary samplerate (%i) mismatch %s (%i)", filename, audioEssenceFile->samplerate, ((isExternalFile) ? "located file" : "previously retrieved data"), RIFFAudioFile->sampleRate); + } + + if (audioEssenceFile->samplesize > 0 && audioEssenceFile->samplesize != RIFFAudioFile->sampleSize) { + warning ("%s : summary samplesize (%i) mismatch %s (%i)", filename, audioEssenceFile->samplesize, ((isExternalFile) ? "located file" : "previously retrieved data"), RIFFAudioFile->sampleSize); + } + + if (audioEssenceFile->length > 0 && (uint64_t)audioEssenceFile->length != RIFFAudioFile->sampleCount) { + warning ("%s : summary samplecount (%" PRIi64 ") mismatch %s (%" PRIi64 ")", filename, audioEssenceFile->length, ((isExternalFile) ? "located file" : "previously retrieved data"), RIFFAudioFile->sampleCount); + } + + audioEssenceFile->channels = RIFFAudioFile->channels; + audioEssenceFile->samplerate = RIFFAudioFile->sampleRate; + audioEssenceFile->samplesize = RIFFAudioFile->sampleSize; + + audioEssenceFile->length = (aafPosition_t)RIFFAudioFile->sampleCount; + audioEssenceFile->pcm_audio_start_offset = (uint64_t)RIFFAudioFile->pcm_audio_start_offset; + audioEssenceFile->samplerateRational->numerator = (int32_t)audioEssenceFile->samplerate; + + audioEssenceFile->samplerateRational->denominator = 1; + + return 0; +} + +int +aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFile) +{ + int rc = 0; + uint64_t dataStreamSize = 0; + unsigned char* dataStream = NULL; + FILE* fp = NULL; + struct RIFFAudioFile RIFFAudioFile; + + /* try audioEssenceFile->summary first, for both embedded and external */ + + if (audioEssenceFile->summary) { + rc = laaf_riff_parseAudioFile (&RIFFAudioFile, RIFF_PARSE_AAF_SUMMARY, &embeddedAudioDataReaderCallback, audioEssenceFile->summary->val, &audioEssenceFile->summary->len, aafi, aafi->log); + + if (rc < 0) { + if (!audioEssenceFile->is_embedded && !audioEssenceFile->usable_file_path) { + warning ("Could not parse essence summary of \"%s\".", audioEssenceFile->name); + goto err; + } + + warning ("Could not parse essence summary of \"%s\". %s", + audioEssenceFile->name, + (audioEssenceFile->is_embedded) ? "Trying essence data stream." : (audioEssenceFile->usable_file_path) ? "Trying external essence file." + : " WTF ???"); + } else { + if (set_audioEssenceWithRIFF (aafi, "AAF Summary", audioEssenceFile, &RIFFAudioFile, 0) < 0) { + goto err; + } + + if (!RIFFAudioFile.channels || + !RIFFAudioFile.sampleRate || + !RIFFAudioFile.sampleSize || + !RIFFAudioFile.sampleCount) { + /* + * Adobe Premiere Pro AIFC/WAVE Summaries of external files are missing + * SSND chunk/DATA chunk size (RIFFAudioFile.sampleCount) + */ + + if (!audioEssenceFile->is_embedded && !audioEssenceFile->usable_file_path) { + warning ("Summary of \"%s\" is missing some data.", audioEssenceFile->name); + goto err; + } + + warning ("Summary of \"%s\" is missing some data. %s", + audioEssenceFile->name, + (audioEssenceFile->is_embedded) ? "Trying essence data stream." : (audioEssenceFile->usable_file_path) ? "Trying external essence file." + : " WTF ???"); + } else { + goto end; + } + } + } else if (audioEssenceFile->is_embedded) { + warning ("Embedded audio essence \"%s\" has no summary. Trying essence data stream.", audioEssenceFile->name); + } else if (audioEssenceFile->usable_file_path) { + warning ("External audio essence \"%s\" has no summary. Trying external file.", audioEssenceFile->name); + } + + if (audioEssenceFile->is_embedded) { + cfb_getStream (aafi->aafd->cfbd, audioEssenceFile->node, &dataStream, &dataStreamSize); + + if (dataStream == NULL) { + error ("Could not retrieve audio essence stream from CFB"); + goto err; + } + + rc = laaf_riff_parseAudioFile (&RIFFAudioFile, RIFF_PARSE_AAF_SUMMARY, &embeddedAudioDataReaderCallback, dataStream, &dataStreamSize, aafi, aafi->log); + + if (rc < 0) { + warning ("Could not parse embedded essence stream of \"%s\".", audioEssenceFile->name); + goto err; + } + + if (set_audioEssenceWithRIFF (aafi, "AAF Embedded stream", audioEssenceFile, &RIFFAudioFile, 0) < 0) { + goto err; + } + + goto end; + } + + if (laaf_util_is_fileext (audioEssenceFile->usable_file_path, "wav") || + laaf_util_is_fileext (audioEssenceFile->usable_file_path, "wave") || + laaf_util_is_fileext (audioEssenceFile->usable_file_path, "aif") || + laaf_util_is_fileext (audioEssenceFile->usable_file_path, "aiff") || + laaf_util_is_fileext (audioEssenceFile->usable_file_path, "aifc")) { + fp = fopen (audioEssenceFile->usable_file_path, "rb"); + + if (fp == NULL) { + error ("Could not open external audio essence file for reading : %s", audioEssenceFile->usable_file_path); + goto err; + } + + rc = laaf_riff_parseAudioFile (&RIFFAudioFile, 0, &externalAudioDataReaderCallback, fp, audioEssenceFile->usable_file_path, aafi, aafi->log); + + if (rc < 0) { + error ("Failed parsing external audio essence file : %s", audioEssenceFile->usable_file_path); + goto err; + } + + if (set_audioEssenceWithRIFF (aafi, audioEssenceFile->usable_file_path, audioEssenceFile, &RIFFAudioFile, 1) < 0) { + goto err; + } + } else { + /* + * should be considered as a non-pcm audio format + * +│ 04317│├──◻ AAFClassID_TimelineMobSlot [slot:6 track:4] (DataDef : AAFDataDef_Sound) : Audio 4 - Layered Audio Editing +│ 01943││ └──◻ AAFClassID_Sequence +│ 02894││ └──◻ AAFClassID_SourceClip +│ 02899││ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : speech-sample +│ 04405││ └──◻ AAFClassID_TimelineMobSlot [slot:1 track:1] (DataDef : AAFDataDef_Sound) +│ 03104││ └──◻ AAFClassID_SourceClip +│ 04140││ └──◻ AAFClassID_SourceMob (UsageCode: n/a) : speech-sample +│ 01287││ └──◻ AAFClassID_PCMDescriptor +│ 01477││ └──◻ AAFClassID_NetworkLocator : file:///C:/Users/user/Desktop/libAAF/test/res/speech-sample.mp3 + * + */ + + audioEssenceFile->type = AAFI_ESSENCE_TYPE_UNK; + } + + rc = 0; + goto end; + +err: + rc = -1; + +end: + free (dataStream); + + if (fp) + fclose (fp); + + return rc; +} + +static size_t +embeddedAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqlen, void* user1, void* user2, void* user3) +{ + unsigned char* data = user1; + size_t datasz = *(size_t*)user2; + AAF_Iface* aafi = (AAF_Iface*)user3; + + if (offset > datasz) { + error ("Requested data starts beyond data length"); + return RIFF_READER_ERROR; + } + + if (offset + reqlen > datasz) { + reqlen = datasz - (offset + reqlen); + } + + memcpy (buf, data + offset, reqlen); + + return reqlen; +} + +static size_t +externalAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqlen, void* user1, void* user2, void* user3) +{ + FILE* fp = (FILE*)user1; + const char* filename = (const char*)user2; + AAF_Iface* aafi = (AAF_Iface*)user3; + +#ifdef _WIN32 + assert (offset < _I64_MAX); + + if (_fseeki64 (fp, (__int64)offset, SEEK_SET) < 0) { + error ("Could not seek to %" PRIu64 " in file '%s' : %s", offset, filename, strerror (errno)); + return RIFF_READER_ERROR; + } +#else + assert (offset < LONG_MAX); + + if (fseek (fp, (long)offset, SEEK_SET) < 0) { + error ("Could not seek to %" PRIu64 " in file '%s' : %s", offset, filename, strerror (errno)); + return RIFF_READER_ERROR; + } +#endif + + size_t byteRead = fread (buf, sizeof (unsigned char), reqlen, fp); + + if (feof (fp)) { + if (byteRead < reqlen) { + error ("Incomplete fread() of '%s' due to EOF : %" PRIu64 " bytes read out of %" PRIu64 " requested", filename, byteRead, reqlen); + return RIFF_READER_ERROR; + } + debug ("fread() : EOF reached in file '%s'", filename); + } else if (ferror (fp)) { + if (byteRead < reqlen) { + error ("Incomplete fread() of '%s' due to error : %" PRIu64 " bytes read out of %" PRIu64 " requested", filename, byteRead, reqlen); + } else { + error ("fread() error of '%s' : %" PRIu64 " bytes read out of %" PRIu64 " requested", filename, byteRead, reqlen); + } + return RIFF_READER_ERROR; + } + + return byteRead; +} diff --git a/libs/aaf/AAFIParser.c b/libs/aaf/AAFIParser.c index 15fb0f964b..19434586d4 100644 --- a/libs/aaf/AAFIParser.c +++ b/libs/aaf/AAFIParser.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -34,102 +34,113 @@ * @{ */ +#include #include -#include #include +#include #include #include #include -#include - -#include - -#include "aaf/AAFDump.h" -#include "aaf/AAFIAudioFiles.h" -#include "aaf/AAFIParser.h" -#include "aaf/AAFIface.h" -#include "aaf/AAFToText.h" -#include "aaf/debug.h" - -#include "aaf/ProTools.h" -#include "aaf/Resolve.h" #include "aaf/AAFDefs/AAFClassDefUIDs.h" -#include "aaf/AAFDefs/AAFPropertyIDs.h" -// #include "aaf/AAFDefs/AAFCompressionDefs.h" #include "aaf/AAFDefs/AAFDataDefs.h" #include "aaf/AAFDefs/AAFExtEnum.h" #include "aaf/AAFDefs/AAFInterpolatorDefs.h" +#include "aaf/AAFDefs/AAFOPDefs.h" #include "aaf/AAFDefs/AAFOperationDefs.h" #include "aaf/AAFDefs/AAFParameterDefs.h" +#include "aaf/AAFDefs/AAFPropertyIDs.h" #include "aaf/AAFDefs/AAFTypeDefUIDs.h" -// #include "aaf/AAFDefs/AAFFileKinds.h" -#include "aaf/AAFDefs/AAFOPDefs.h" -// #include "aaf/AAFDefs/AAFContainerDefs.h" +#include "aaf/AAFDump.h" +#include "aaf/AAFIEssenceFile.h" +#include "aaf/AAFIParser.h" +#include "aaf/AAFIface.h" +#include "aaf/AAFToText.h" + +#include "aaf/MediaComposer.h" +#include "aaf/ProTools.h" +#include "aaf/Resolve.h" + +#include "aaf/log.h" #include "aaf/utils.h" #define debug(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) - -// #define trace( ... ) -// _dbg( aafi->dbg, aafi, LIB_AAF_IFACE_TRACE, 0, __VA_ARGS__ ) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) static aafRational_t AAFI_DEFAULT_TC_EDIT_RATE = { 25, 1 }; -#define RESET_CONTEXT(ctx) \ - /*ctx.MobSlot = NULL;*/ \ - ctx.current_track = NULL; \ - /*ctx.current_pos = 0;*/ \ - ctx.current_transition = NULL; \ - ctx.current_clip_gain = NULL; \ - ctx.current_clip_automation = NULL; \ - ctx.current_essence = NULL; \ - ctx.current_clip = NULL; \ - ctx.current_clip_is_muted = 0; \ - ctx.current_clip_is_combined = 0; \ - ctx.current_combined_clip_total_channel = 0; \ - ctx.current_combined_clip_channel_num = 0; \ +#define RESET_CTX__AudioGain(ctx) \ + ctx.current_clip_is_muted = 0; \ + ctx.current_clip_gain = NULL; \ + ctx.current_clip_gain_is_used = 0; \ + ctx.current_clip_variable_gain = NULL; \ + ctx.current_clip_variable_gain_is_used = 0; + +#define RESET_CTX__AudioChannelCombiner(ctx) \ + ctx.current_clip_is_combined = 0; \ + ctx.current_combined_clip_total_channel = 0; \ + ctx.current_combined_clip_channel_num = 0; \ ctx.current_combined_clip_forced_length = 0; -// ctx.current_track_is_multichannel = 0; -// ctx.current_multichannel_track_channel = 0; -// ctx.current_multichannel_track_clip_length = 0; -// static void aafi_trace_obj( AAF_Iface *aafi, aafObject *Obj, char *color ); - -static wchar_t* -build_unique_audiofilename (AAF_Iface* aafi, aafiAudioEssence* audioEssence); -static wchar_t* -build_unique_videofilename (AAF_Iface* aafi, aafiVideoEssence* videoEssence); - -/* TODO move to AAFCore.c */ -static aafObject* -get_Object_Ancestor (AAF_Iface* aafi, aafObject* Obj, const aafUID_t* ClassID); - -static aafUID_t* -get_Component_DataDefinition (AAF_Iface* aafi, aafObject* Component); -// static aafUID_t * get_FileDescriptor_ContainerFormat( AAF_Iface *aafi, aafObject *FileDescriptor ); -static aafUID_t* -get_OperationGroup_OperationIdentification (AAF_Iface* aafi, aafObject* OperationGroup); -static aafUID_t* -get_Parameter_InterpolationIdentification (AAF_Iface* aafi, aafObject* Parameter); - -static aafObject* -get_EssenceData_By_MobID (AAF_Iface* aafi, aafMobID_t* MobID); - -// static aafiAudioEssence * getAudioEssenceBySourceMobID( AAF_Iface *aafi, aafMobID_t *sourceMobID ); -// static aafiVideoEssence * getVideoEssenceBySourceMobID( AAF_Iface *aafi, aafMobID_t *sourceMobID ); +#define RESET_CONTEXT(ctx) \ + ctx.current_track = NULL; \ + ctx.current_audio_essence = NULL; \ + ctx.current_clip = NULL; \ + RESET_CTX__AudioGain (ctx); \ + RESET_CTX__AudioChannelCombiner (ctx); static int -parse_DigitalImageDescriptor (AAF_Iface* aafi, aafObject* DIDescriptor, td* __ptd); +parse_Mob (AAF_Iface* aafi, aafObject* Mob, td* __ptd); static int -parse_CDCIDescriptor (AAF_Iface* aafi, aafObject* CDCIDescriptor, td* __ptd); +parse_CompositionMob (AAF_Iface* aafi, aafObject* CompoMob, td* __ptd); +static int +parse_SourceMob (AAF_Iface* aafi, aafObject* SourceMob, td* __ptd); + +static int +parse_MobSlot (AAF_Iface* aafi, aafObject* MobSlot, td* __ptd); +static int +parse_TimelineMobSlot (AAF_Iface* aafi, aafObject* TimelineMobSlot, td* __ptd); +static int +parse_EventMobSlot (AAF_Iface* aafi, aafObject* EventMobSlot, td* __ptd); + +static int +parse_Component (AAF_Iface* aafi, aafObject* Component, td* __ptd); + +static int +parse_Transition (AAF_Iface* aafi, aafObject* Transition, td* __ptd); +static int +parse_Segment (AAF_Iface* aafi, aafObject* Segment, td* __ptd); + +static int +parse_Filler (AAF_Iface* aafi, aafObject* Filler, td* __ptd); +static int +parse_SourceClip (AAF_Iface* aafi, aafObject* SourceClip, td* __ptd); +static int +parse_Timecode (AAF_Iface* aafi, aafObject* Timecode, td* __ptd); +static int +parse_DescriptiveMarker (AAF_Iface* aafi, aafObject* DescriptiveMarker, td* __ptd); +static int +parse_Sequence (AAF_Iface* aafi, aafObject* Sequence, td* __ptd); +static int +parse_Selector (AAF_Iface* aafi, aafObject* Selector, td* __ptd); +static int +parse_NestedScope (AAF_Iface* aafi, aafObject* NestedScope, td* __ptd); +static int +parse_OperationGroup (AAF_Iface* aafi, aafObject* OpGroup, td* __ptd); + +static int +parse_Parameter (AAF_Iface* aafi, aafObject* Parameter, td* __ptd); +static int +parse_ConstantValue (AAF_Iface* aafi, aafObject* ConstantValue, td* __ptd); +static int +parse_VaryingValue (AAF_Iface* aafi, aafObject* VaryingValue, td* __ptd); static int parse_EssenceDescriptor (AAF_Iface* aafi, aafObject* EssenceDesc, td* __ptd); @@ -140,6 +151,11 @@ parse_WAVEDescriptor (AAF_Iface* aafi, aafObject* WAVEDescriptor, td* __ptd); static int parse_AIFCDescriptor (AAF_Iface* aafi, aafObject* AIFCDescriptor, td* __ptd); +static int +parse_DigitalImageDescriptor (AAF_Iface* aafi, aafObject* DIDescriptor, td* __ptd); +static int +parse_CDCIDescriptor (AAF_Iface* aafi, aafObject* CDCIDescriptor, td* __ptd); + static int parse_Locator (AAF_Iface* aafi, aafObject* Locator, td* __ptd); static int @@ -149,1295 +165,394 @@ static int parse_EssenceData (AAF_Iface* aafi, aafObject* EssenceData, td* __ptd); static int -parse_Component (AAF_Iface* aafi, aafObject* Component, td* __ptd); -static int -parse_Transition (AAF_Iface* aafi, aafObject* Transition, td* __ptd); -static int -parse_NestedScope (AAF_Iface* aafi, aafObject* NestedScope, td* __ptd); -static int -parse_Filler (AAF_Iface* aafi, aafObject* Filler, td* __ptd); -static int -parse_Sequence (AAF_Iface* aafi, aafObject* Sequence, td* __ptd); -static int -parse_Timecode (AAF_Iface* aafi, aafObject* Timecode, td* __ptd); -static int -parse_OperationGroup (AAF_Iface* aafi, aafObject* OpGroup, td* __ptd); -static int -parse_SourceClip (AAF_Iface* aafi, aafObject* SourceClip, td* __ptd); -static int -parse_Selector (AAF_Iface* aafi, aafObject* Selector, td* __ptd); - -static int -parse_Parameter (AAF_Iface* aafi, aafObject* Parameter, td* __ptd); -static int -parse_ConstantValue (AAF_Iface* aafi, aafObject* ConstantValue, td* __ptd); -static int -parse_VaryingValue (AAF_Iface* aafi, aafObject* VaryingValue, td* __ptd); +retrieve_UserComments (AAF_Iface* aafi, aafObject* UserComments, aafiMetaData** metadataList); static int retrieve_ControlPoints (AAF_Iface* aafi, aafObject* Points, aafRational_t* times[], aafRational_t* values[]); -static int -parse_Mob (AAF_Iface* aafi, aafObject* Mob); -static int -parse_CompositionMob (AAF_Iface* aafi, aafObject* CompoMob, td* __ptd); -static int -parse_SourceMob (AAF_Iface* aafi, aafObject* SourceMob, td* __ptd); - -static int -parse_MobSlot (AAF_Iface* aafi, aafObject* MobSlot, td* __ptd); - -static void -xplore_StrongObjectReferenceVector (AAF_Iface* aafi, aafObject* ObjCollection, td* __ptd); - -static void -xplore_StrongObjectReferenceVector (AAF_Iface* aafi, aafObject* ObjCollection, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 0); - - // aaf_dump_ObjectProperties( aafi->aafd, ComponentAttributeList ); - - struct dbg* dbg = aafi->dbg; - aafObject* Obj = NULL; - - aaf_foreach_ObjectInSet (&Obj, ObjCollection, NULL) - { - // aaf_dump_ObjectProperties( aafi->aafd, ObjCollection ); - /* TODO implement retrieve_TaggedValue() */ - - if (aaf_get_property (Obj, PID_TaggedValue_Name) && - aaf_get_property (Obj, PID_TaggedValue_Value)) { - wchar_t* name = aaf_get_propertyValue (Obj, PID_TaggedValue_Name, &AAFTypeID_String); - aafIndirect_t* indirect = aaf_get_propertyValue (Obj, PID_TaggedValue_Value, &AAFTypeID_Indirect); - - if (aafUIDCmp (&indirect->TypeDef, &AAFTypeID_Int32)) { - int32_t* indirectValue = aaf_get_indirectValue (aafi->aafd, indirect, &AAFTypeID_Int32); - DBG_BUFFER_WRITE (dbg, "Tagged | Name: %ls%*s Value (%ls) : %i\n", name, 56 - (int)wcslen (name), " ", aaft_TypeIDToText (&indirect->TypeDef), *indirectValue); - } else if (aafUIDCmp (&indirect->TypeDef, &AAFTypeID_String)) { - wchar_t* indirectValue = aaf_get_indirectValue (aafi->aafd, indirect, &AAFTypeID_String); - DBG_BUFFER_WRITE (dbg, "Tagged | Name: %ls%*s Value (%ls) : %ls\n", name, 56 - (int)wcslen (name), " ", aaft_TypeIDToText (&indirect->TypeDef), indirectValue); - free (indirectValue); - } else { - DBG_BUFFER_WRITE (dbg, "Tagged | Name: %ls%*s Value (%s%ls%s) : %sUNKNOWN_TYPE%s\n", name, 56 - (int)wcslen (name), " ", ANSI_COLOR_RED (dbg), aaft_TypeIDToText (&indirect->TypeDef), ANSI_COLOR_RESET (dbg), ANSI_COLOR_RED (dbg), ANSI_COLOR_RESET (dbg)); - } - - dbg->debug_callback (dbg, (void*)aafi, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); - - free (name); - } else { - dbg->debug_callback (dbg, (void*)aafi, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); - aaf_dump_ObjectProperties (aafi->aafd, Obj); - } - } -} - -void -aafi_dump_obj (AAF_Iface* aafi, aafObject* Obj, struct trace_dump* __td, int state, int line, const char* fmt, ...) -{ - if (aafi->ctx.options.trace == 0) - return; - - /* Print caller line number */ - struct dbg* dbg = aafi->dbg; - - if (Obj) { - switch (state) { - case TD_ERROR: - DBG_BUFFER_WRITE (dbg, "%serr %s%ls %s", ANSI_COLOR_RED (dbg), ANSI_COLOR_DARKGREY (dbg), L"\u2502", ANSI_COLOR_RED (dbg)); - break; - case TD_WARNING: - DBG_BUFFER_WRITE (dbg, "%swrn %s%ls %s", ANSI_COLOR_YELLOW (dbg), ANSI_COLOR_DARKGREY (dbg), L"\u2502", ANSI_COLOR_YELLOW (dbg)); - break; - case TD_NOT_SUPPORTED: - DBG_BUFFER_WRITE (dbg, "%suns %s%ls %s", ANSI_COLOR_ORANGE (dbg), ANSI_COLOR_DARKGREY (dbg), L"\u2502", ANSI_COLOR_ORANGE (dbg)); - break; - default: - DBG_BUFFER_WRITE (dbg, " %s%ls ", ANSI_COLOR_DARKGREY (dbg), L"\u2502"); - break; - } - DBG_BUFFER_WRITE (dbg, "%05i", line); - } else { - DBG_BUFFER_WRITE (dbg, " %s%ls%s ", ANSI_COLOR_DARKGREY (dbg), L"\u2502", ANSI_COLOR_RESET (dbg)); - } - - DBG_BUFFER_WRITE (dbg, "%s%ls%s", ANSI_COLOR_DARKGREY (dbg), L"\u2502", ANSI_COLOR_RESET (dbg)); // │ - - /* Print padding and vertical lines */ - - if (__td->lv > 0) { - for (int i = 0; i < __td->lv; i++) { - /* current level iteration has more than one entry remaining in loop */ - - if (__td->ll[i] > 1) { - /* next level iteration is current trace */ - - if (i + 1 == __td->lv) { - if (Obj) { - DBG_BUFFER_WRITE (dbg, "%ls", L"\u251c\u2500\u2500\u25fb "); // ├──◻ - } else { - DBG_BUFFER_WRITE (dbg, "%ls", L"\u2502 "); // │ - } - } else { - DBG_BUFFER_WRITE (dbg, "%ls", L"\u2502 "); // │ - } - } else if (i + 1 == __td->lv && Obj) { - DBG_BUFFER_WRITE (dbg, "%ls", L"\u2514\u2500\u2500\u25fb "); // └──◻ - } else { - DBG_BUFFER_WRITE (dbg, " "); - } - } - } - - if (Obj) { - switch (state) { - case TD_ERROR: - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_RED (dbg)); - break; - case TD_WARNING: - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_YELLOW (dbg)); - break; - case TD_NOT_SUPPORTED: - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_ORANGE (dbg)); - break; - case TD_INFO: - case TD_OK: - if (__td->sub) { - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_DARKGREY (dbg)); - } else { - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_CYAN (dbg)); - } - - break; - } - - DBG_BUFFER_WRITE (dbg, "%ls ", aaft_ClassIDToText (aafi->aafd, Obj->Class->ID)); - - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_RESET (dbg)); - - if (aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot)) { - aafObject* Segment = aaf_get_propertyValue (Obj, PID_MobSlot_Segment, &AAFTypeID_SegmentStrongReference); - aafUID_t* DataDefinition = get_Component_DataDefinition (aafi, Segment); - wchar_t* name = aaf_get_propertyValue (Obj, PID_MobSlot_SlotName, &AAFTypeID_String); - uint32_t* slotID = aaf_get_propertyValue (Obj, PID_MobSlot_SlotID, &AAFTypeID_UInt32); - uint32_t* trackNo = aaf_get_propertyValue (Obj, PID_MobSlot_PhysicalTrackNumber, &AAFTypeID_UInt32); - - DBG_BUFFER_WRITE (dbg, "[slot:%s%i%s track:%s%i%s] (DataDef : %s%ls%s) %s%ls ", - ANSI_COLOR_BOLD (dbg), - (slotID) ? (int)(*slotID) : -1, - ANSI_COLOR_RESET (dbg), - ANSI_COLOR_BOLD (dbg), - (trackNo) ? (int)(*trackNo) : -1, - ANSI_COLOR_RESET (dbg), - ANSI_COLOR_DARKGREY (dbg), - aaft_DataDefToText (aafi->aafd, DataDefinition), - ANSI_COLOR_RESET (dbg), - (name && name[0] != 0x00) ? ": " : "", (name) ? name : L""); - - free (name); - } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_CompositionMob) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_MasterMob) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_SourceMob)) { - aafUID_t* usageCode = aaf_get_propertyValue (Obj, PID_Mob_UsageCode, &AAFTypeID_UsageType); - wchar_t* name = aaf_get_propertyValue (Obj, PID_Mob_Name, &AAFTypeID_String); - - DBG_BUFFER_WRITE (dbg, "(UsageCode: %s%ls%s) %s%ls", - ANSI_COLOR_DARKGREY (dbg), - aaft_UsageCodeToText (usageCode), - ANSI_COLOR_RESET (dbg), - (name && name[0] != 0x00) ? ": " : "", (name) ? name : L""); - - free (name); - } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_OperationGroup)) { - aafUID_t* OperationIdentification = get_OperationGroup_OperationIdentification (aafi, Obj); - - int64_t* length = aaf_get_propertyValue (Obj, PID_Component_Length, &AAFTypeID_LengthType); - - DBG_BUFFER_WRITE (dbg, "(OpIdent: %s%ls%s; Length: %s%li%s) ", - ANSI_COLOR_DARKGREY (dbg), - aaft_OperationDefToText (aafi->aafd, OperationIdentification), - ANSI_COLOR_RESET (dbg), - ANSI_COLOR_DARKGREY (dbg), - (length) ? *length : -1, - ANSI_COLOR_RESET (dbg)); - } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_Sequence) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_Filler) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_SourceClip) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_Selector) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_Transition)) { - int64_t* length = aaf_get_propertyValue (Obj, PID_Component_Length, &AAFTypeID_LengthType); - - DBG_BUFFER_WRITE (dbg, "(Length: %s%li%s) ", - ANSI_COLOR_DARKGREY (dbg), - (length) ? *length : -1, - ANSI_COLOR_RESET (dbg)); - } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_ConstantValue)) { - aafIndirect_t* Indirect = aaf_get_propertyValue (Obj, PID_ConstantValue_Value, &AAFTypeID_Indirect); - - if (Indirect) { - aafRational_t* multiplier = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Rational); - - if (multiplier) { - DBG_BUFFER_WRITE (dbg, "(Value: %s%i/%i%s %+05.1lf dB) ", - ANSI_COLOR_DARKGREY (dbg), - multiplier->numerator, - multiplier->denominator, - 20 * log10 (aafRationalToFloat (*multiplier)), - ANSI_COLOR_RESET (dbg)); - } - } - } - // else if ( aafUIDCmp( Obj->Class->ID, &AAFClassID_TapeDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_FilmDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_CDCIDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_RGBADescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_TIFFDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_SoundDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_PCMDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_AES3PCMDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_WAVEDescriptor ) || - // aafUIDCmp( Obj->Class->ID, &AAFClassID_AIFCDescriptor ) ) - // { - // aafUID_t *ContainerFormat = get_FileDescriptor_ContainerFormat( aafi, Obj ); - // DBG_BUFFER_WRITE( dbg, "(ContainerIdent : \x1b[38;5;242m%ls\x1b[0m)", aaft_ContainerToText(ContainerFormat) ); - // } - - if (state == TD_ERROR) { - DBG_BUFFER_WRITE (dbg, ": %s", ANSI_COLOR_RED (dbg)); - } else if (state == TD_INFO) { - DBG_BUFFER_WRITE (dbg, ": %s", ANSI_COLOR_CYAN (dbg)); - } - - va_list args; - va_start (args, fmt); - - dbg->_dbg_msg_pos += laaf_util_vsnprintf_realloc (&dbg->_dbg_msg, &dbg->_dbg_msg_size, dbg->_dbg_msg_pos, fmt, &args); - - va_end (args); - // va_list args; - // va_list args2; - // va_copy( args2, args ); - // - // va_start( args2, fmt ); - // // vprintf(fmt, args); - // // offset += laaf_util_vsnprintf_realloc( &dbg->_dbg_msg, &dbg->_dbg_msg_size, offset, fmt, args ); - // int needed = vsnprintf( NULL, 0, fmt, args2 ) + 1; - // if ( needed >= dbg->_dbg_msg_size + offset ) { - // char *p = realloc( dbg->_dbg_msg, offset+needed ); - // if (p) { - // dbg->_dbg_msg = p; - // } else { - // /* TODO: realloc() faillure */ - // // free(*str); - // // *str = NULL; - // // *size = 0; - // // return -1; - // } - // } - // va_end( args2 ); - // - // va_start( args, fmt ); - // // vprintf( fmt, args ); - // offset += vsnprintf( dbg->_dbg_msg+offset, dbg->_dbg_msg_size-offset, fmt, args ); - // va_end( args ); - - if (state == TD_ERROR || state == TD_INFO) { - DBG_BUFFER_WRITE (dbg, "."); - } - - if (!aafi->ctx.options.dump_class_aaf_properties) { - aafProperty* Prop = NULL; - int hasUnknownProps = 0; - - for (Prop = Obj->Properties; Prop != NULL; Prop = Prop->next) { - if (Prop->def->meta) { - // DBG_BUFFER_WRITE( dbg, "\n"); - - if (aafi->ctx.options.trace_meta) { - // aaf_dump_ObjectProperties( aafi->aafd, Obj ); - - // if ( Prop->pid == 0xffca ) { - if (Prop->sf == SF_STRONG_OBJECT_REFERENCE_VECTOR) { - DBG_BUFFER_WRITE (dbg, "\n"); - DBG_BUFFER_WRITE (dbg, " >>> (0x%04x) %ls (%ls)\n", Prop->pid, aaft_PIDToText (aafi->aafd, Prop->pid), aaft_StoredFormToText (Prop->sf) /*AUIDToText( &Prop->def->type ),*/ /*aaft_TypeIDToText( &(Prop->def->type) )*/); - void* propValue = aaf_get_propertyValue (Obj, Prop->pid, &AAFUID_NULL); - xplore_StrongObjectReferenceVector (aafi, propValue, __td); - - // DUMP_OBJ_NO_SUPPORT( aafi, propValue, __td ); - } else { - DBG_BUFFER_WRITE (dbg, "\n"); - aaf_dump_ObjectProperty (aafi->aafd, Prop); - } - } else { - DBG_BUFFER_WRITE (dbg, "%s%s %ls[0x%04x]", ANSI_COLOR_RESET (dbg), (!hasUnknownProps) ? " (MetaProps:" : "", aaft_PIDToText (aafi->aafd, Prop->pid), Prop->pid); - // laaf_util_dump_hex( Prop->val, Prop->len ); - hasUnknownProps++; - } - } - } - if (aafi->ctx.options.trace_meta == 0 && hasUnknownProps) { - DBG_BUFFER_WRITE (dbg, ")"); - } - } - - if (aafi->ctx.options.dump_class_raw_properties && wcscmp (aaft_ClassIDToText (aafi->aafd, Obj->Class->ID), aafi->ctx.options.dump_class_raw_properties) == 0) { - DBG_BUFFER_WRITE (dbg, "\n\n"); - DBG_BUFFER_WRITE (dbg, "======================================================================\n"); - DBG_BUFFER_WRITE (dbg, " CFB Object Properties Dump\n"); - DBG_BUFFER_WRITE (dbg, "======================================================================\n"); - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_DARKGREY (dbg)); - DBG_BUFFER_WRITE (dbg, "%ls\n", aaft_ClassIDToText (aafi->aafd, Obj->Class->ID)); - DBG_BUFFER_WRITE (dbg, "%ls/properties\n", aaf_get_ObjectPath (Obj)); - DBG_BUFFER_WRITE (dbg, "%s\n\n", ANSI_COLOR_RESET (dbg)); - - // cfb_dump_node( aafi->aafd->cfbd, cfb_getChildNode( aafi->aafd->cfbd, L"properties", Obj->Node ), 1 ); - aaf_dump_nodeStreamProperties (aafi->aafd, cfb_getChildNode (aafi->aafd->cfbd, L"properties", Obj->Node)); - - DBG_BUFFER_WRITE (dbg, "\n"); - } - - if (aafi->ctx.options.dump_class_aaf_properties && wcscmp (aaft_ClassIDToText (aafi->aafd, Obj->Class->ID), aafi->ctx.options.dump_class_aaf_properties) == 0) { - DBG_BUFFER_WRITE (dbg, "\n\n"); - DBG_BUFFER_WRITE (dbg, "======================================================================\n"); - DBG_BUFFER_WRITE (dbg, " AAF Properties Dump\n"); - DBG_BUFFER_WRITE (dbg, "======================================================================\n"); - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_DARKGREY (dbg)); - DBG_BUFFER_WRITE (dbg, "%ls\n", aaft_ClassIDToText (aafi->aafd, Obj->Class->ID)); - DBG_BUFFER_WRITE (dbg, "%ls/properties\n", aaf_get_ObjectPath (Obj)); - DBG_BUFFER_WRITE (dbg, "%s\n\n", ANSI_COLOR_RESET (dbg)); - - aaf_dump_ObjectProperties (aafi->aafd, Obj); - - DBG_BUFFER_WRITE (dbg, "\n"); - } - - DBG_BUFFER_WRITE (dbg, "%s", ANSI_COLOR_RESET (dbg)); - } - - // DBG_BUFFER_WRITE( dbg, "\n" ); - - dbg->debug_callback (dbg, (void*)aafi, DEBUG_SRC_ID_TRACE, 0, "", "", 0, dbg->_dbg_msg, dbg->user); - - /* if end of branch, print one line padding */ - if (Obj && (__td->eob || state == TD_ERROR)) - aafi_dump_obj (aafi, NULL, __td, 0, -1, ""); -} - -void -aafi_dump_obj_no_support (AAF_Iface* aafi, aafObject* Obj, struct trace_dump* __td, int line) -{ - // aafUID_t *DataDefinition = NULL; - - if (aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot) && - aafUIDCmp (Obj->Parent->Class->ID, &AAFClassID_CompositionMob)) { - /* this part is handled by aafi_dump_obj() already. */ - aafi_dump_obj (aafi, Obj, __td, TD_NOT_SUPPORTED, line, ""); - return; - // aafObject *Segment = aaf_get_propertyValue( Obj, PID_MobSlot_Segment, &AAFTypeID_SegmentStrongReference ); - // - // if ( Segment != NULL ) /* req */ { - // DataDefinition = get_Component_DataDefinition( aafi, Segment ); - // } - // } - // else { - // DataDefinition = get_Component_DataDefinition( aafi, Obj ); - } - - // DataDefinition = get_Component_DataDefinition( aafi, Obj ); - - aafi_dump_obj (aafi, Obj, __td, TD_NOT_SUPPORTED, line, ""); - - // aafi_dump_obj( aafi, Obj, __td, WARNING, line, "%s%ls%s", - // // aaft_ClassIDToText( aafi->aafd, Obj->Class->ID ), - // ((DataDefinition) ? "(Segment DataDefinition: \x1b[38;5;242m" : ""), - // ((DataDefinition) ? aaft_DataDefToText( aafi->aafd, DataDefinition ) : L""), - // ((DataDefinition) ? ") \x1b[0m" : "") ); -} - -/* -#define DUMP_OBJ( aafi, Obj, __td ) \ - aafi_dump_obj( aafi, Obj, __td, OK, __LINE__, "" ); - -#define DUMP_OBJ_ERROR( aafi, Obj, __td, ... ) \ - (__td)->eob = 1; \ - aafi_dump_obj( aafi, Obj, __td, ERROR, __LINE__, __VA_ARGS__ ); - -#define DUMP_OBJ_WARNING( aafi, Obj, __td, ... ) \ - aafi_dump_obj( aafi, Obj, __td, WARNING, __LINE__, __VA_ARGS__ ); - -#define DUMP_OBJ_INFO( aafi, Obj, __td, ... ) \ - aafi_dump_obj( aafi, Obj, __td, OK, __LINE__, __VA_ARGS__ ); - -#define DUMP_OBJ_NO_SUPPORT( aafi, Obj, __td ) \ - (__td)->eob = 1; \ - aafi_dump_obj_no_support( aafi, Obj, __td, __LINE__ ); \ - // aaf_dump_ObjectProperties( aafi->aafd, Obj ); -*/ - -static wchar_t* -build_unique_audiofilename (AAF_Iface* aafi, aafiAudioEssence* audioEssence) -{ - wchar_t* unique = NULL; - size_t unique_size = 0; - size_t file_name_len = 0; - - if (audioEssence->file_name) { - file_name_len = wcslen (audioEssence->file_name); - unique_size = file_name_len + 1 + 4; // +4 = "_001" - unique_size = (unique_size < AAFUID_PRINTED_LEN + 1) ? AAFUID_PRINTED_LEN + 1 : unique_size; - - // debug("%lu, %lu", file_name_len, unique_size); - - unique = malloc (sizeof (wchar_t) * unique_size); - - if (unique == NULL) { - error ("Could not allocate memory : %s", strerror (errno)); - return NULL; - } - - if (swprintf (unique, unique_size, L"%" WPRIws, audioEssence->file_name) < 0) { - error ("Could not prepare unique filename"); - return NULL; - } - } else { - file_name_len = strlen ("unknown"); - unique_size = file_name_len + 1 + 4; // +4 = "_001" - unique_size = (unique_size < AAFUID_PRINTED_LEN + 1) ? AAFUID_PRINTED_LEN + 1 : unique_size; - - unique = malloc (sizeof (wchar_t) * unique_size); - - if (unique == NULL) { - error ("Could not allocate memory : %s", strerror (errno)); - return NULL; - } - - if (swprintf (unique, unique_size, L"unknown") < 0) { - error ("Could not prepare unique filename"); - return NULL; - } - } - - // debug( "%ls", unique ); - - aafiAudioEssence* ae = NULL; - - if (aafi->ctx.options.forbid_nonlatin_filenames && laaf_util_wstr_contains_nonlatin (unique)) { - aafUID_t* uuid = &(audioEssence->sourceMobID->material); - - int rc = swprintf (unique, unique_size, L"%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", - uuid->Data1, - uuid->Data2, - uuid->Data3, - uuid->Data4[0], - uuid->Data4[1], - uuid->Data4[2], - uuid->Data4[3], - uuid->Data4[4], - uuid->Data4[5], - uuid->Data4[6], - uuid->Data4[7]); - - if (rc < 0) { - error ("Failed to set unique filename with SourceMobID UID"); - free (unique); - return NULL; - } - - audioEssence->unique_file_name = unique; - - return unique; - } - - int index = 0; - - foreachEssence (ae, aafi->Audio->Essences) - { - if (ae->unique_file_name != NULL && wcscmp (ae->unique_file_name, unique) == 0) { - if (swprintf (unique + file_name_len, (unique_size - file_name_len), L"_%i", ++index) < 0) { - error ("Failed to increment unique filename"); - free (unique); - return NULL; - } - - ae = aafi->Audio->Essences; // check again - // debug( "%ls", unique ); - } - } - - audioEssence->unique_file_name = unique; - - // debug( "%ls", audioEssence->wunique_file_name ); - - return unique; -} - -static wchar_t* -build_unique_videofilename (AAF_Iface* aafi, aafiVideoEssence* videoEssence) -{ - /* TODO 1024 should be a macro ! */ - - wchar_t* unique = calloc (sizeof (wchar_t), 1024); - - size_t file_name_len = wcslen (videoEssence->file_name); - - // debug( "%i", file_name_len ); - - memcpy (unique, videoEssence->file_name, (file_name_len + 1) * sizeof (wchar_t)); - - // debug( "%ls", unique ); - - aafiVideoEssence* ve = NULL; - - if (1) { - size_t i = 0; - - for (; i < file_name_len; i++) { - /* if char is out of the Basic Latin range */ - - if (unique[i] > 0xff) { - // debug( "MobID : %ls", aaft_MobIDToText( videoEssence->sourceMobID ) ); - aafUID_t* uuid = &(videoEssence->sourceMobID->material); - swprintf (unique, 1024, L"%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", - uuid->Data1, - uuid->Data2, - uuid->Data3, - uuid->Data4[0], - uuid->Data4[1], - uuid->Data4[2], - uuid->Data4[3], - uuid->Data4[4], - uuid->Data4[5], - uuid->Data4[6], - uuid->Data4[7]); - - videoEssence->unique_file_name = unique; - - return unique; - } - } - } - - int id = 0; - - foreachEssence (ve, aafi->Video->Essences) - { - if (ve->unique_file_name != NULL && wcscmp (ve->unique_file_name, unique) == 0) { - swprintf (unique + file_name_len, (1024 - file_name_len), L"_%i", ++id); - // debug( "%ls", unique ); - ve = aafi->Video->Essences; // check again - } - } - - videoEssence->unique_file_name = unique; - - // debug( "%ls", videoEssence->wunique_file_name ); - - return unique; -} - -static aafObject* -get_Object_Ancestor (AAF_Iface* aafi, aafObject* Obj, const aafUID_t* ClassID) -{ - (void)aafi; - - /* - * NOTE : AAFClassID_ContentStorage is the container of Mob and EssenceData, - * not of Identification, Dictionary and MetaDictionary. If needed, the func - * should work for them too thanks to Obj != NULL. - */ - - while (Obj != NULL && !aafUIDCmp (Obj->Class->ID, &AAFClassID_ContentStorage)) { - if (aafUIDCmp (ClassID, Obj->Class->ID)) { - return Obj; - } - - /* Works also with abstract class */ - - if (aafUIDCmp (ClassID, &AAFClassID_Mob) && (aafUIDCmp (Obj->Class->ID, &AAFClassID_MasterMob) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_SourceMob) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_CompositionMob))) { - return Obj; - } - - if (aafUIDCmp (ClassID, &AAFClassID_MobSlot) && (aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_StaticMobSlot) || - aafUIDCmp (Obj->Class->ID, &AAFClassID_EventMobSlot))) { - return Obj; - } - - Obj = Obj->Parent; - } - - return NULL; -} - /* **************************************************************************** - * D i c t i o n a r y - * ****************************************************************************/ - -static aafUID_t* -get_Component_DataDefinition (AAF_Iface* aafi, aafObject* Component) -{ - aafWeakRef_t* weakRef = aaf_get_propertyValue (Component, PID_Component_DataDefinition, &AAFTypeID_DataDefinitionWeakReference); - - if (weakRef == NULL) { - warning ("Missing Component::DataDefinition."); - return NULL; - } - - aafObject* DataDefinition = aaf_get_ObjectByWeakRef (aafi->aafd->DataDefinition, weakRef); - - if (DataDefinition == NULL) { - warning ("Could not retrieve WeakRef from Dictionary::DataDefinition."); - return NULL; - } - - aafUID_t* DataIdentification = aaf_get_propertyValue (DataDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); - - if (DataIdentification == NULL) { - warning ("Missing DataDefinition's DefinitionObject::Identification."); - return NULL; - } - - return DataIdentification; -} - -// static aafUID_t * get_FileDescriptor_ContainerFormat( AAF_Iface *aafi, aafObject *FileDescriptor ) -// { -// aafWeakRef_t *ContainerDefWeakRef = aaf_get_propertyValue( FileDescriptor, PID_FileDescriptor_ContainerFormat, &AAFTypeID_ClassDefinitionWeakReference ); -// -// if ( ContainerDefWeakRef == NULL ) { -// warning( "Missing FileDescriptor::ContainerFormat." ); -// return NULL; -// } -// -// aafObject *ContainerDefinition = aaf_get_ObjectByWeakRef( aafi->aafd->ContainerDefinition, ContainerDefWeakRef ); -// -// if ( ContainerDefinition == NULL ) { -// warning( "Could not retrieve WeakRef from Dictionary::ContainerDefinitions." ); -// return NULL; -// } -// -// -// aafUID_t *ContainerIdentification = aaf_get_propertyValue( ContainerDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID ); -// -// if ( ContainerIdentification == NULL ) { -// warning( "Missing ContainerDefinition's DefinitionObject::Identification." ); -// return NULL; -// } -// -// -// return ContainerIdentification; -// } - -static aafUID_t* -get_OperationGroup_OperationIdentification (AAF_Iface* aafi, aafObject* OperationGroup) -{ - aafWeakRef_t* OperationDefWeakRef = aaf_get_propertyValue (OperationGroup, PID_OperationGroup_Operation, &AAFTypeID_OperationDefinitionWeakReference); - - if (OperationDefWeakRef == NULL) { - error ("Missing OperationGroup::Operation."); - return NULL; - } - - aafObject* OperationDefinition = aaf_get_ObjectByWeakRef (aafi->aafd->OperationDefinition, OperationDefWeakRef); - - if (OperationDefinition == NULL) { - error ("Could not retrieve OperationDefinition from dictionary."); - return NULL; - } - - aafUID_t* OperationIdentification = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); - - if (OperationIdentification == NULL) { - error ("Missing DefinitionObject::Identification."); - return NULL; - } - - return OperationIdentification; -} - -/* TODO not parameter ? VaryingValue ? */ -static aafUID_t* -get_Parameter_InterpolationIdentification (AAF_Iface* aafi, aafObject* Parameter) -{ - aafWeakRef_t* InterpolationDefWeakRef = aaf_get_propertyValue (Parameter, PID_VaryingValue_Interpolation, &AAFTypeID_InterpolationDefinitionWeakReference); - - if (InterpolationDefWeakRef == NULL) { - error ("Missing Parameter::Interpolation."); - return NULL; - } - - aafObject* InterpolationDefinition = aaf_get_ObjectByWeakRef (aafi->aafd->InterpolationDefinition, InterpolationDefWeakRef); - - if (InterpolationDefinition == NULL) { - error ("Could not find InterpolationDefinition."); - return NULL; - } - - aafUID_t* InterpolationIdentification = aaf_get_propertyValue (InterpolationDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); - - if (InterpolationIdentification == NULL) { - error ("Missing Parameter DefinitionObject::Identification."); - return NULL; - } - - return InterpolationIdentification; -} - -static aafObject* -get_EssenceData_By_MobID (AAF_Iface* aafi, aafMobID_t* MobID) -{ - aafMobID_t* DataMobID = NULL; - aafObject* EssenceData = NULL; - - for (EssenceData = aafi->aafd->EssenceData; EssenceData != NULL; EssenceData = EssenceData->next) { - DataMobID = aaf_get_propertyValue (EssenceData, PID_EssenceData_MobID, &AAFTypeID_MobIDType); - - if (aafMobIDCmp (DataMobID, MobID)) - break; - } - - return EssenceData; -} - -// /* TODO is this SourceMobID or SourceID (masterMobID) ??? */ -// static aafiAudioEssence * getAudioEssenceBySourceMobID( AAF_Iface *aafi, aafMobID_t *sourceMobID ) -// { -// aafiAudioEssence * audioEssence = NULL; -// -// -// for ( audioEssence = aafi->Audio->Essences; audioEssence != NULL; audioEssence = audioEssence->next ) { -// if ( aafMobIDCmp( audioEssence->masterMobID, sourceMobID ) ) -// break; -// } -// -// -// return audioEssence; -// } - -// /* TODO is this SourceMobID or SourceID (masterMobID) ??? */ -// static aafiVideoEssence * getVideoEssenceBySourceMobID( AAF_Iface *aafi, aafMobID_t *sourceMobID ) -// { -// aafiVideoEssence * videoEssence = NULL; -// -// // debug( "%p", aafi->Video->tc ); -// debug( "%p", aafi->Video->Essences ); -// debug( "%ls", aaft_MobIDToText( sourceMobID ) ); -// -// -// for ( videoEssence = aafi->Video->Essences; videoEssence != NULL; videoEssence = videoEssence->next ) { -// if ( aafMobIDCmp( videoEssence->masterMobID, sourceMobID ) ) -// break; -// } -// -// -// return videoEssence; -// } - -/* **************************************************************************** - * E s s e n c e D e s c r i p t o r + * M o b * **************************************************************************** - * - * EssenceDescriptor (abs) - * | - * |--> FileDescriptor (abs) - * | | - * | |--> WAVEDescriptor - * | |--> AIFCDescriptor - * | |--> SoundDescriptor - * | | | - * | | `--> PCMDescriptor - * | | - * | `--> DigitalImageDescriptor (abs) - * | | - * | `--> CDCIDescriptor - * | - * | - * |--> PhysicalDescriptor - * `--> TapeDescriptor + + * Mob (abs) + * | + * |--> CompositionMob + * |--> MasterMob + * `--> SourceMob */ static int -parse_EssenceDescriptor (AAF_Iface* aafi, aafObject* EssenceDesc, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 0); - - if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_PCMDescriptor)) { - parse_PCMDescriptor (aafi, EssenceDesc, &__td); - } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_WAVEDescriptor)) { - parse_WAVEDescriptor (aafi, EssenceDesc, &__td); - } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_AIFCDescriptor)) { - parse_AIFCDescriptor (aafi, EssenceDesc, &__td); - } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_SoundDescriptor)) { - /* Compressed Audio (MP3, AAC ?). Not encountered yet */ - - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); - __td.lv--; - } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_AES3PCMDescriptor)) { - /* Not described in specs, not encountered yet. */ - - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); - __td.lv--; - } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_MultipleDescriptor)) { - /* - * A MultipleDescriptor contains a vector of FileDescriptor objects and is - * used when the file source consists of multiple tracks of essence (e.g MXF). - * Each essence track is described by a MobSlots object in the SourceMob and a - * FileDescriptor object. The FileDescriptor is linked to the MobSlot by - * setting the FileDescriptor::LinkedSlotID property equal to the - * MobSlot::SlotID property. - * - * -> test.aaf - */ - - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); - __td.lv--; - - } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_CDCIDescriptor)) { - parse_CDCIDescriptor (aafi, EssenceDesc, &__td); - } else { - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); - __td.lv--; - } - - /* - * Locators are a property of EssenceDescriptor. The property holds a vector of - * Locators object, that should provide information to help find a file that - * contains the essence (WAV, MXF, etc.) or to help find the physical media. - * - * A Locator can either be a NetworkLocator or a TextLocator. - * - * A NetworkLocator holds a URLString property : - * - * p.41 : Absolute Uniform Resource Locator (URL) complying with RFC 1738 or relative - * Uniform Resource Identifier (URI) complying with RFC 2396 for file containing - * the essence. If it is a relative URI, the base URI is determined from the URI - * of the AAF file itself. - * Informative note: A valid URL or URI uses a constrained character set and uses - * the / character as the path separator. - */ - - aafObject* Locator = NULL; - aafObject* Locators = aaf_get_propertyValue (EssenceDesc, PID_EssenceDescriptor_Locator, &AAFTypeID_LocatorStrongReferenceVector); /* opt */ - - __td.lv++; - int i = 0; - - aaf_foreach_ObjectInSet (&Locator, Locators, NULL) - { - /* TODO retrieve all locators, then when searching file, try all parsed locators. */ - __td.ll[__td.lv] = (Locators->Header->_entryCount > 1) ? (Locators->Header->_entryCount - i++) : 0; - parse_Locator (aafi, Locator, &__td); - } - - return 0; -} - -static int -parse_DigitalImageDescriptor (AAF_Iface* aafi, aafObject* DIDescriptor, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 0); - - /* TODO parse and save content to videoEssence */ - - aafiVideoEssence* videoEssence = aafi->ctx.current_video_essence; //(aafiVideoEssence*)aafi->ctx.current_essence; - - if (videoEssence == NULL) { - DUMP_OBJ_ERROR (aafi, DIDescriptor, &__td, "aafi->ctx.current_video_essence not set"); - return -1; - } - - /* - * « Informative note: In the case of picture essence, the Sample Rate is usually the frame rate. The value should be - * numerically exact, for example {25,1} or {30000, 1001}. » - * - * « Informative note: Care should be taken if a sample rate of {2997,100} is encountered, since this may have been intended - * as a (mistaken) approximation to the exact value. » - */ - - aafRational_t* framerate = aaf_get_propertyValue (DIDescriptor, PID_FileDescriptor_SampleRate, &AAFTypeID_Rational); - - if (framerate == NULL) { /* REQ */ - DUMP_OBJ_ERROR (aafi, DIDescriptor, &__td, "Missing PID_FileDescriptor_SampleRate (framerate)"); - return -1; - } - - videoEssence->framerate = framerate; - - debug ("Video framerate : %i/%i", framerate->numerator, framerate->denominator); - - /* - * All mandatory properties below are treated as optional, because we assume that - * video will be an external file so we are not using those, and because some AAF - * implementations does not even set those mandatory properties (eg. Davinci Resolve). - * - * TODO: parse PID_FileDescriptor_Length ? - */ - - uint32_t* storedHeight = aaf_get_propertyValue (DIDescriptor, PID_DigitalImageDescriptor_StoredHeight, &AAFTypeID_UInt32); - - if (storedHeight == NULL) { /* REQ */ - DUMP_OBJ_WARNING (aafi, DIDescriptor, &__td, "Missing PID_DigitalImageDescriptor_StoredHeight"); - } - - // debug( "storedHeight : %u", *storedHeight ); - - uint32_t* storedWidth = aaf_get_propertyValue (DIDescriptor, PID_DigitalImageDescriptor_StoredWidth, &AAFTypeID_UInt32); - - if (storedWidth == NULL) { /* REQ */ - DUMP_OBJ_WARNING (aafi, DIDescriptor, &__td, "Missing PID_DigitalImageDescriptor_StoredWidth"); - } - - // debug( "storedWidth : %u", *storedWidth ); - - uint32_t* displayHeight = aaf_get_propertyValue (DIDescriptor, PID_DigitalImageDescriptor_DisplayHeight, &AAFTypeID_UInt32); - - if (displayHeight == NULL) { - DUMP_OBJ_WARNING (aafi, DIDescriptor, &__td, "Missing PID_DigitalImageDescriptor_DisplayHeight"); - } - - // debug( "displayHeight : %u", *displayHeight ); - - uint32_t* displayWidth = aaf_get_propertyValue (DIDescriptor, PID_DigitalImageDescriptor_DisplayWidth, &AAFTypeID_UInt32); - - if (displayWidth == NULL) { - DUMP_OBJ_WARNING (aafi, DIDescriptor, &__td, "Missing PID_DigitalImageDescriptor_DisplayWidth"); - } - - // debug( "displayWidth : %u", *displayWidth ); - - aafRational_t* imageAspectRatio = aaf_get_propertyValue (DIDescriptor, PID_DigitalImageDescriptor_ImageAspectRatio, &AAFTypeID_Rational); - - if (imageAspectRatio == NULL) { /* REQ */ - DUMP_OBJ_WARNING (aafi, DIDescriptor, &__td, "Missing PID_DigitalImageDescriptor_ImageAspectRatio"); - } - - // debug( "imageAspectRatio : %i/%i", imageAspectRatio->numerator, imageAspectRatio->denominator ); - - return 0; -} - -static int -parse_CDCIDescriptor (AAF_Iface* aafi, aafObject* CDCIDescriptor, td* __ptd) +parse_Mob (AAF_Iface* aafi, aafObject* Mob, td* __ptd) { struct trace_dump __td; __td_set (__td, __ptd, 1); - if (!aaf_get_property (CDCIDescriptor, PID_EssenceDescriptor_Locator)) - __td.eob = 1; + int rc = 0; - /* TODO parse CDCI class */ + aafObject* MobSlots = aaf_get_propertyValue (Mob, PID_Mob_Slots, &AAFTypeID_MobSlotStrongReferenceVector); - int rc = parse_DigitalImageDescriptor (aafi, CDCIDescriptor, __ptd); + if (!MobSlots) { + TRACE_OBJ_ERROR (aafi, Mob, &__td, "Missing Mob::Slots"); + goto err; + } - if (!rc) - DUMP_OBJ (aafi, CDCIDescriptor, &__td); + if (aafUIDCmp (Mob->Class->ID, &AAFClassID_CompositionMob)) { + parse_CompositionMob (aafi, Mob, &__td); + } else if (aafUIDCmp (Mob->Class->ID, &AAFClassID_SourceMob)) { + parse_SourceMob (aafi, Mob, &__td); + } else { + /* NOTE: MasterMob is accessed directly from parse_SourceClip() */ + TRACE_OBJ_NO_SUPPORT (aafi, Mob, &__td); + } + aafObject* MobSlot = NULL; + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&MobSlot, MobSlots, i, __td) + { + parse_MobSlot (aafi, MobSlot, &__td); + } + + goto end; + +err: + rc = -1; + +end: return rc; } static int -parse_PCMDescriptor (AAF_Iface* aafi, aafObject* PCMDescriptor, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - if (!aaf_get_property (PCMDescriptor, PID_EssenceDescriptor_Locator)) - __td.eob = 1; - - aafiAudioEssence* audioEssence = (aafiAudioEssence*)aafi->ctx.current_essence; - - if (audioEssence == NULL) { - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "aafi->ctx.current_essence not set"); - return -1; - } - - audioEssence->type = AAFI_ESSENCE_TYPE_PCM; - - /* Duration of the essence in sample units (not edit units !) */ - aafPosition_t* length = aaf_get_propertyValue (PCMDescriptor, PID_FileDescriptor_Length, &AAFTypeID_PositionType); - - if (length == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing PID_FileDescriptor_Length"); - return -1; - } - - audioEssence->length = *length; - - uint32_t* channels = aaf_get_propertyValue (PCMDescriptor, PID_SoundDescriptor_Channels, &AAFTypeID_UInt32); - - if (channels == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing PID_SoundDescriptor_Channels"); - return -1; - } - - audioEssence->channels = *channels; - - aafRational_t* samplerate = aaf_get_propertyValue (PCMDescriptor, PID_FileDescriptor_SampleRate, &AAFTypeID_Rational); - - if (samplerate == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing PID_FileDescriptor_SampleRate"); - return -1; - } - - if (samplerate->denominator != 1) { - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "PID_FileDescriptor_SampleRate should be integer but is %i/%i", samplerate->numerator, samplerate->denominator); - return -1; - } - - audioEssence->samplerate = samplerate->numerator; - audioEssence->samplerateRational->numerator = samplerate->numerator; - audioEssence->samplerateRational->denominator = samplerate->denominator; - - uint32_t* samplesize = aaf_get_propertyValue (PCMDescriptor, PID_SoundDescriptor_QuantizationBits, &AAFTypeID_UInt32); // uint32_t in AAF std - - if (samplesize == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing PID_SoundDescriptor_QuantizationBits"); - return -1; - } - - if (*samplesize >= (1 << 15)) { - DUMP_OBJ_ERROR (aafi, PCMDescriptor, &__td, "PID_SoundDescriptor_QuantizationBits value error : %u", *samplesize); - return -1; - } - - audioEssence->samplesize = (int16_t)*samplesize; - - if (aafi->Audio->samplesize >= 0) { - /* Set global AAF SampleSize, if it equals preceding. Otherwise set to -1 */ - aafi->Audio->samplesize = (aafi->Audio->samplesize == 0 || (uint16_t)aafi->Audio->samplesize == audioEssence->samplesize) ? audioEssence->samplesize : -1; - } - - /* TODO parse the rest of the class */ - - DUMP_OBJ (aafi, PCMDescriptor, &__td); - - return 0; -} - -static int -parse_WAVEDescriptor (AAF_Iface* aafi, aafObject* WAVEDescriptor, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - if (!aaf_get_property (WAVEDescriptor, PID_EssenceDescriptor_Locator)) - __td.eob = 1; - - aafiAudioEssence* audioEssence = (aafiAudioEssence*)aafi->ctx.current_essence; - - if (audioEssence == NULL) { - DUMP_OBJ_ERROR (aafi, WAVEDescriptor, &__td, "aafi->ctx.current_essence not set"); - return -1; - } - - audioEssence->type = AAFI_ESSENCE_TYPE_WAVE; - - aafProperty* summary = aaf_get_property (WAVEDescriptor, PID_WAVEDescriptor_Summary); - - if (summary == NULL) { - DUMP_OBJ_ERROR (aafi, WAVEDescriptor, &__td, "Missing PID_WAVEDescriptor_Summary"); - return -1; - } - - audioEssence->summary = summary; - - /* - * NOTE : Summary is parsed later in "post-processing" aafi_retrieveData(), - * to be sure clips and essences are linked, so we are able to fallback on - * essence stream in case summary does not contain the full header part. - * - * TODO parse it here - */ - - DUMP_OBJ (aafi, WAVEDescriptor, &__td); - - return 0; -} - -static int -parse_AIFCDescriptor (AAF_Iface* aafi, aafObject* AIFCDescriptor, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - if (!aaf_get_property (AIFCDescriptor, PID_EssenceDescriptor_Locator)) - __td.eob = 1; - - aafiAudioEssence* audioEssence = (aafiAudioEssence*)aafi->ctx.current_essence; - - if (audioEssence == NULL) { - DUMP_OBJ_ERROR (aafi, AIFCDescriptor, &__td, "aafi->ctx.current_essence not set"); - return -1; - } - - audioEssence->type = AAFI_ESSENCE_TYPE_AIFC; - - aafProperty* summary = aaf_get_property (AIFCDescriptor, PID_AIFCDescriptor_Summary); - - if (summary == NULL) { - DUMP_OBJ_ERROR (aafi, AIFCDescriptor, &__td, "Missing PID_AIFCDescriptor_Summary"); - return -1; - } - - audioEssence->summary = summary; - - /* - * NOTE : Summary is parsed later in "post-processing" aafi_retrieveData(), - * to be sure clips and essences are linked, so we are able to fallback on - * essence stream in case summary does not contain the full header part. - */ - - DUMP_OBJ (aafi, AIFCDescriptor, &__td); - - return 0; -} - -/* - * Locator (abs) - * | - * ,---------------. - * | | - * NetworkLocator TextLocator - */ - -static int -parse_Locator (AAF_Iface* aafi, aafObject* Locator, td* __ptd) +parse_CompositionMob (AAF_Iface* aafi, aafObject* CompoMob, td* __ptd) { struct trace_dump __td; __td_set (__td, __ptd, 0); - if (aafUIDCmp (Locator->Class->ID, &AAFClassID_NetworkLocator)) { - parse_NetworkLocator (aafi, Locator, &__td); - } else if (aafUIDCmp (Locator->Class->ID, &AAFClassID_TextLocator)) { + aafUID_t* UsageCode = aaf_get_propertyValue (CompoMob, PID_Mob_UsageCode, &AAFTypeID_UsageType); + + if ((aafUIDCmp (aafi->aafd->Header.OperationalPattern, &AAFOPDef_EditProtocol) && aafUIDCmp (UsageCode, &AAFUsage_TopLevel)) || + (!aafUIDCmp (aafi->aafd->Header.OperationalPattern, &AAFOPDef_EditProtocol) && (aafUIDCmp (UsageCode, &AAFUsage_TopLevel) || !UsageCode))) { + aafi->ctx.TopLevelCompositionMob = CompoMob; + aafi->compositionName = aaf_get_propertyValue (CompoMob, PID_Mob_Name, &AAFTypeID_String); + + aafObject* UserComments = aaf_get_propertyValue (CompoMob, PID_Mob_UserComments, &AAFTypeID_TaggedValueStrongReferenceVector); + + if (retrieve_UserComments (aafi, UserComments, &aafi->metadata) < 0) { + TRACE_OBJ_WARNING (aafi, CompoMob, &__td, "Error parsing Mob::UserComments"); + } else { + TRACE_OBJ (aafi, CompoMob, &__td); + } + } else { + TRACE_OBJ_NO_SUPPORT (aafi, CompoMob, &__td); + } + + return 0; +} + +static int +parse_SourceMob (AAF_Iface* aafi, aafObject* SourceMob, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + aafMobID_t* MobID = aaf_get_propertyValue (SourceMob, PID_Mob_MobID, &AAFTypeID_MobIDType); + + if (!MobID) { + TRACE_OBJ_ERROR (aafi, SourceMob, &__td, "Missing Mob::MobID"); + return -1; + } + + aafTimeStamp_t* CreationTime = aaf_get_propertyValue (SourceMob, PID_Mob_CreationTime, &AAFTypeID_TimeStamp); + + if (!CreationTime) { + TRACE_OBJ_ERROR (aafi, SourceMob, &__td, "Missing Mob::CreationTime"); + return -1; + } + + aafObject* EssenceDesc = aaf_get_propertyValue (SourceMob, PID_SourceMob_EssenceDescription, &AAFTypeID_EssenceDescriptorStrongReference); + + if (!EssenceDesc) { + TRACE_OBJ_ERROR (aafi, SourceMob, &__td, "Missing SourceMob::EssenceDescription"); + return -1; + } + + TRACE_OBJ (aafi, SourceMob, &__td); + + /* + * SourceMob can be parsed for Audio and Video. + * aafi->ctx.current_audio_essence is set, it means we are parsing Audio, so + * we need to retrieve more data. + */ + + if (aafi->ctx.current_audio_essence) { + aafiAudioEssenceFile* audioEssenceFile = (aafiAudioEssenceFile*)aafi->ctx.current_audio_essence; + + memcpy (audioEssenceFile->umid, MobID, sizeof (aafMobID_t)); + + int rc = snprintf (audioEssenceFile->originationDate, sizeof (((aafiAudioEssenceFile*)0)->originationDate), "%04u:%02u:%02u", + (CreationTime->date.year <= 9999) ? CreationTime->date.year : 0, + (CreationTime->date.month <= 99) ? CreationTime->date.month : 0, + (CreationTime->date.day <= 99) ? CreationTime->date.day : 0); + + assert (rc > 0 && (size_t)rc < sizeof (((aafiAudioEssenceFile*)0)->originationDate)); + + // if ( rc < 0 || (size_t)rc >= sizeof(((aafiAudioEssenceFile *)0)->originationDate) ) { + // fprintf( stderr, "snprintf() error" ); + // return -1; + // } + + rc = snprintf (audioEssenceFile->originationTime, sizeof (((aafiAudioEssenceFile*)0)->originationTime), "%02u:%02u:%02u", + (CreationTime->time.hour <= 99) ? CreationTime->time.hour : 0, + (CreationTime->time.minute <= 99) ? CreationTime->time.minute : 0, + (CreationTime->time.second <= 99) ? CreationTime->time.second : 0); + + assert (rc > 0 && (size_t)rc < sizeof (((aafiAudioEssenceFile*)0)->originationTime)); + + // if ( rc < 0 || (size_t)rc >= sizeof(((aafiAudioEssenceFile *)0)->originationTime) ) { + // fprintf( stderr, "snprintf() error" ); + // return -1; + // } + } + + __td.ll[__td.lv] = 2; + parse_EssenceDescriptor (aafi, EssenceDesc, &__td); + __td.ll[__td.lv] = 1; + + return 0; +} + +/* **************************************************************************** + * M o b S l o t + * **************************************************************************** + * + * MobSlot (abs) + * | + * |--> TimelineMobSlot + * |--> EventMobSlot + * `--> StaticMobSlot + */ + +static int +parse_MobSlot (AAF_Iface* aafi, aafObject* MobSlot, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + + aafObject* Segment = aaf_get_propertyValue (MobSlot, PID_MobSlot_Segment, &AAFTypeID_SegmentStrongReference); + + if (!Segment) { + TRACE_OBJ_ERROR (aafi, MobSlot, &__td, "Missing MobSlot::Segment"); + return -1; + } + + if (aafUIDCmp (MobSlot->Class->ID, &AAFClassID_TimelineMobSlot)) { + if (parse_TimelineMobSlot (aafi, MobSlot, &__td) < 0) { + return -1; + } + } else if (aafUIDCmp (MobSlot->Class->ID, &AAFClassID_EventMobSlot)) { + if (parse_EventMobSlot (aafi, MobSlot, &__td) < 0) { + return -1; + } + } else { + TRACE_OBJ_NO_SUPPORT (aafi, MobSlot, &__td); + return -1; + } + + parse_Segment (aafi, Segment, &__td); + + return 0; +} + +static int +parse_TimelineMobSlot (AAF_Iface* aafi, aafObject* TimelineMobSlot, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + aafObject* ParentMob = aaf_get_ObjectAncestor (TimelineMobSlot, &AAFClassID_Mob); + + if (!ParentMob) { + TRACE_OBJ_ERROR (aafi, TimelineMobSlot, &__td, "Could not retrieve parent Mob"); + return -1; + } + + uint32_t* track_num = aaf_get_propertyValue (TimelineMobSlot, PID_MobSlot_PhysicalTrackNumber, &AAFTypeID_UInt32); + + if (!track_num) { + debug ("Missing MobSlot::PhysicalTrackNumber"); + } + + aafObject* Segment = aaf_get_propertyValue (TimelineMobSlot, PID_MobSlot_Segment, &AAFTypeID_SegmentStrongReference); + + if (!Segment) { + TRACE_OBJ_ERROR (aafi, TimelineMobSlot, &__td, "Missing MobSlot::Segment"); + return -1; + } + + aafWeakRef_t* dataDefWeakRef = aaf_get_propertyValue (Segment, PID_Component_DataDefinition, &AAFTypeID_DataDefinitionWeakReference); + + if (!dataDefWeakRef) { + TRACE_OBJ_ERROR (aafi, Segment, &__td, "Could not retrieve Component::DataDefinition from Segment child"); + return -1; + } + + aafUID_t* DataDefinition = aaf_get_DataIdentificationByWeakRef (aafi->aafd, dataDefWeakRef); + + if (!DataDefinition) { + TRACE_OBJ_ERROR (aafi, TimelineMobSlot, &__td, "Could not retrieve DataDefinition"); + return -1; + } + + aafRational_t* edit_rate = aaf_get_propertyValue (TimelineMobSlot, PID_TimelineMobSlot_EditRate, &AAFTypeID_Rational); + + if (!edit_rate) { + TRACE_OBJ_ERROR (aafi, TimelineMobSlot, &__td, "Missing TimelineMobSlot::EditRate"); + return -1; + } + + if (aafUIDCmp (ParentMob->Class->ID, &AAFClassID_CompositionMob)) { /* - * A TextLocator object provides information to the user to help locate the file - * containing the essence or to locate the physical media. The TextLocator is not - * intended for applications to use without user intervention. + * Each TimelineMobSlot represents a track, either audio or video. * - * TODO what to do with those ??? - * never encountered anyway.. + * The Timeline MobSlot::Segment should hold a Sequence of Components. + * This Sequence represents the timeline track. Therefore, each SourceClip + * contained in the Sequence::Components represents a clip on the timeline. + * + * CompositionMob can have TimelineMobSlots, StaticMobSlots, EventMobSlots */ - __td.eob = 1; - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, Locator, &__td); + /* + * TODO: implement multiple TopLevel compositions support + */ - // wchar_t *name = aaf_get_propertyValue( Locator, PID_TextLocator_Name, &AAFTypeID_String ); - // warning( "Got an AAFClassID_TextLocator : \"%ls\"", name ); - // free( name ); + if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || + aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { + /* + * « In a CompositionMob or MasterMob, PhysicalTrackNumber is the output + * channel number that the MobSlot should be routed to when played. » + */ + + if (aafi->ctx.TopLevelCompositionMob == ParentMob /*!parentMobUsageCode || aafUIDCmp( parentMobUsageCode, &AAFUsage_TopLevel )*/ /*!aafi->ctx.is_inside_derivation_chain*/) { + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + + uint32_t tracknumber = (track_num) ? *track_num : (aafi->Audio->track_count + 1); + + aafiAudioTrack* track = aafi_newAudioTrack (aafi); + + track->number = tracknumber; + track->name = aaf_get_propertyValue (TimelineMobSlot, PID_MobSlot_SlotName, &AAFTypeID_String); + track->edit_rate = edit_rate; + + aafi->Audio->track_count += 1; + + aafi->ctx.current_track = track; + + /* + * Avid Media Composer + */ + + void* TimelineMobAttributeList = aaf_get_propertyValue (TimelineMobSlot, aaf_get_PropertyIDByName (aafi->aafd, "TimelineMobAttributeList"), &AAFTypeID_TaggedValueStrongReferenceVector); + + if (TimelineMobAttributeList) { + int32_t* solo = aaf_get_TaggedValueByName (aafi->aafd, TimelineMobAttributeList, "AudioMixerCompSolo", &AAFTypeID_Int32); + int32_t* mute = aaf_get_TaggedValueByName (aafi->aafd, TimelineMobAttributeList, "AudioMixerCompMute", &AAFTypeID_Int32); + + if (solo && *solo) { + track->solo = 1; + } + + if (mute && *mute) { + track->mute = 1; + } + } + } else { + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + } + } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || + aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { + if (aafi->Video->Tracks) { + TRACE_OBJ_ERROR (aafi, TimelineMobSlot, &__td, "Current implementation supports only one video track"); + return -1; + } + + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + + uint32_t tracknumber = (track_num) ? *track_num : 1 /* current implementation supports only one video track */; + + aafiVideoTrack* track = aafi_newVideoTrack (aafi); + + track->number = tracknumber; + track->name = aaf_get_propertyValue (TimelineMobSlot, PID_MobSlot_SlotName, &AAFTypeID_String); + track->edit_rate = edit_rate; + } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Timecode) || + aafUIDCmp (DataDefinition, &AAFDataDef_LegacyTimecode)) { + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + } else if (aafUIDCmp (DataDefinition, &AAFDataDef_DescriptiveMetadata)) { + /* + * Avid Media Composer 23.12, markers with duration (no-duration markers are held by AAFClassID_EventMobSlot) + * + │ 04179│ └──◻ AAFClassID_TimelineMobSlot [slot:3003 track:12] (DataDef: AAFDataDef_DescriptiveMetadata) : Segmentation + │ 01946│ └──◻ AAFClassID_Sequence (Length: 4) + │ 03031│ └──◻ AAFClassID_DescriptiveMarker (Length: 4) (MetaProps: CommentMarkerAttributeList[0xffd4] CommentMarkerColor[0xffdb] CommentMarkerUSer[0xffda] CommentMarkerDate[0xffd9] CommentMarkerTime[0xffd8]) + */ + + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + } else { + TRACE_OBJ_NO_SUPPORT (aafi, TimelineMobSlot, &__td); + return -1; + } + } else if (aafUIDCmp (ParentMob->Class->ID, &AAFClassID_MasterMob)) { + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + } else if (aafUIDCmp (ParentMob->Class->ID, &AAFClassID_SourceMob)) { + /* + * SourceMob can be parsed for Audio and Video. + * aafi->ctx.current_audio_essence is set, it means we are parsing Audio, so + * we need to retrieve more data. + */ + + if (aafi->ctx.current_audio_essence) { + aafPosition_t* Origin = aaf_get_propertyValue (TimelineMobSlot, PID_TimelineMobSlot_Origin, &AAFTypeID_PositionType); + + if (!Origin) { + TRACE_OBJ_ERROR (aafi, TimelineMobSlot, &__td, "Missing TimelineMobSlot::Origin"); + return -1; + } + + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + + aafiAudioEssenceFile* audioEssenceFile = (aafiAudioEssenceFile*)aafi->ctx.current_audio_essence; + + audioEssenceFile->sourceMobSlotOrigin = *Origin; + audioEssenceFile->sourceMobSlotEditRate = edit_rate; + } else { + TRACE_OBJ (aafi, TimelineMobSlot, &__td); + } } else { - __td.eob = 1; - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, Locator, &__td); + /* + * AAFClassID_MasterMob and AAFClassID_SourceMob are accessed directly from TimelineMobSlot > SourceClip + */ + TRACE_OBJ_NO_SUPPORT (aafi, TimelineMobSlot, &__td); + return -1; } return 0; } static int -parse_NetworkLocator (AAF_Iface* aafi, aafObject* NetworkLocator, td* __ptd) +parse_EventMobSlot (AAF_Iface* aafi, aafObject* EventMobSlot, td* __ptd) { struct trace_dump __td; - __td_set (__td, __ptd, 1); - __td.eob = 1; + __td_set (__td, __ptd, 0); - /* - * This holds an URI pointing to the essence file, when it is not embedded. - * However, sometimes it holds an URI to the AAF file itself when essence is - * embedded so it is not a valid way to test if essence is embedded or not. - */ + aafRational_t* edit_rate = aaf_get_propertyValue (EventMobSlot, PID_EventMobSlot_EditRate, &AAFTypeID_Rational); - wchar_t* original_file_path = aaf_get_propertyValue (NetworkLocator, PID_NetworkLocator_URLString, &AAFTypeID_String); - - if (original_file_path == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, NetworkLocator, &__td, "Missing PID_NetworkLocator_URLString"); + if (!edit_rate) { + TRACE_OBJ_ERROR (aafi, EventMobSlot, &__td, "Missing EventMobSlot::EditRate"); return -1; } - /* TODO find a better way to check if we're parsing audio */ + TRACE_OBJ (aafi, EventMobSlot, &__td); - if (aafi->ctx.current_essence) { - aafi->ctx.current_essence->original_file_path = original_file_path; - } else if (aafi->ctx.current_video_essence) { - aafi->ctx.current_video_essence->original_file_path = original_file_path; - } else { - DUMP_OBJ_ERROR (aafi, NetworkLocator, &__td, "aafi->ctx.current_essence AND aafi->ctx.current_video_essence not set"); - return -1; - } - - DUMP_OBJ_INFO (aafi, NetworkLocator, &__td, ": %ls", original_file_path); - - return 0; -} - -static int -parse_EssenceData (AAF_Iface* aafi, aafObject* EssenceData, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - __td.eob = 1; - - aafiAudioEssence* audioEssence = (aafiAudioEssence*)aafi->ctx.current_essence; - - if (audioEssence == NULL) { - DUMP_OBJ_ERROR (aafi, EssenceData, &__td, "aafi->ctx.current_essence not set"); - return -1; - } - - /* - * The EssenceData::Data property has the stored form SF_DATA_STREAM, so - * it holds the name of the Data stream, which should be located at - * /Path/To/EssenceData/DataStream - */ - - wchar_t* StreamName = aaf_get_propertyValue (EssenceData, PID_EssenceData_Data, &AAFTypeID_String); - - if (StreamName == NULL) { - DUMP_OBJ_ERROR (aafi, EssenceData, &__td, "Missing PID_EssenceData_Data"); - return -1; - } - - wchar_t DataPath[CFB_PATH_NAME_SZ]; - memset (DataPath, 0x00, sizeof (DataPath)); - - wchar_t* path = aaf_get_ObjectPath (EssenceData); - - swprintf (DataPath, CFB_PATH_NAME_SZ, L"%" WPRIws L"/%" WPRIws, path, StreamName); - - free (StreamName); - - cfbNode* DataNode = cfb_getNodeByPath (aafi->aafd->cfbd, DataPath, 0); - - if (DataNode == NULL) { - DUMP_OBJ_ERROR (aafi, EssenceData, &__td, "Could not retrieve Data stream node %ls", DataPath); - return -1; - } - - audioEssence->node = DataNode; - - audioEssence->is_embedded = 1; /* TODO to be set elsewhere ? */ - - /* disable raw data byte length, because we want it to be the exact audio length in samples */ - - // uint64_t dataLen = cfb_getNodeStreamLen( aafi->aafd->cfbd, DataNode ); - // - // if ( dataLen == 0 ) { - // DUMP_OBJ_WARNING( aafi, EssenceData, &__td, "Got 0 Bytes Data stream length" ); - // return -1; - // } - // else { - // DUMP_OBJ( aafi, EssenceData, &__td ); - // } - // - // /* NOTE Might be tweaked by aafi_parse_audio_summary() */ - // audioEssence->length = dataLen; + aafi->ctx.current_markers_edit_rate = edit_rate; return 0; } @@ -1468,18 +583,9 @@ parse_Component (AAF_Iface* aafi, aafObject* Component, td* __ptd) __td_set (__td, __ptd, 0); if (aafUIDCmp (Component->Class->ID, &AAFClassID_Transition)) { - /* - * A Transition between a Filler and a SourceClip sets a Fade In. - * A Transition between a SourceClip and a Filler sets a Fade Out. - * A Transition between two SourceClips sets a Cross-Fade. - * - * Since the Transition applies to the elements that suround it in - * the Sequence, the OperationGroup::InputSegments is then left unused. - */ - parse_Transition (aafi, Component, &__td); } else { - aafi_parse_Segment (aafi, Component, &__td); + parse_Segment (aafi, Component, &__td); } return 0; @@ -1491,148 +597,114 @@ parse_Transition (AAF_Iface* aafi, aafObject* Transition, td* __ptd) struct trace_dump __td; __td_set (__td, __ptd, 1); - aafUID_t* DataDefinition = get_Component_DataDefinition (aafi, Transition); + /* + * A Transition between a Filler and a SourceClip sets a Fade In. + * A Transition between a SourceClip and a Filler sets a Fade Out. + * A Transition between two SourceClips sets a Cross-Fade. + * + * Since the Transition applies to the elements that suround it in + * the Sequence, the OperationGroup::InputSegments is left unused. + */ - if (DataDefinition == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, Transition, &__td, "Could not retrieve DataDefinition"); + aafWeakRef_t* dataDefWeakRef = aaf_get_propertyValue (Transition, PID_Component_DataDefinition, &AAFTypeID_DataDefinitionWeakReference); + + if (!dataDefWeakRef) { + TRACE_OBJ_ERROR (aafi, Transition, &__td, "Missing Component::DataDefinition."); + return -1; + } + + aafUID_t* DataDefinition = aaf_get_DataIdentificationByWeakRef (aafi->aafd, dataDefWeakRef); + + if (!DataDefinition) { + TRACE_OBJ_ERROR (aafi, Transition, &__td, "Could not retrieve DataDefinition"); return -1; } if (!aafUIDCmp (DataDefinition, &AAFDataDef_Sound) && !aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { - DUMP_OBJ_ERROR (aafi, Transition, &__td, "Current implementation only supports Transition inside Audio Tracks"); + TRACE_OBJ_ERROR (aafi, Transition, &__td, "Current implementation does not support video Transitions"); return -1; } int64_t* length = aaf_get_propertyValue (Transition, PID_Component_Length, &AAFTypeID_LengthType); - if (length == NULL) { - DUMP_OBJ_ERROR (aafi, Transition, &__td, "Missing PID_Component_Length"); + if (!length) { + TRACE_OBJ_ERROR (aafi, Transition, &__td, "Missing Component::Length"); return -1; } - int flags = 0; - - if (Transition->prev != NULL && aafUIDCmp (Transition->prev->Class->ID, &AAFClassID_Filler)) { - flags |= AAFI_TRANS_FADE_IN; - } else if (Transition->next != NULL && aafUIDCmp (Transition->next->Class->ID, &AAFClassID_Filler)) { - flags |= AAFI_TRANS_FADE_OUT; - } else if (Transition->next != NULL && aafUIDCmp (Transition->next->Class->ID, &AAFClassID_Filler) == 0 && - Transition->prev != NULL && aafUIDCmp (Transition->prev->Class->ID, &AAFClassID_Filler) == 0) { - flags |= AAFI_TRANS_XFADE; - } else { - DUMP_OBJ_ERROR (aafi, Transition, &__td, "Could not guess if type is FadeIn, FadeOut or xFade"); - return -1; - } - - aafiTimelineItem* Item = aafi_newTimelineItem (aafi, aafi->ctx.current_track, AAFI_TRANS); - - aafiTransition* Trans = Item->data; //(aafiTransition*)&Item->data; - - Trans->len = *length; - Trans->flags = flags; - - int missing_cutpt = 0; - - aafPosition_t* cut_point = aaf_get_propertyValue (Transition, PID_Transition_CutPoint, &AAFTypeID_PositionType); - - if (cut_point == NULL) { /* req */ - // DUMP_OBJ_WARNING( aafi, Transition, &__td, "Missing PID_Transition_CutPoint : Setting to Trans->len/2" ); - missing_cutpt = 1; - Trans->cut_pt = Trans->len / 2; // set default cutpoint to the middle of transition - } else { - Trans->cut_pt = *cut_point; - } - aafObject* OpGroup = aaf_get_propertyValue (Transition, PID_Transition_OperationGroup, &AAFTypeID_OperationGroupStrongReference); - if (OpGroup != NULL) { /* req */ - - if (missing_cutpt) { - DUMP_OBJ_WARNING (aafi, Transition, &__td, "Missing PID_Transition_CutPoint : Setting to Trans->len/2"); - } else { - DUMP_OBJ (aafi, Transition, &__td); - } - - /* - * Don't handle parse_OperationGroup() return code, since it should - * always fallback to default in case of failure. - */ - - aafi->ctx.current_transition = Trans; - parse_OperationGroup (aafi, OpGroup, &__td); - aafi->ctx.current_transition = NULL; - } else { - /* Setting fade to default */ - - __td.eob = 1; - - if (missing_cutpt) { - DUMP_OBJ_WARNING (aafi, Transition, &__td, "Missing PID_Transition_CutPoint AND PID_Transition_OperationGroup : Setting to Trans->len/2; Linear"); - } else { - DUMP_OBJ_WARNING (aafi, Transition, &__td, "Missing PID_Transition_OperationGroup : Setting to Linear interpolation"); - } - - Trans->flags |= (AAFI_INTERPOL_LINEAR | AAFI_TRANS_SINGLE_CURVE); - - Trans->time_a = calloc (2, sizeof (aafRational_t)); - Trans->value_a = calloc (2, sizeof (aafRational_t)); - - Trans->time_a[0].numerator = 0; - Trans->time_a[0].denominator = 0; - Trans->time_a[1].numerator = 1; - Trans->time_a[1].denominator = 1; - - if (Trans->flags & AAFI_TRANS_FADE_IN || - Trans->flags & AAFI_TRANS_XFADE) { - Trans->value_a[0].numerator = 0; - Trans->value_a[0].denominator = 0; - Trans->value_a[1].numerator = 1; - Trans->value_a[1].denominator = 1; - } else if (Trans->flags & AAFI_TRANS_FADE_OUT) { - Trans->value_a[0].numerator = 1; - Trans->value_a[0].denominator = 1; - Trans->value_a[1].numerator = 0; - Trans->value_a[1].denominator = 0; - } + if (!OpGroup) { + TRACE_OBJ_ERROR (aafi, Transition, &__td, "Missing Transition::OperationGroup"); + return -1; } + aafPosition_t* cutPoint = aaf_get_propertyValue (Transition, PID_Transition_CutPoint, &AAFTypeID_PositionType); + + if (!cutPoint) { + /* not encountered though */ + debug ("Missing Transition::CutPoint : setting cut point to Transition::Length/2"); + } + + uint32_t fadeType = 0; + + if (Transition->prev != NULL && aafUIDCmp (Transition->prev->Class->ID, &AAFClassID_Filler)) { + fadeType |= AAFI_TRANS_FADE_IN; + } else if (Transition->next != NULL && aafUIDCmp (Transition->next->Class->ID, &AAFClassID_Filler)) { + fadeType |= AAFI_TRANS_FADE_OUT; + } else if (Transition->next != NULL && aafUIDCmp (Transition->next->Class->ID, &AAFClassID_Filler) == 0 && + Transition->prev != NULL && aafUIDCmp (Transition->prev->Class->ID, &AAFClassID_Filler) == 0) { + fadeType |= AAFI_TRANS_XFADE; + } else { + TRACE_OBJ_ERROR (aafi, Transition, &__td, "Could not guess if type is FadeIn, FadeOut or xFade"); + return -1; + } + + TRACE_OBJ (aafi, Transition, &__td); + + aafiTransition* Trans = aafi_newTransition (aafi, aafi->ctx.current_track); + + Trans->len = *length; + Trans->flags = fadeType; + Trans->cut_pt = (cutPoint) ? *cutPoint : (Trans->len / 2); + + /* + * OperationGroup *might* contain a Parameter (ParameterDef_Level) specifying + * the fade curve. However, this parameter is optional regarding AAF_EditProtocol + * and there is most likely no implementation that exports custom fade curves. + * Thus, we only retrieve ParameterDef_Level to possibly set interpolation, and we + * always set the fade as defined in AAF_EditProtocol, with only two points : + * + * « ParameterDef_Level (optional; default is a VaryingValue object + * with two control points: Value 0 at time 0, and value 1 at time 1) » + */ + + if (fadeType & AAFI_TRANS_FADE_IN || + fadeType & AAFI_TRANS_XFADE) { + Trans->value_a[0].numerator = 0; + Trans->value_a[0].denominator = 0; + Trans->value_a[1].numerator = 1; + Trans->value_a[1].denominator = 1; + } else if (fadeType & AAFI_TRANS_FADE_OUT) { + Trans->value_a[0].numerator = 1; + Trans->value_a[0].denominator = 1; + Trans->value_a[1].numerator = 0; + Trans->value_a[1].denominator = 0; + } + + aafi->ctx.current_transition = Trans; + + parse_OperationGroup (aafi, OpGroup, &__td); + + aafi->ctx.current_transition = NULL; aafi->ctx.current_track->current_pos -= *length; return 0; } -static int -parse_NestedScope (AAF_Iface* aafi, aafObject* NestedScope, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - aafObject* Slot = NULL; - aafObject* Slots = aaf_get_propertyValue (NestedScope, PID_NestedScope_Slots, &AAFUID_NULL); - - if (Slots == NULL) { - DUMP_OBJ_ERROR (aafi, NestedScope, &__td, "Missing PID_NestedScope_Slots"); - return -1; - } - - DUMP_OBJ (aafi, NestedScope, &__td); - - int i = 0; - - aaf_foreach_ObjectInSet (&Slot, Slots, NULL) - { - __td.ll[__td.lv] = (Slots->Header->_entryCount > 1) ? (Slots->Header->_entryCount - i++) : 0; //(MobSlot->next) ? 1 : 0; - aafi_parse_Segment (aafi, Slot, &__td); - } - - /* TODO should we take aafi_parse_Segment() return code into account ? */ - - return 0; -} - int -aafi_parse_Segment (AAF_Iface* aafi, aafObject* Segment, td* __ptd) +parse_Segment (AAF_Iface* aafi, aafObject* Segment, td* __ptd) { struct trace_dump __td; __td_set (__td, __ptd, 0); @@ -1650,33 +722,28 @@ aafi_parse_Segment (AAF_Iface* aafi, aafObject* Segment, td* __ptd) } else if (aafUIDCmp (Segment->Class->ID, &AAFClassID_NestedScope)) { return parse_NestedScope (aafi, Segment, &__td); } else if (aafUIDCmp (Segment->Class->ID, &AAFClassID_Timecode)) { - /* - * TODO can contain sequence ? other Timecode SMPTE .. - */ - return parse_Timecode (aafi, Segment, &__td); } else if (aafUIDCmp (Segment->Class->ID, &AAFClassID_DescriptiveMarker)) { - if (resolve_AAF (aafi)) { - resolve_parse_aafObject_DescriptiveMarker (aafi, Segment, &__td); - } else { - __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, Segment, &__td); - return -1; - } + return parse_DescriptiveMarker (aafi, Segment, &__td); } else if (aafUIDCmp (Segment->Class->ID, &AAFClassID_EssenceGroup)) { /* * Should provide support for multiple essences representing the same * source material with different resolution, compression, codec, etc. * - * TODO To be tested with Avid and rendered effects. + * TODO To be tested with Avid and rendered effects ? */ __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, Segment, &__td); + TRACE_OBJ_NO_SUPPORT (aafi, Segment, &__td); + __td.lv--; + return -1; } else { __td.lv++; - DUMP_OBJ_NO_SUPPORT (aafi, Segment, &__td); + TRACE_OBJ_NO_SUPPORT (aafi, Segment, &__td); + __td.lv--; + + return -1; } return 0; @@ -1687,542 +754,46 @@ parse_Filler (AAF_Iface* aafi, aafObject* Filler, td* __ptd) { struct trace_dump __td; __td_set (__td, __ptd, 1); - __td.eob = 1; - aafUID_t* DataDefinition = get_Component_DataDefinition (aafi, Filler); + aafWeakRef_t* dataDefWeakRef = aaf_get_propertyValue (Filler, PID_Component_DataDefinition, &AAFTypeID_DataDefinitionWeakReference); - if (DataDefinition == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, Filler, &__td, "Could not retrieve DataDefinition"); + if (!dataDefWeakRef) { + TRACE_OBJ_ERROR (aafi, Filler, &__td, "Missing Component::DataDefinition."); return -1; } - if (aafUIDCmp (Filler->Parent->Class->ID, &AAFClassID_TimelineMobSlot)) { - /* - * Just an empty track, do nothing. - */ - } else if (aafUIDCmp (Filler->Parent->Class->ID, &AAFClassID_Sequence) || - aafUIDCmp (Filler->Parent->Class->ID, &AAFClassID_Selector)) { - /* - * This represents an empty space on the timeline, between two clips - * which is Component::Length long. - */ + aafUID_t* DataDefinition = aaf_get_DataIdentificationByWeakRef (aafi->aafd, dataDefWeakRef); - int64_t* length = aaf_get_propertyValue (Filler, PID_Component_Length, &AAFTypeID_LengthType); - - if (length == NULL) { /* probably req for Filler */ - DUMP_OBJ_ERROR (aafi, Filler, &__td, "Missing PID_Component_Length"); - return -1; - } - - if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { - aafi->ctx.current_track->current_pos += *length; - } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { - aafi->Video->Tracks->current_pos += *length; - } - - } else { - DUMP_OBJ_NO_SUPPORT (aafi, Filler, &__td); + if (!DataDefinition) { + TRACE_OBJ_ERROR (aafi, Filler, &__td, "Could not retrieve DataDefinition"); return -1; } - DUMP_OBJ (aafi, Filler, &__td); - - return 0; -} - -static int -parse_Sequence (AAF_Iface* aafi, aafObject* Sequence, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - aafObject* Component = NULL; - aafObject* Components = aaf_get_propertyValue (Sequence, PID_Sequence_Components, &AAFTypeID_ComponentStrongReferenceVector); - - if (Components == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, Sequence, &__td, "Missing PID_Sequence_Components"); - return -1; - } - - DUMP_OBJ (aafi, Sequence, &__td); - - int i = 0; - - aaf_foreach_ObjectInSet (&Component, Components, NULL) - { - __td.ll[__td.lv] = (Components->Header->_entryCount > 1) ? (Components->Header->_entryCount - i++) : 0; //(MobSlot->next) ? 1 : 0; - parse_Component (aafi, Component, &__td); - } - - return 0; -} - -static int -parse_Timecode (AAF_Iface* aafi, aafObject* Timecode, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - __td.eob = 1; - - aafPosition_t* tc_start = aaf_get_propertyValue (Timecode, PID_Timecode_Start, &AAFTypeID_PositionType); - - if (tc_start == NULL) { - DUMP_OBJ_ERROR (aafi, Timecode, &__td, "Missing PID_Timecode_Start"); - return -1; - } - - uint16_t* tc_fps = aaf_get_propertyValue (Timecode, PID_Timecode_FPS, &AAFTypeID_UInt16); - - if (tc_fps == NULL) { - DUMP_OBJ_ERROR (aafi, Timecode, &__td, "Missing PID_Timecode_FPS"); - return -1; - } - - uint8_t* tc_drop = aaf_get_propertyValue (Timecode, PID_Timecode_Drop, &AAFTypeID_UInt8); - - if (tc_drop == NULL) { - DUMP_OBJ_ERROR (aafi, Timecode, &__td, "Missing PID_Timecode_Drop"); - return -1; - } - - /* TODO this should be retrieved directly from TimelineMobSlot */ - - aafObject* ParentMobSlot = get_Object_Ancestor (aafi, Timecode, &AAFClassID_MobSlot); - - if (ParentMobSlot == NULL) { - DUMP_OBJ_ERROR (aafi, Timecode, &__td, "Could not retrieve parent MobSlot"); - return -1; - } - - aafRational_t* tc_edit_rate = aaf_get_propertyValue (ParentMobSlot, PID_TimelineMobSlot_EditRate, &AAFTypeID_Rational); - - if (tc_edit_rate == NULL) { - DUMP_OBJ_ERROR (aafi, Timecode, &__td, "Missing parent MobSlot PID_TimelineMobSlot_EditRate"); - return -1; - } - - if (aafi->Timecode) { - DUMP_OBJ_WARNING (aafi, Timecode, &__td, "Timecode was already set, ignoring (%lu, %u fps)", *tc_start, *tc_fps); - return -1; - } - /* TODO allocate in specific function */ - - aafiTimecode* tc = calloc (sizeof (aafiTimecode), sizeof (unsigned char)); - - if (tc == NULL) { - DUMP_OBJ_ERROR (aafi, Timecode, &__td, "calloc() : %s", strerror (errno)); - return -1; - } - - tc->start = *tc_start; - tc->fps = *tc_fps; - tc->drop = *tc_drop; - tc->edit_rate = tc_edit_rate; - - aafi->Timecode = tc; - - DUMP_OBJ (aafi, Timecode, &__td); - - return 0; -} - -static int -parse_OperationGroup (AAF_Iface* aafi, aafObject* OpGroup, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - if (!aaf_get_property (OpGroup, PID_OperationGroup_InputSegments) && - !aaf_get_property (OpGroup, PID_OperationGroup_Parameters)) { - __td.eob = 1; - } - - aafObject* ParentMob = get_Object_Ancestor (aafi, OpGroup, &AAFClassID_Mob); - - if (ParentMob == NULL) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Could not retrieve parent Mob"); - return -1; - } - - if (!aafUIDCmp (ParentMob->Class->ID, &AAFClassID_CompositionMob)) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "OperationGroup parser is currently implemented for AAFClassID_CompositionMob children only"); - return -1; - } - - aafUID_t* OperationIdentification = get_OperationGroup_OperationIdentification (aafi, OpGroup); - - /* PRINT OPERATIONDEFINITIONS */ - - // aafObject * Parameters = aaf_get_propertyValue( OpGroup, PID_OperationGroup_Parameters ); - // - // if ( Parameters ) { - // aafObject * Param = NULL; - // - // aaf_foreach_ObjectInSet( &Param, Parameters, NULL ) { - // aafUID_t *ParamDef = aaf_get_propertyValue( Param, PID_Parameter_Definition, &AAFTypeID_AUID ); - // debug( " OpDef %ls (%ls) | %ls", aaft_OperationDefToText(aafi->aafd, OperationIdentification), AUIDToText( ParamDef ), aaft_ParameterToText( aafi->aafd, ParamDef ) ); - // } - // } - - // if ( aafUIDCmp( aafi->ctx.Mob->Class->ID, &AAFClassID_MasterMob ) ) { - // - // /* - // * TODO: This was seen in the spec, but never encountered in real world. - // */ - // - // aafi_trace_obj( aafi, Segment, ANSI_COLOR_RED ); - // error( "MobSlot::Segment > OperationGroup Not implemented yet." ); - // return -1; - // - // } - - int rc = 0; - - if (aafUIDCmp (OpGroup->Parent->Class->ID, &AAFClassID_Transition)) { - aafiTransition* Trans = aafi->ctx.current_transition; - - if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioDissolve)) { - /* - * Mono Audio Dissolve (Fade, Cross Fade) - * - * The same parameter (curve/level) is applied to the outgoing fade on first - * clip (if any) and to the incoming fade on second clip (if any). - */ - - // __td.eob = 1; - - Trans->flags |= AAFI_TRANS_SINGLE_CURVE; - - int set_default = 0; - - aafObject* Param = NULL; - aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); /* opt */ - - if (Parameters) { - /* Retrieve AAFParameterDef_Level parameter */ - - aaf_foreach_ObjectInSet (&Param, Parameters, NULL) - { - aafUID_t* ParamDef = aaf_get_propertyValue (Param, PID_Parameter_Definition, &AAFTypeID_AUID); - - if (aafUIDCmp (ParamDef, &AAFParameterDef_Level)) - break; - } - } else { - // DUMP_OBJ_WARNING( aafi, OpGroup, &__td, "Missing PID_OperationGroup_Parameters: Falling back to Linear" ); - set_default = 1; - } - - if (Param) { - DUMP_OBJ (aafi, OpGroup, &__td); - - if (aaf_get_property (OpGroup, PID_OperationGroup_InputSegments)) { - __td.ll[__td.lv] = 2; - } - - if (parse_Parameter (aafi, Param, &__td) < 0) { - set_default = 1; - } - - __td.ll[__td.lv] = 0; - } else { - /* - * Do not notify exception since this case is standard compliant : - * - * ParameterDef_Level (optional; default is a VaryingValue object with - * two control points: Value 0 at time 0, and value 1 at time 1) - */ - - __td.eob = 1; - DUMP_OBJ (aafi, OpGroup, &__td); - - // DUMP_OBJ_WARNING( aafi, OpGroup, &__td, "Missing Parameter AAFParameterDef_Level: Setting to Linear" ); - - set_default = 1; - } - - if (set_default) { - /* - * ParameterDef_Level (optional; default is a VaryingValue object - * with two control points: Value 0 at time 0, and value 1 at time 1) - * - * This is also a fallback in case of parse_Parameter() failure. - */ - - Trans->flags |= AAFI_INTERPOL_LINEAR; - - Trans->time_a = calloc (2, sizeof (aafRational_t)); - Trans->value_a = calloc (2, sizeof (aafRational_t)); - - Trans->time_a[0].numerator = 0; - Trans->time_a[0].denominator = 0; - Trans->time_a[1].numerator = 1; - Trans->time_a[1].denominator = 1; - - if (Trans->flags & AAFI_TRANS_FADE_IN || - Trans->flags & AAFI_TRANS_XFADE) { - Trans->value_a[0].numerator = 0; - Trans->value_a[0].denominator = 0; - Trans->value_a[1].numerator = 1; - Trans->value_a[1].denominator = 1; - } else if (Trans->flags & AAFI_TRANS_FADE_OUT) { - Trans->value_a[0].numerator = 1; - Trans->value_a[0].denominator = 1; - Trans->value_a[1].numerator = 0; - Trans->value_a[1].denominator = 0; - } - } - - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_TwoParameterMonoAudioDissolve)) { - DUMP_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); - /* Two distinct parameters are used for the outgoing and incoming fades. */ - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_StereoAudioDissolve)) { - DUMP_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); - /* TODO Unknown usage and implementation */ - } else { - DUMP_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); - } - - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_AudioChannelCombiner)) { - DUMP_OBJ (aafi, OpGroup, &__td); - - aafObject* InputSegment = NULL; - aafObject* InputSegments = aaf_get_propertyValue (OpGroup, PID_OperationGroup_InputSegments, &AAFTypeID_SegmentStrongReferenceVector); - - __td.ll[__td.lv] = InputSegments->Header->_entryCount; - - aafi->ctx.current_clip_is_combined = 1; - aafi->ctx.current_combined_clip_total_channel = InputSegments->Header->_entryCount; - aafi->ctx.current_combined_clip_channel_num = 0; - aafi->ctx.current_combined_clip_forced_length = 0; - - if (resolve_AAF (aafi)) { - /* - * This is clearly a violation of the standard (p 57). When Davinci Resolve - * exports multichannel clips, it does not set SourceClip::Length correctly. - * Insted, it's more like some sort of frame-rounded value which dosn't match - * the timeline. However, the correct value is set to OperationGroup::length. - */ - int64_t* length = aaf_get_propertyValue (OpGroup, PID_Component_Length, &AAFTypeID_LengthType); - aafi->ctx.current_combined_clip_forced_length = (length) ? *length : 0; - } - - aaf_foreach_ObjectInSet (&InputSegment, InputSegments, NULL) - { - aafi_parse_Segment (aafi, InputSegment, &__td); - - aafi->ctx.current_combined_clip_channel_num++; - __td.ll[__td.lv]--; - } - - /* - * Sets the track format. - */ - - aafiAudioTrack* current_track = (aafiAudioTrack*)aafi->ctx.current_track; - - aafiTrackFormat_e track_format = AAFI_TRACK_FORMAT_UNKNOWN; - - if (aafi->ctx.current_combined_clip_total_channel == 2) { - track_format = AAFI_TRACK_FORMAT_STEREO; - } else if (aafi->ctx.current_combined_clip_total_channel == 6) { - track_format = AAFI_TRACK_FORMAT_5_1; - } else if (aafi->ctx.current_combined_clip_total_channel == 8) { - track_format = AAFI_TRACK_FORMAT_7_1; - } else { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Unknown track format (%u)", aafi->ctx.current_combined_clip_total_channel); - - /* - * Reset multichannel track context. - */ - - aafi->ctx.current_clip_is_combined = 0; - aafi->ctx.current_combined_clip_total_channel = 0; - aafi->ctx.current_combined_clip_channel_num = 0; - aafi->ctx.current_combined_clip_forced_length = 0; - - return -1; - } - - if (current_track->format != AAFI_TRACK_FORMAT_NOT_SET && - current_track->format != track_format) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Track format (%u) does not match current clip (%u)", current_track->format, track_format); - - /* - * Reset multichannel track context. - */ - - aafi->ctx.current_clip_is_combined = 0; - aafi->ctx.current_combined_clip_total_channel = 0; - aafi->ctx.current_combined_clip_channel_num = 0; - aafi->ctx.current_combined_clip_forced_length = 0; - - return -1; - } - - current_track->format = track_format; - - /* - * Reset multichannel track context. - */ - - aafi->ctx.current_clip_is_combined = 0; - aafi->ctx.current_combined_clip_total_channel = 0; - aafi->ctx.current_combined_clip_channel_num = 0; - aafi->ctx.current_combined_clip_forced_length = 0; - - // return; - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioGain)) { - aafObject* Param = NULL; - aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); - - if (Parameters == NULL) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Missing PID_OperationGroup_Parameters"); - rc = -1; - goto end; // we still have to parse segments - } - - /* Retrieve AAFParameterDef_Amplitude parameter */ - - aaf_foreach_ObjectInSet (&Param, Parameters, NULL) - { - aafUID_t* ParamDef = aaf_get_propertyValue (Param, PID_Parameter_Definition, &AAFTypeID_AUID); - - if (aafUIDCmp (ParamDef, &AAFParameterDef_Amplitude)) - break; - } - - if (Param == NULL) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Missing Parameter ParameterDef_Amplitude"); - rc = -1; - goto end; // we still have to parse segments - } - - DUMP_OBJ (aafi, OpGroup, &__td); - - __td.ll[__td.lv] = 2; - - rc = parse_Parameter (aafi, Param, &__td); - - // if ( rc == 0 ) { - // DUMP_OBJ( aafi, OpGroup, &__td ); - // } - // else { - // DUMP_OBJ_ERROR( aafi, OpGroup, &__td, "Failed parsing parameter" ); - // } - - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_StereoAudioGain)) { - /* Unknown usage and implementation, not encountered yet */ - DUMP_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioPan)) { - /* TODO Should Only be Track-based (first Segment of TimelineMobSlot.) */ - - /* - * We have to loop because of custom Parameters. - * Seen in AVID Media Composer AAFs (test.aaf). TODO ParamDef PanVol_IsTrimGainEffect ? - */ - - aafObject* Param = NULL; - aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); - - if (Parameters == NULL) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Missing PID_OperationGroup_Parameters"); - rc = -1; - goto end; // we still have to parse segments - } - - /* Retrieve AAFParameterDef_Pan parameter */ - - aaf_foreach_ObjectInSet (&Param, Parameters, NULL) - { - aafUID_t* ParamDef = aaf_get_propertyValue (Param, PID_Parameter_Definition, &AAFTypeID_AUID); - - if (aafUIDCmp (ParamDef, &AAFParameterDef_Pan)) - break; - } - - if (Param == NULL) { - DUMP_OBJ_ERROR (aafi, OpGroup, &__td, "Missing Parameter ParameterDef_Amplitude"); - rc = -1; - goto end; // we still have to parse segments - } - - DUMP_OBJ (aafi, OpGroup, &__td); - - __td.ll[__td.lv] = 2; - - rc = parse_Parameter (aafi, Param, &__td); - - // if ( rc == 0 ) { - // DUMP_OBJ( aafi, OpGroup, &__td ); - // } - // else { - // DUMP_OBJ_ERROR( aafi, OpGroup, &__td, "Failed parsing parameter" ); - // } - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioMixdown)) { - DUMP_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); - /* TODO Unknown usage and implementation */ - } else { - DUMP_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); - } - -end: - /* - * Parses Segments in the OperationGroup::InputSegments, only if - * OperationGroup is not a Transition as a Transition has no InputSegments, - * and not an AudioChannelCombiner as they were already parsed. + * This represents an empty space on the timeline, between two clips, + * which is Component::Length long. + * TODO: is realy parent mandatory a Sequence or Selector ? */ - if (aafUIDCmp (OpGroup->Parent->Class->ID, &AAFClassID_Transition) == 0 && - aafUIDCmp (OperationIdentification, &AAFOperationDef_AudioChannelCombiner) == 0) { - aafObject* InputSegment = NULL; - aafObject* InputSegments = aaf_get_propertyValue (OpGroup, PID_OperationGroup_InputSegments, &AAFTypeID_SegmentStrongReferenceVector); + int64_t* length = aaf_get_propertyValue (Filler, PID_Component_Length, &AAFTypeID_LengthType); - int i = 0; - __td.ll[__td.lv] = (InputSegments) ? InputSegments->Header->_entryCount : 0; - - aaf_foreach_ObjectInSet (&InputSegment, InputSegments, NULL) - { - __td.ll[__td.lv] = __td.ll[__td.lv] - i++; - aafi_parse_Segment (aafi, InputSegment, &__td); - } + if (!length) { + TRACE_OBJ_ERROR (aafi, Filler, &__td, "Missing Component::Length"); + return -1; } - /* End of current OperationGroup context. */ - - aafObject* Obj = OpGroup; - for (; Obj != NULL && aafUIDCmp (Obj->Class->ID, &AAFClassID_ContentStorage) == 0; Obj = Obj->Parent) - if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_OperationGroup)) - break; - - if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioGain)) { - if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot)) { - if (aafi->ctx.clips_using_gain == 0) { - aafi_freeAudioGain (aafi->ctx.current_clip_gain); - } - - if (aafi->ctx.clips_using_automation == 0) { - aafi_freeAudioGain (aafi->ctx.current_clip_automation); - } - - /* Clip-based Gain */ - aafi->ctx.current_clip_is_muted = 0; - aafi->ctx.current_clip_gain = NULL; - aafi->ctx.current_clip_automation = NULL; - aafi->ctx.clips_using_gain = 0; - aafi->ctx.clips_using_automation = 0; - } - - // free( aafi->ctx.current_track->gain ); - // aafi->ctx.current_track->gain = NULL; + if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || + aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { + aafi->ctx.current_track->current_pos += *length; + } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || + aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { + aafi->Video->Tracks->current_pos += *length; } - return rc; + TRACE_OBJ (aafi, Filler, &__td); + + return 0; } static int @@ -2231,54 +802,58 @@ parse_SourceClip (AAF_Iface* aafi, aafObject* SourceClip, td* __ptd) struct trace_dump __td; __td_set (__td, __ptd, 1); - __td.hc = 1; // link to MasterMob, SourceMob + aafWeakRef_t* dataDefWeakRef = aaf_get_propertyValue (SourceClip, PID_Component_DataDefinition, &AAFTypeID_DataDefinitionWeakReference); - aafUID_t* DataDefinition = get_Component_DataDefinition (aafi, SourceClip); - - if (DataDefinition == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve DataDefinition"); + if (!dataDefWeakRef) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing Component::DataDefinition."); return -1; } - aafObject* ParentMob = get_Object_Ancestor (aafi, SourceClip, &AAFClassID_Mob); + aafUID_t* DataDefinition = aaf_get_DataIdentificationByWeakRef (aafi->aafd, dataDefWeakRef); - if (ParentMob == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve parent Mob"); + if (!DataDefinition) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve DataDefinition"); + return -1; + } + + aafObject* ParentMob = aaf_get_ObjectAncestor (SourceClip, &AAFClassID_Mob); + + if (!ParentMob) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve parent Mob"); return -1; } aafMobID_t* parentMobID = aaf_get_propertyValue (ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType); - if (parentMobID == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing parent Mob PID_Mob_MobID"); + if (!parentMobID) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing parent Mob::MobID"); return -1; } + aafUID_t* parentMobUsageCode = aaf_get_propertyValue (ParentMob, PID_Mob_UsageCode, &AAFTypeID_UsageType); + + if (!parentMobUsageCode) { + debug ("Missing parent Mob Mob::UsageCode"); + } + aafMobID_t* sourceID = aaf_get_propertyValue (SourceClip, PID_SourceReference_SourceID, &AAFTypeID_MobIDType); - if (sourceID == NULL) { /* opt */ - /* NOTE: PID_SourceReference_SourceID is optionnal, there might be none. */ - // DUMP_OBJ_ERROR( aafi, SourceClip, &__td, "Missing PID_SourceReference_SourceID" ); - // return -1; - } - uint32_t* SourceMobSlotID = aaf_get_propertyValue (SourceClip, PID_SourceReference_SourceMobSlotID, &AAFTypeID_UInt32); - if (SourceMobSlotID == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing PID_SourceReference_SourceMobSlotID"); + if (!SourceMobSlotID) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing SourceReference::SourceMobSlotID"); return -1; } /* - * TODO: handle SourceReference::MonoSourceSlotIDs and associated conditional rules. + * TODO: handle SourceReference::ChannelIDs and SourceReference::MonoSourceSlotIDs * (Multi-channels) */ - aafObject* targetMob = NULL; - aafObject* targetMobSlot = NULL; - aafUID_t* targetMobUsageCode = NULL; + aafObject* targetMob = NULL; + aafObject* targetMobSlot = NULL; - if (sourceID == NULL) { + if (sourceID == NULL || aafMobIDCmp (sourceID, &AAFMOBID_NULL)) { /* * p.49 : To create a SourceReference that refers to a MobSlot within * the same Mob as the SourceReference, omit the SourceID property. @@ -2292,30 +867,30 @@ parse_SourceClip (AAF_Iface* aafi, aafObject* SourceClip, td* __ptd) // sourceID = parentMobID; // targetMob = ParentMob; + + debug ("SourceReference::SourceID is missing or NULL"); } else { targetMob = aaf_get_MobByID (aafi->aafd->Mobs, sourceID); - if (targetMob == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve target Mob by ID : %ls", aaft_MobIDToText (sourceID)); + if (!targetMob) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve target Mob by ID : %s", aaft_MobIDToText (sourceID)); return -1; } - targetMobUsageCode = aaf_get_propertyValue (targetMob, PID_Mob_UsageCode, &AAFTypeID_UsageType); - aafObject* targetMobSlots = aaf_get_propertyValue (targetMob, PID_Mob_Slots, &AAFTypeID_MobSlotStrongReferenceVector); - if (targetMobSlots == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing target Mob PID_Mob_Slots"); + if (!targetMobSlots) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing target Mob::Slots"); return -1; } targetMobSlot = aaf_get_MobSlotBySlotID (targetMobSlots, *SourceMobSlotID); - if (targetMobSlot == NULL) { + if (!targetMobSlot) { /* TODO check if there is a workaround : - * AAFInfo --aaf-clips '/home/agfline/Developpement/libaaf_testfiles/ADP/ADP_STTRACK_CLIPGAIN_TRACKGAIN_XFADE_NOOPTONEXPORT.aaf' + * valgrind --track-origins=yes --leak-check=full ./bin/AAFInfo --trace --aaf-essences --aaf-clips /home/agfline/Programming/libaaf/LibAAF/test/private/aaf/ADP/ADP_STTRACK_CLIPGAIN_TRACKGAIN_XFADE_NOOPTONEXPORT.aaf --verb 3 */ - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve target MobSlot ID : %u", *SourceMobSlotID); + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve target MobSlot ID : %u", *SourceMobSlotID); return -1; } } @@ -2323,360 +898,263 @@ parse_SourceClip (AAF_Iface* aafi, aafObject* SourceClip, td* __ptd) /* *** Clip *** */ if (aafUIDCmp (ParentMob->Class->ID, &AAFClassID_CompositionMob)) { - // DUMP_OBJ( aafi, SourceClip, &__td ); - int64_t* length = aaf_get_propertyValue (SourceClip, PID_Component_Length, &AAFTypeID_LengthType); - if (length == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing PID_Component_Length"); + if (!length) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing Component::Length"); return -1; } int64_t* startTime = aaf_get_propertyValue (SourceClip, PID_SourceClip_StartTime, &AAFTypeID_PositionType); - if (startTime == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing PID_SourceClip_StartTime"); + if (!startTime) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing SourceClip::StartTime"); return -1; } - struct aafiContext ctxBackup; - - aafUID_t* CurrentUsageCode = aaf_get_propertyValue (ParentMob, PID_Mob_UsageCode, &AAFTypeID_UsageType); - - if (CurrentUsageCode == NULL) { - /* NOTE: PID_Mob_UsageCode is optionnal, there might be none. */ - // DUMP_OBJ_ERROR( aafi, SourceClip, &__td, "Missing PID_Mob_UsageCode" ); - // return -1; - } - - // if ( aafUIDCmp( aafi->aafd->Header.OperationalPattern, &AAFOPDef_EditProtocol ) ) - { - // if ( (CurrentUsageCode && aafUIDCmp( CurrentUsageCode, &AAFUsage_SubClip )) || CurrentUsageCode == NULL ) { - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_YELLOW ); - // } - // else { - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_MAGENTA ); - // } - - /* - * If SourceClip points to a CompositionMob instead of a MasterMob, we - * are at the begining (or inside) a derivation chain. - */ - - if (aafUIDCmp (targetMob->Class->ID, &AAFClassID_CompositionMob)) { - DUMP_OBJ (aafi, SourceClip, &__td); - - /* Only to print trace */ - __td.lv++; - DUMP_OBJ (aafi, targetMob, &__td); - // __td.lv++; - - memcpy (&ctxBackup, &(aafi->ctx), sizeof (struct aafiContext)); - - RESET_CONTEXT (aafi->ctx); - - aafi->ctx.current_track = ctxBackup.current_track; - aafi->ctx.is_inside_derivation_chain = 1; - - parse_MobSlot (aafi, targetMobSlot, &__td); - - void* new_clip = aafi->ctx.current_clip; - - memcpy (&(aafi->ctx), &ctxBackup, sizeof (struct aafiContext)); - - if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { - aafi->ctx.current_clip = (aafiAudioClip*)new_clip; - - if (new_clip && aafUIDCmp (CurrentUsageCode, &AAFUsage_TopLevel)) { - /* - * All derivation chain calls ended. - * - * We came back at level zero of parse_SourceClip() nested calls, so - * the clip and its source was added, we only have to set its length, - * offset and gain with correct values. - * - * TODO: aafi->current_clip pointer to new_clip instead ? - */ - - ((aafiAudioClip*)new_clip)->len = (aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : *length; - ((aafiAudioClip*)new_clip)->essence_offset = *startTime; - ((aafiAudioClip*)new_clip)->gain = aafi->ctx.current_clip_gain; - ((aafiAudioClip*)new_clip)->automation = aafi->ctx.current_clip_automation; - ((aafiAudioClip*)new_clip)->mute = aafi->ctx.current_clip_is_muted; - aafi->ctx.clips_using_gain++; - aafi->ctx.clips_using_automation++; - - aafi->ctx.current_track->current_pos += ((aafiAudioClip*)new_clip)->len; - } - } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { - if (new_clip && aafUIDCmp (CurrentUsageCode, &AAFUsage_TopLevel)) { - /* - * All derivation chain calls ended. - * - * We came back at level zero of parse_SourceClip() nested calls, so - * the clip and its source was added, we only have to set its length, - * offset and gain with correct values. - */ - - ((aafiVideoClip*)new_clip)->len = (aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : *length; - ((aafiVideoClip*)new_clip)->essence_offset = *startTime; - - aafi->Video->Tracks->current_pos += ((aafiVideoClip*)new_clip)->len; - } - } - - return 0; - - } else if (aafUIDCmp (targetMob->Class->ID, &AAFClassID_MasterMob)) { - /* - * We are inside the derivation chain and we reached the SourceClip - * pointing to MasterMob (the audio essence). - * - * Thus, we can add the clip and parse the audio essence normaly. - */ - } - } - if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { - // if ( *length == 1 ) { - // /* - // * If length equals 1 EditUnit, the clip is probably a padding for "Media Composer Compatibility". - // * Therefore, we don't need it. - // * - // * TODO BUT this could also be some rendered fade.. we should find a way to distinguish between the two. - // */ - // - // // aaf_dump_ObjectProperties( aafi->aafd, SourceClip ); - // - // warning( "Got a 1 EU length clip, probably some NLE compatibility padding : Skipping." ); - // - // - // - // if ( aafi->ctx.current_track_is_multichannel == 0 ) { - // aafi->ctx.current_pos += *length; - // } - // else { - // aafi->ctx.current_multichannel_track_clip_length = *length; - // } - // - // return -1; - // } - - if (aafi->ctx.current_clip_is_combined && - aafi->ctx.current_combined_clip_channel_num > 0) { - /* - * Parsing multichannel audio clip (AAFOperationDef_AudioChannelCombiner) - * We already parsed first SourceClip in AAFOperationDef_AudioChannelCombiner. - * We just have to check everything match for all clips left (each clip represents a channel) - */ - - if (aafi->ctx.current_combined_clip_forced_length == 0 && aafi->ctx.current_clip->len != *length) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "SourceClip length does not match first one in AAFOperationDef_AudioChannelCombiner"); - return -1; - } - - if (aafMobIDCmp (aafi->ctx.current_clip->essencePointerList->essence->masterMobID, sourceID)) { + if (aafi->ctx.TopLevelCompositionMob == ParentMob /*!parentMobUsageCode || aafUIDCmp( parentMobUsageCode, &AAFUsage_TopLevel )*/) { + if (aafi->ctx.current_clip_is_combined && + aafi->ctx.current_combined_clip_channel_num > 0) { /* - * Clip channel rely on the same audio file source (single multichannel file) + * Parsing multichannel audio clip (AAFOperationDef_AudioChannelCombiner) + * We already parsed the first SourceClip in AAFOperationDef_AudioChannelCombiner. + * We just have to check everything match for all clips left (each clip represents a channel) * - * Assume that all clip channels will point to the same multichannel essence file, in the right order. - * (Davinci Resolve multichannel clips) + │ 02277│ ├──◻ AAFClassID_OperationGroup (OpIdent: AAFOperationDef_AudioChannelCombiner; Length: 517207) + │ 02816│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02821│ │ │ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : 7 + │ 04622│ │ │ └──◻ AAFClassID_TimelineMobSlot [slot:1 track:1] (DataDef : AAFDataDef_Sound) + │ 03185│ │ │ └──◻ AAFClassID_SourceClip (Length: 523723) + │ 04346│ │ │ └──◻ AAFClassID_SourceMob (UsageCode: n/a) : 7 + │ 01393│ │ │ └──◻ AAFClassID_WAVEDescriptor + │ 01532│ │ │ └──◻ AAFClassID_NetworkLocator : file://localhost/C:/Users/user/Desktop/res/7.1-SMPTE-channel-identif.wav + │ │ │ │ + │ 02666│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02666│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02666│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02666│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02666│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02666│ │ ├──◻ AAFClassID_SourceClip (Length: 516000) + │ 02666│ │ └──◻ AAFClassID_SourceClip (Length: 516000) */ - aafi->ctx.current_clip->essencePointerList->essenceChannel = 0; + if (aafi->ctx.current_combined_clip_forced_length == 0 && + aafi->ctx.current_clip->len != *length) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "SourceClip length does not match first one in AAFOperationDef_AudioChannelCombiner"); + return -1; + } - DUMP_OBJ (aafi, SourceClip, &__td); - return 0; + if (targetMob && !aafUIDCmp (targetMob->Class->ID, &AAFClassID_MasterMob)) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Multichannel-combined SourceClip does not target a MasterMob: %s", aaft_ClassIDToText (aafi->aafd, targetMob->Class->ID)); + return -1; + } + + if (aafMobIDCmp (aafi->ctx.current_clip->essencePointerList->essenceFile->masterMobID, sourceID) && + aafi->ctx.current_clip->essencePointerList->essenceFile->masterMobSlotID == *SourceMobSlotID) { + /* + * Clip channel rely on the same audio file source (single multichannel file) + * + * Assume that all clip channels will point to the same multichannel essence file, in the right order. + * (Davinci Resolve multichannel clips) + */ + + aafi->ctx.current_clip->essencePointerList->essenceChannel = 0; + + TRACE_OBJ_INFO (aafi, SourceClip, &__td, "Ignore parsing of clip channel %i pointing to the same audio source file", aafi->ctx.current_combined_clip_channel_num + 1); + return 0; + } } - } - aafiAudioClip* audioClip = NULL; + if (!aafi->ctx.current_clip_is_combined || + (aafi->ctx.current_clip_is_combined && aafi->ctx.current_combined_clip_channel_num == 0)) { + /* + * Create new clip, only if we are parsing a single mono clip, or if + * we are parsing the first SourceClip describing the first channel of + * a multichannel clip inside an AAFOperationDef_AudioChannelCombiner + */ - if (!aafi->ctx.current_clip_is_combined || (aafi->ctx.current_clip_is_combined && aafi->ctx.current_combined_clip_channel_num == 0)) { - /* - * Create new clip, only if we are parsing a single mono clip, or if - * we are parsing the first SourceClip describing a multichannel clip - * inside an AAFOperationDef_AudioChannelCombiner + aafiAudioClip* audioClip = aafi_newAudioClip (aafi, aafi->ctx.current_track); + + aafiTimelineItem* timelineItem = audioClip->timelineItem; + + timelineItem->pos = aafi->ctx.current_track->current_pos; + timelineItem->len = (aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : *length; + + audioClip->gain = aafi->ctx.current_clip_gain; + audioClip->automation = aafi->ctx.current_clip_variable_gain; + audioClip->mute = aafi->ctx.current_clip_is_muted; + audioClip->pos = aafi->ctx.current_track->current_pos; + + if (aafi->ctx.avid_warp_clip_edit_rate) { + audioClip->essence_offset = aafi_convertUnit (*startTime, aafi->ctx.avid_warp_clip_edit_rate, aafi->ctx.current_track->edit_rate); + audioClip->len = aafi_convertUnit ((aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : *length, aafi->ctx.avid_warp_clip_edit_rate, aafi->ctx.current_track->edit_rate); + } else { + audioClip->essence_offset = *startTime; + audioClip->len = (aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : *length; + } + + aafi->ctx.current_track->current_pos += audioClip->len; + aafi->ctx.current_track->clipCount++; + + aafi->ctx.current_clip_gain_is_used++; + aafi->ctx.current_clip_variable_gain_is_used++; + + /* + * ComponentAttributeList is non-standard, but used by Avid Media Composer + * and Davinci Resolve to attach Clip Notes. + */ + + void* ComponentAttributeList = aaf_get_propertyValue (SourceClip, aaf_get_PropertyIDByName (aafi->aafd, "ComponentAttributeList"), &AAFTypeID_TaggedValueStrongReferenceVector); + + if (ComponentAttributeList) { + char* comment = aaf_get_TaggedValueByName (aafi->aafd, ComponentAttributeList, "_COMMENT", &AAFTypeID_String); + + if (comment) { + aafiMetaData* meta = aafi_newMetadata (aafi, &audioClip->metadata); + + if (!meta) { + warning ("Could not create new Metadata."); + } else { + meta->text = comment; + meta->name = laaf_util_c99strdup ("_COMMENT"); + + if (!meta->name) { + error ("Could not duplicate meta name : %s", "_COMMENT"); + aafiMetaData* tmp = meta->next; + aafi_freeMetadata (&meta); + audioClip->metadata = tmp; + } + } + } + } + + aafi->ctx.current_clip = audioClip; + } + + if (aafi->ctx.current_clip_is_combined == 0) { + if (aafi->ctx.current_track->format != AAFI_TRACK_FORMAT_NOT_SET && + aafi->ctx.current_track->format != AAFI_TRACK_FORMAT_MONO) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Track format (%u) does not match current clip (%u)", aafi->ctx.current_track->format, AAFI_TRACK_FORMAT_MONO); + } else { + aafi->ctx.current_track->format = AAFI_TRACK_FORMAT_MONO; + } + } + } else if (aafUIDCmp (parentMobUsageCode, &AAFUsage_SubClip)) { + /* Exemple of AAFUsage_SubClip in ../test/private/aaf/AAF/E2R_52min/224E2R190008_ENQUETES_DE_REGION_N32_LA_SECHERESSE_UNE_FATALITE.aaf + * TODO: Looks like a sub-clip is just used to reference an existing clip, but to show it in UI with a different name. + * It seems that sub-clip length always matches MasterMob > SourceLip length + * Therefore, we should only parse its name. + * + │ 02709││ ├──◻ AAFClassID_SourceClip (Length: 183) + │ 02723││ │ └──◻ AAFClassID_CompositionMob (UsageCode: AAFUsage_SubClip) : plato 8 1ere.Copy.01.new.06 (MetaProps: SubclipBegin[0xfff6] SubclipFullLength[0xfff7] MobAttributeList[0xfff9]) + │ 04478││ │ └──◻ AAFClassID_TimelineMobSlot [slot:2 track:2] (DataDef : AAFDataDef_Sound) + │ 02978││ │ └──◻ AAFClassID_SourceClip (Length: 681) + │ 02983││ │ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : FTVHD-X400-0946.new.06 (MetaProps: MobAttributeList[0xfff9] ConvertFrameRate[0xfff8]) + │ 04561││ │ └──◻ AAFClassID_TimelineMobSlot [slot:2 track:2] (DataDef : AAFDataDef_Sound) : FTVHD-X400-0946 + │ 03188││ │ └──◻ AAFClassID_SourceClip (Length: 681) + │ 04305││ │ └──◻ AAFClassID_SourceMob (UsageCode: n/a) : FTVHD-X400-0946.PHYS (MetaProps: MobAttributeList[0xfff9]) + │ 01342││ │ └──◻ AAFClassID_PCMDescriptor (MetaProps: DataOffset[0xffde]) */ - aafiTimelineItem* item = aafi_newTimelineItem (aafi, aafi->ctx.current_track, AAFI_AUDIO_CLIP); + aafi->ctx.current_clip->subClipName = aaf_get_propertyValue (ParentMob, PID_Mob_Name, &AAFTypeID_String); - audioClip = item->data; //(aafiAudioClip*)&item->data; - - aafi->ctx.clips_using_gain++; - aafi->ctx.clips_using_automation++; - audioClip->gain = aafi->ctx.current_clip_gain; - audioClip->automation = aafi->ctx.current_clip_automation; - audioClip->mute = aafi->ctx.current_clip_is_muted; - audioClip->pos = aafi->ctx.current_track->current_pos; - audioClip->len = (aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : *length; - - audioClip->essence_offset = *startTime; - - aafi->ctx.current_clip = audioClip; - } else { - /* clip is multichannel and we are parsing SourceClip channel > first channel */ - audioClip = aafi->ctx.current_clip; - } - - if (!aafi->ctx.is_inside_derivation_chain && - (!aafi->ctx.current_clip_is_combined || (aafi->ctx.current_clip_is_combined && aafi->ctx.current_combined_clip_channel_num == 0))) { - /* - * We update ONLY ONCE when SourceClip belongs to a OpGroup AAFOperationDef_AudioChannelCombiner. - * - * We DO NOT update current pos when SourceClip belongs to a sub CompositionMob - * because in that case, current pos was already updated by initial SourceClip - * pointing to AAFClassID_CompositionMob - -04606│├──◻ AAFClassID_TimelineMobSlot [slot:16 track:8] (DataDef : AAFDataDef_LegacySound) -02064││ └──◻ AAFClassID_Sequence -02037││ ├──◻ AAFClassID_Filler - ││ │ -02502││ ├──◻ AAFClassID_OperationGroup (OpIdent: AAFOperationDef_MonoAudioGain) (MetaProps: ComponentAttributeList[0xffcc]) -03780││ │ ├──◻ AAFClassID_ConstantValue -POS UPDATED HERE --> └──◻ AAFClassID_SourceClip -02842││ │ └──◻ AAFClassID_CompositionMob (UsageCode: AAFUsage_AdjustedClip) : Islamic Call to Prayer - Amazing Adhan by Edris Aslami.mp3.new.01 (MetaProps: MobAttributeList[0xfff9] ConvertFrameRate[0xfff8]) -04606││ │ └──◻ AAFClassID_TimelineMobSlot [slot:2 track:2] (DataDef : AAFDataDef_LegacySound) -02502││ │ └──◻ AAFClassID_OperationGroup (OpIdent: AAFOperationDef_MonoAudioGain) -03780││ │ ├──◻ AAFClassID_ConstantValue -POS NOT UPDATED HERE ------------------> └──◻ AAFClassID_SourceClip -03085││ │ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : Islamic Call to Prayer - Amazing Adhan by Edris Aslami.mp3.new.01 (MetaProps: AppCode[0xfffa]) -04705││ │ └──◻ AAFClassID_TimelineMobSlot -03305││ │ └──◻ AAFClassID_SourceClip -04412││ │ └──◻ AAFClassID_SourceMob (UsageCode: n/a) : Islamic Call to Prayer - Amazing Adhan by Edris Aslami.mp3 (MetaProps: MobAttributeList[0xfff9]) -01400││ │ └──◻ AAFClassID_WAVEDescriptor -01555││ │ └──◻ AAFClassID_NetworkLocator : file:///MEDIA2/2199_Rapport_Astellas Main Content/audio/AX TEST.aaf - - */ - - aafi->ctx.current_track->current_pos += (aafi->ctx.current_combined_clip_forced_length) ? aafi->ctx.current_combined_clip_forced_length : audioClip->len; - } - - if (aafi->ctx.current_clip_is_combined == 0) { - if (aafi->ctx.current_track->format != AAFI_TRACK_FORMAT_NOT_SET && - aafi->ctx.current_track->format != AAFI_TRACK_FORMAT_MONO) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Track format (%u) does not match current clip (%u)", aafi->ctx.current_track->format, AAFI_TRACK_FORMAT_MONO); - } else { - aafi->ctx.current_track->format = AAFI_TRACK_FORMAT_MONO; + if (!aafi->ctx.current_clip->subClipName) { + debug ("Missing parent Mob::Name (sub-clip name)"); } + + aafObject* UserComments = aaf_get_propertyValue (ParentMob, PID_Mob_UserComments, &AAFTypeID_TaggedValueStrongReferenceVector); + + if (retrieve_UserComments (aafi, UserComments, &aafi->ctx.current_clip->metadata) < 0) { + warning ("Error parsing parent Mob::UserComments"); + } + } else if (aafUIDCmp (parentMobUsageCode, &AAFUsage_AdjustedClip)) { + // if ( aafi->ctx.current_adjusted_clip_gain ) { + // applyGainOffset( aafi, &aafi->ctx.current_clip->gain, aafi->ctx.current_adjusted_clip_gain ); + // aafi_freeAudioGain( aafi->ctx.current_adjusted_clip_gain ); + // aafi->ctx.current_adjusted_clip_gain = NULL; + // } + } else if (!parentMobUsageCode) { + debug ("CompositionMob UsageCode is NULL. Keep on parsing..."); + } else { + debug ("Unsupported CompositionMob UsageCode: %s", aaft_UsageCodeToText (parentMobUsageCode)); + TRACE_OBJ_NO_SUPPORT (aafi, SourceClip, &__td); + return -1; } - if (aafUIDCmp (targetMob->Class->ID, &AAFClassID_MasterMob)) { - if (targetMobSlot == NULL) { - /* TODO isn't it already checked above ? */ - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing target MobSlot"); + if (targetMob && aafUIDCmp (targetMob->Class->ID, &AAFClassID_MasterMob)) { + if (!targetMobSlot) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing target MobSlot"); return -1; } - DUMP_OBJ (aafi, SourceClip, &__td); + TRACE_OBJ (aafi, SourceClip, &__td); - /* Only to print trace */ __td.lv++; - DUMP_OBJ (aafi, targetMob, &__td); + TRACE_OBJ (aafi, targetMob, &__td); - memcpy (&ctxBackup, &(aafi->ctx), sizeof (struct aafiContext)); - - /* TODO: Commented out to avoid reset of ctx.current_clip_is_combined */ - // RESET_CONTEXT( aafi->ctx ); - - aafi->ctx.current_track = ctxBackup.current_track; - aafi->ctx.current_clip = audioClip; - - /* retrieve essence */ parse_MobSlot (aafi, targetMobSlot, &__td); + } else if (targetMob && aafUIDCmp (targetMob->Class->ID, &AAFClassID_CompositionMob)) { + /* + * If SourceClip points to a CompositionMob instead of a MasterMob, we + * are at the begining (or inside) a derivation chain. + */ - memcpy (&(aafi->ctx), &ctxBackup, sizeof (struct aafiContext)); + TRACE_OBJ (aafi, SourceClip, &__td); + + __td.lv++; + TRACE_OBJ (aafi, targetMob, &__td); + + parse_MobSlot (aafi, targetMobSlot, &__td); } else { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Targeted Mob isn't MasterMob : %ls", aaft_ClassIDToText (aafi->aafd, targetMob->Class->ID)); + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Targeted Mob no supported: %s", aaft_ClassIDToText (aafi->aafd, targetMob->Class->ID)); return -1; } } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { - /* - * │ 04382│├──◻ AAFClassID_TimelineMobSlot [slot:2 track:1] (DataDef : AAFDataDef_Picture) - * │ 01939││ └──◻ AAFClassID_Sequence - * │ 03007││ └──◻ AAFClassID_SourceClip - */ + if (aafi->ctx.TopLevelCompositionMob != ParentMob) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Current implementation does not support parsing video SourceClip out of TopLevel CompositionMob"); + return -1; + } - /* - * │ 04390│└──◻ AAFClassID_TimelineMobSlot [slot:8 track:1] (DataDef : AAFDataDef_LegacyPicture) : Video Mixdown - * │ 03007│ └──◻ AAFClassID_SourceClip - */ - - if (aafi->Video->Tracks->Items) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Current implementation supports only one video clip"); + if (aafi->Video->Tracks->timelineItems) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Current implementation supports only one video clip"); return -1; } /* Add the new clip */ - aafiTimelineItem* item = aafi_newTimelineItem (aafi, aafi->Video->Tracks, AAFI_VIDEO_CLIP); + aafiVideoClip* videoClip = aafi_newVideoClip (aafi, aafi->Video->Tracks); - aafiVideoClip* videoClip = item->data; //(aafiVideoClip*)&item->data; + aafiTimelineItem* timelineItem = videoClip->timelineItem; - videoClip->pos = aafi->Video->Tracks->current_pos; - videoClip->len = *length; + timelineItem->pos = aafi->Video->Tracks->current_pos; + timelineItem->len = *length; + videoClip->pos = aafi->Video->Tracks->current_pos; + videoClip->len = *length; videoClip->essence_offset = *startTime; - /* - * p.49 : To create a SourceReference that refers to a MobSlot within - * the same Mob as the SourceReference, omit the SourceID property. - * - * NOTE: This should not happen here because The "CompositionMob > SourceClip::SourceID" - * should always point to the corresponding "MasterMob", that is a different Mob. - */ - - videoClip->masterMobID = sourceID; - - // if ( videoClip->masterMobID == NULL ) { - // videoClip->masterMobID = aaf_get_propertyValue( ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType ); - // warning( "Missing SourceReference::SourceID, retrieving from parent Mob." ); - // } - - if (!aafUIDCmp (aafi->aafd->Header.OperationalPattern, &AAFOPDef_EditProtocol) || - aafUIDCmp (CurrentUsageCode, &AAFUsage_TopLevel)) { - /* - * NOTE for AAFOPDef_EditProtocol only : - * - * If SourceClip belongs to a TopLevel Mob, we can update position. - * Otherwise, it means we are inside a derivation chain ( ie: TopLevelCompositionMob -> SourceClip -> SubLevel:CompositionMob -> SourceClip ) - * and the clip length is not the good one. In that case, position is updated above. - */ - - aafi->Video->Tracks->current_pos += videoClip->len; - } + aafi->Video->Tracks->current_pos += videoClip->len; aafi->ctx.current_video_clip = videoClip; - if (aafUIDCmp (targetMob->Class->ID, &AAFClassID_MasterMob)) { - if (targetMobSlot == NULL) { - /* TODO isn't it already checked above ? */ - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Missing target MobSlot"); + if (targetMob && aafUIDCmp (targetMob->Class->ID, &AAFClassID_MasterMob)) { + if (!targetMobSlot) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing target MobSlot"); return -1; } - DUMP_OBJ (aafi, SourceClip, &__td); + TRACE_OBJ (aafi, SourceClip, &__td); - /* Only to print trace */ __td.lv++; - DUMP_OBJ (aafi, targetMob, &__td); - - // memcpy( &ctxBackup, &(aafi->ctx), sizeof(struct aafiContext) ); - // - // RESET_CONTEXT( aafi->ctx ); + TRACE_OBJ (aafi, targetMob, &__td); parse_MobSlot (aafi, targetMobSlot, &__td); - - // memcpy( &(aafi->ctx), &ctxBackup, sizeof(struct aafiContext) ); - } else { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Targeted mob isn't MasterMob : %ls", aaft_ClassIDToText (aafi->aafd, targetMob->Class->ID)); - // parse_CompositionMob( ) + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Current implementation does not support video SourceClip not targetting a MasterMob: %s", (targetMob) ? aaft_ClassIDToText (aafi->aafd, targetMob->Class->ID) : "[MISSING TARGET MOB]"); return -1; } } @@ -2687,15 +1165,15 @@ POS NOT UPDATED HERE ------------------> └──◻ AAFClassID_SourceClip else if (aafUIDCmp (ParentMob->Class->ID, &AAFClassID_MasterMob)) { aafMobID_t* masterMobID = aaf_get_propertyValue (ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType); - if (masterMobID == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve parent Mob PID_Mob_MobID"); + if (!masterMobID) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Missing parent Mob::MobID"); return -1; } - aafObject* ParentMobSlot = get_Object_Ancestor (aafi, SourceClip, &AAFClassID_MobSlot); + aafObject* ParentMobSlot = aaf_get_ObjectAncestor (SourceClip, &AAFClassID_MobSlot); - if (ParentMobSlot == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve parent MobSlot"); + if (!ParentMobSlot) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve parent MobSlot"); return -1; } @@ -2706,7 +1184,7 @@ POS NOT UPDATED HERE ------------------> └──◻ AAFClassID_SourceClip if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { if (!aafi->ctx.current_clip) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "aafi->ctx.current_clip not set"); + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "aafi->ctx.current_clip not set"); return -1; } @@ -2714,292 +1192,361 @@ POS NOT UPDATED HERE ------------------> └──◻ AAFClassID_SourceClip * Check if this Essence has already been retrieved */ - aafiAudioEssence* audioEssence = NULL; + aafiAudioEssenceFile* audioEssenceFile = NULL; - foreachEssence (audioEssence, aafi->Audio->Essences) + AAFI_foreachAudioEssenceFile (aafi, audioEssenceFile) { - if (aafMobIDCmp (audioEssence->sourceMobID, sourceID) && audioEssence->sourceMobSlotID == (unsigned)*SourceMobSlotID) { + if (aafMobIDCmp (audioEssenceFile->sourceMobID, sourceID) && audioEssenceFile->sourceMobSlotID == (unsigned)*SourceMobSlotID) { __td.eob = 1; - DUMP_OBJ_WARNING (aafi, SourceClip, &__td, "Essence already parsed: Linking with %ls", audioEssence->file_name); - - aafi->ctx.current_clip->essencePointerList = aafi_newAudioEssencePointer (aafi, &aafi->ctx.current_clip->essencePointerList, audioEssence, essenceChannelNum); + TRACE_OBJ_INFO (aafi, SourceClip, &__td, "Essence already parsed: Linking with %s", audioEssenceFile->name); + aafi->ctx.current_clip->essencePointerList = aafi_newAudioEssencePointer (aafi, &aafi->ctx.current_clip->essencePointerList, audioEssenceFile, essenceChannelNum); return 0; } } /* new Essence, carry on. */ - audioEssence = aafi_newAudioEssence (aafi); + audioEssenceFile = aafi_newAudioEssence (aafi); - audioEssence->masterMobSlotID = *masterMobSlotID; - audioEssence->masterMobID = masterMobID; - audioEssence->file_name = aaf_get_propertyValue (ParentMob, PID_Mob_Name, &AAFTypeID_String); + audioEssenceFile->masterMobSlotID = *masterMobSlotID; + audioEssenceFile->masterMobID = masterMobID; + audioEssenceFile->name = aaf_get_propertyValue (ParentMob, PID_Mob_Name, &AAFTypeID_String); - if (audioEssence->file_name == NULL) { - debug ("Missing MasterMob::PID_Mob_Name (essence file name)"); + if (audioEssenceFile->name == NULL) { + debug ("Missing parent Mob::Name (essence file name)"); } - /* - * p.49 : « To create a SourceReference that refers to a MobSlot within - * the same Mob as the SourceReference, omit the SourceID property. » - */ + audioEssenceFile->sourceMobSlotID = *SourceMobSlotID; + audioEssenceFile->sourceMobID = sourceID; - audioEssence->sourceMobSlotID = *SourceMobSlotID; - audioEssence->sourceMobID = sourceID; + aafObject* SourceMob = aaf_get_MobByID (aafi->aafd->Mobs, audioEssenceFile->sourceMobID); - // if ( audioEssence->sourceMobID == NULL ) { - // audioEssence->sourceMobID = aaf_get_propertyValue( ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType ); - // warning( "Could not retrieve SourceReference::SourceID, retrieving from parent Mob." ); - // } - - aafi->ctx.current_essence = audioEssence; - - DUMP_OBJ (aafi, SourceClip, &__td); - - aafObject* SourceMob = aaf_get_MobByID (aafi->aafd->Mobs, audioEssence->sourceMobID); - - if (SourceMob == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve SourceMob by ID : %ls", aaft_MobIDToText (audioEssence->sourceMobID)); + if (!SourceMob) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve SourceMob by ID : %s", aaft_MobIDToText (audioEssenceFile->sourceMobID)); return -1; } - audioEssence->SourceMob = SourceMob; + aafi->ctx.current_audio_essence = audioEssenceFile; - aafObject* EssenceData = get_EssenceData_By_MobID (aafi, audioEssence->sourceMobID); + void* MobUserComments = aaf_get_propertyValue (ParentMob, PID_Mob_UserComments, &AAFTypeID_TaggedValueStrongReferenceVector); + + if (retrieve_UserComments (aafi, MobUserComments, &audioEssenceFile->metadata) < 0) { + TRACE_OBJ_WARNING (aafi, SourceClip, &__td, "Error parsing parent Mob::UserComments"); + } else { + TRACE_OBJ (aafi, SourceClip, &__td); + } + + audioEssenceFile->SourceMob = SourceMob; + + aafObject* EssenceData = aaf_get_EssenceDataByMobID (aafi->aafd, audioEssenceFile->sourceMobID); if (EssenceData) __td.ll[__td.lv] = 2; - parse_SourceMob (aafi, SourceMob, &__td); + parse_Mob (aafi, SourceMob, &__td); - __td.ll[__td.lv] = 0; + if (EssenceData) + __td.ll[__td.lv] = 1; - if (EssenceData == NULL) { - /* - * It means essence is not embedded. - */ - // return -1; - } else { + if (EssenceData) { + /* If EssenceData was found, it means essence is embedded */ parse_EssenceData (aafi, EssenceData, &__td); + __td.ll[__td.lv] = 0; } - audioEssence->unique_file_name = build_unique_audiofilename (aafi, audioEssence); + aafi_build_unique_audio_essence_name (aafi, audioEssenceFile); - aafi->ctx.current_clip->essencePointerList = aafi_newAudioEssencePointer (aafi, &aafi->ctx.current_clip->essencePointerList, audioEssence, essenceChannelNum); + aafi->ctx.current_clip->essencePointerList = aafi_newAudioEssencePointer (aafi, &aafi->ctx.current_clip->essencePointerList, audioEssenceFile, essenceChannelNum); + aafi->ctx.current_audio_essence = NULL; } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { - /* - * │ 04382│├──◻ AAFClassID_TimelineMobSlot [slot:2 track:1] (DataDef : AAFDataDef_Picture) - * │ 01939││ └──◻ AAFClassID_Sequence - * │ 03007││ └──◻ AAFClassID_SourceClip - * │ 03012││ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : sample@29 - * │ 04402││ └──◻ AAFClassID_TimelineMobSlot - * │ 03234││ └──◻ AAFClassID_SourceClip - */ - - /* - * │ 04390│└──◻ AAFClassID_TimelineMobSlot [slot:8 track:1] (DataDef : AAFDataDef_LegacyPicture) : Video Mixdown - * │ 03007│ └──◻ AAFClassID_SourceClip - * │ 03012│ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : 2975854 - PREPARATIFS DISPOSITIF 2 30.Exported.01,Video Mixdown,5 (MetaProps: ConvertFrameRate[0xfff8]) - * │ 04410│ └──◻ AAFClassID_TimelineMobSlot - * │ 03242│ └──◻ AAFClassID_SourceClip - */ - - /* Check if this Essence has already been retrieved */ - - // int slotID = MobSlot->Entry->_localKey; - - // aafObject *Obj = aaf_get_MobByID( aafi->aafd, sourceID ); - // debug( "SourceMobID : %ls", aaft_MobIDToText(sourceID) ); - // debug( "MasterMobID : %ls", aaft_MobIDToText(mobID) ); - if (!aafi->ctx.current_video_clip) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "aafi->ctx.current_video_clip not set"); + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "aafi->ctx.current_video_clip not set"); return -1; } - aafiVideoEssence* videoEssence = NULL; + /* + * Check if this Essence has already been retrieved + */ - foreachEssence (videoEssence, aafi->Video->Essences) + aafiVideoEssence* videoEssenceFile = NULL; + + AAFI_foreachVideoEssence (aafi, videoEssenceFile) { - if (aafMobIDCmp (videoEssence->sourceMobID, sourceID) && videoEssence->sourceMobSlotID == (unsigned)*SourceMobSlotID) { - /* Essence already retrieved */ - aafi->ctx.current_video_clip->Essence = videoEssence; - __td.eob = 1; - DUMP_OBJ_INFO (aafi, SourceClip, &__td, "Essence already parsed: Linking with %ls", videoEssence->file_name); + if (aafMobIDCmp (videoEssenceFile->sourceMobID, sourceID) && videoEssenceFile->sourceMobSlotID == (unsigned)*SourceMobSlotID) { + __td.eob = 1; + TRACE_OBJ_INFO (aafi, SourceClip, &__td, "Essence already parsed: Linking with %s", videoEssenceFile->name); + aafi->ctx.current_video_clip->Essence = videoEssenceFile; return 0; } } /* new Essence, carry on. */ - videoEssence = aafi_newVideoEssence (aafi); + videoEssenceFile = aafi_newVideoEssence (aafi); - aafi->ctx.current_video_clip->Essence = videoEssence; + aafi->ctx.current_video_clip->Essence = videoEssenceFile; - videoEssence->masterMobSlotID = *masterMobSlotID; - videoEssence->masterMobID = masterMobID; + videoEssenceFile->masterMobSlotID = *masterMobSlotID; + videoEssenceFile->masterMobID = masterMobID; + videoEssenceFile->name = aaf_get_propertyValue (ParentMob, PID_Mob_Name, &AAFTypeID_String); - videoEssence->file_name = aaf_get_propertyValue (ParentMob, PID_Mob_Name, &AAFTypeID_String); - - if (videoEssence->file_name == NULL) { - debug ("Missing MasterMob::PID_Mob_Name (essence file name)"); + if (videoEssenceFile->name == NULL) { + debug ("Missing parent Mob::Name (essence file name)"); } - /* - * p.49 : To create a SourceReference that refers to a MobSlot within - * the same Mob as the SourceReference, omit the SourceID property. - */ + videoEssenceFile->sourceMobSlotID = *SourceMobSlotID; + videoEssenceFile->sourceMobID = sourceID; - videoEssence->sourceMobSlotID = *SourceMobSlotID; - videoEssence->sourceMobID = sourceID; + TRACE_OBJ (aafi, SourceClip, &__td); - // if ( audioEssence->sourceMobID == NULL ) { - // audioEssence->sourceMobID = aaf_get_propertyValue( ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType ); - // warning( "Could not retrieve SourceReference::SourceID, retrieving from parent Mob." ); - // } + aafObject* SourceMob = aaf_get_MobByID (aafi->aafd->Mobs, videoEssenceFile->sourceMobID); - DUMP_OBJ (aafi, SourceClip, &__td); - - aafObject* SourceMob = aaf_get_MobByID (aafi->aafd->Mobs, videoEssence->sourceMobID); - - if (SourceMob == NULL) { - DUMP_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve SourceMob by ID : %ls", aaft_MobIDToText (videoEssence->sourceMobID)); + if (!SourceMob) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not retrieve SourceMob by ID : %s", aaft_MobIDToText (videoEssenceFile->sourceMobID)); return -1; } - videoEssence->SourceMob = SourceMob; + videoEssenceFile->SourceMob = SourceMob; - aafObject* EssenceData = get_EssenceData_By_MobID (aafi, videoEssence->sourceMobID); + aafi->ctx.current_video_essence = videoEssenceFile; - if (EssenceData) - __td.ll[__td.lv] = 2; + aafObject* EssenceData = aaf_get_EssenceDataByMobID (aafi->aafd, videoEssenceFile->sourceMobID); - aafi->ctx.current_video_essence = videoEssence; + parse_Mob (aafi, SourceMob, &__td); - parse_SourceMob (aafi, SourceMob, &__td); - - __td.ll[__td.lv] = 0; - - if (EssenceData == NULL) { + if (EssenceData) { /* - * It means essence is not embedded. + * It means essence is embedded, otherwise it's not. */ - // return -1; - } else { parse_EssenceData (aafi, EssenceData, &__td); } - videoEssence->unique_file_name = build_unique_videofilename (aafi, videoEssence); + /* + * No need to check for uniqueness, current version supports only one video clip. + */ + videoEssenceFile->unique_name = laaf_util_c99strdup (videoEssenceFile->name); - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_MAGENTA ); + if (!videoEssenceFile->unique_name) { + TRACE_OBJ_ERROR (aafi, SourceClip, &__td, "Could not duplicate video essence unique name : %s", videoEssenceFile->name); + return -1; + } - // debug( "Master MOB SOURCE CLIP" ); - // - // aafiVideoEssence *videoEssence = aafi_newVideoEssence( aafi ); - // - // aafi->ctx.current_essence = (aafiVideoEssence*)videoEssence; - // - // - // videoEssence->file_name = aaf_get_propertyValue( /*aafi->ctx.*/ParentMob, PID_Mob_Name, &AAFTypeID_String ); - // - // - // videoEssence->masterMobID = aaf_get_propertyValue( /*aafi->ctx.*/ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType ); - // - // if ( videoEssence->masterMobID == NULL ) { - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_RED ); - // error( "Could not retrieve Mob::MobID." ); - // return -1; - // } - // - // /* - // * p.49 : To create a SourceReference that refers to a MobSlot within - // * the same Mob as the SourceReference, omit the SourceID property. - // */ - // - // videoEssence->sourceMobID = SourceID; //aaf_get_propertyValue( SourceClip, PID_SourceReference_SourceID, &AAFTypeID_MobIDType ); - // - // if ( videoEssence->sourceMobID == NULL ) { - // // aafObject *Mob = NULL; - // // - // // for ( Mob = SourceClip; Mob != NULL; Mob = Mob->Parent ) { - // // if ( aafUIDCmp( Mob->Class->ID, &AAFClassID_MasterMob ) ) - // // break; - // // } - // - // videoEssence->sourceMobID = aaf_get_propertyValue( ParentMob, PID_Mob_MobID, &AAFTypeID_MobIDType ); - // - // warning( "Could not retrieve SourceReference::SourceID, retrieving from parent Mob." ); - // } - // - // - // - // aafObject *SourceMob = aaf_get_MobByID( aafi->aafd->Mobs, videoEssence->sourceMobID ); - // - // if ( SourceMob == NULL ) { - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_RED ); - // error( "Could not retrieve SourceMob." ); - // return -1; - // } - // - // videoEssence->SourceMob = SourceMob; - // - // - // - // // parse_SourceMob( aafi, SourceMob ); - // - // - // /* TODO the following must be moved to parse_SourceMob() !!! */ - // - // aafObject *EssenceDesc = aaf_get_propertyValue( SourceMob, PID_SourceMob_EssenceDescription, &AAFTypeID_EssenceDescriptorStrongReference ); - // - // if ( EssenceDesc == NULL ) { - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_RED ); - // error( "Could not retrieve EssenceDesc." ); - // return -1; - // } - // - // - // // TODO - // parse_EssenceDescriptor( aafi, EssenceDesc ); - // - // - // - // videoEssence->unique_file_name = build_unique_videofilename( aafi, videoEssence ); - // - // - // - // /* NOTE since multiple clips can point to the same MasterMob, we have to loop. */ - // - // aafiVideoTrack * videoTrack = NULL; - // aafiTimelineItem * videoItem = NULL; - // - // foreach_videoTrack( videoTrack, aafi ) { - // foreach_Item( videoItem, videoTrack ) { - // if ( videoItem->type != AAFI_VIDEO_CLIP ) { - // continue; - // } - // - // aafiVideoClip *videoClip = (aafiVideoClip*)&videoItem->data; - // - // if ( aafMobIDCmp( videoClip->masterMobID, videoEssence->masterMobID ) ) { - // debug( "FOUND VIDEO ESSENCE CLIP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); - // videoClip->Essence = videoEssence; - // } - // } - // } - // - // aafi_trace_obj( aafi, SourceClip, ANSI_COLOR_MAGENTA ); - // + aafi->ctx.current_video_essence = NULL; } + } else if (aafUIDCmp (ParentMob->Class->ID, &AAFClassID_SourceMob)) { + /* Nothing to parse here at first glance : SourceMob > TimelineMobSlot > SourceClip */ + TRACE_OBJ (aafi, SourceClip, &__td); } else { - DUMP_OBJ_NO_SUPPORT (aafi, SourceClip, &__td); + TRACE_OBJ_NO_SUPPORT (aafi, SourceClip, &__td); return -1; } return 0; } +static int +parse_Timecode (AAF_Iface* aafi, aafObject* Timecode, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + __td.eob = 1; + + aafPosition_t* tc_start = aaf_get_propertyValue (Timecode, PID_Timecode_Start, &AAFTypeID_PositionType); + + if (tc_start == NULL) { + TRACE_OBJ_ERROR (aafi, Timecode, &__td, "Missing Timecode::Start"); + return -1; + } + + uint16_t* tc_fps = aaf_get_propertyValue (Timecode, PID_Timecode_FPS, &AAFTypeID_UInt16); + + if (tc_fps == NULL) { + TRACE_OBJ_ERROR (aafi, Timecode, &__td, "Missing Timecode::FPS"); + return -1; + } + + uint8_t* tc_drop = aaf_get_propertyValue (Timecode, PID_Timecode_Drop, &AAFTypeID_UInt8); + + if (tc_drop == NULL) { + TRACE_OBJ_ERROR (aafi, Timecode, &__td, "Missing Timecode::Drop"); + return -1; + } + + /* TODO this should be retrieved directly from TimelineMobSlot */ + + aafObject* ParentMobSlot = aaf_get_ObjectAncestor (Timecode, &AAFClassID_MobSlot); + + if (!ParentMobSlot) { + TRACE_OBJ_ERROR (aafi, Timecode, &__td, "Could not retrieve parent MobSlot"); + return -1; + } + + aafRational_t* tc_edit_rate = aaf_get_propertyValue (ParentMobSlot, PID_TimelineMobSlot_EditRate, &AAFTypeID_Rational); + + if (tc_edit_rate == NULL) { + TRACE_OBJ_ERROR (aafi, Timecode, &__td, "Missing parent TimelineMobSlot::EditRate"); + return -1; + } + + if (aafi->Timecode) { + TRACE_OBJ_WARNING (aafi, Timecode, &__td, "Timecode was already set, ignoring (%lu, %u fps)", *tc_start, *tc_fps); + return -1; + } + + aafiTimecode* tc = calloc (1, sizeof (aafiTimecode)); + + if (!tc) { + TRACE_OBJ_ERROR (aafi, Timecode, &__td, "Out of memory"); + return -1; + } + + tc->start = *tc_start; + tc->fps = *tc_fps; + tc->drop = *tc_drop; + tc->edit_rate = tc_edit_rate; + + aafi->Timecode = tc; + + TRACE_OBJ (aafi, Timecode, &__td); + + return 0; +} + +static int +parse_DescriptiveMarker (AAF_Iface* aafi, aafObject* DescriptiveMarker, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + + aafPosition_t* start = aaf_get_propertyValue (DescriptiveMarker, PID_Event_Position, &AAFTypeID_PositionType); + + if (!start) { + /* + * « If an Event is in a TimelineMobSlot or a StaticMobSlot, it shall not have a Position + * property. If an Event is in a EventMobSlot, it shall have a Position property. » + */ + TRACE_OBJ_ERROR (aafi, DescriptiveMarker, &__td, "Missing Event::Position"); + return -1; + } + + TRACE_OBJ (aafi, DescriptiveMarker, &__td); + + aafPosition_t* length = aaf_get_propertyValue (DescriptiveMarker, PID_Component_Length, &AAFTypeID_PositionType); + char* comment = aaf_get_propertyValue (DescriptiveMarker, PID_Event_Comment, &AAFTypeID_String); + char* name = aaf_get_propertyValue (DescriptiveMarker, aaf_get_PropertyIDByName (aafi->aafd, "CommentMarkerUser"), &AAFTypeID_String); + + if (!name) { + /* Avid Media Composer 23.12 */ + name = aaf_get_propertyValue (DescriptiveMarker, aaf_get_PropertyIDByName (aafi->aafd, "CommentMarkerUSer"), &AAFTypeID_String); + } + + uint16_t* RGBColor = NULL; + aafProperty* RGBColorProp = aaf_get_property (DescriptiveMarker, aaf_get_PropertyIDByName (aafi->aafd, "CommentMarkerColor")); + + if (RGBColorProp) { + if (RGBColorProp->len != sizeof (uint16_t) * 3) { + error ("CommentMarkerColor has wrong size: %u", RGBColorProp->len); + } else { + RGBColor = RGBColorProp->val; + + /* big endian to little endian */ + RGBColor[0] = (RGBColor[0] >> 8) | (RGBColor[0] << 8); + RGBColor[1] = (RGBColor[1] >> 8) | (RGBColor[1] << 8); + RGBColor[2] = (RGBColor[2] >> 8) | (RGBColor[2] << 8); + } + } + + aafi_newMarker (aafi, aafi->ctx.current_markers_edit_rate, *start, ((length) ? *length : 0), name, comment, &RGBColor); + + return 0; +} + +static int +parse_Sequence (AAF_Iface* aafi, aafObject* Sequence, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + + aafObject* Component = NULL; + aafObject* Components = aaf_get_propertyValue (Sequence, PID_Sequence_Components, &AAFTypeID_ComponentStrongReferenceVector); + + if (!Components) { + TRACE_OBJ_ERROR (aafi, Sequence, &__td, "Missing Sequence::Components"); + return -1; + } + + TRACE_OBJ (aafi, Sequence, &__td); + + /* + * "Audio Warp" OperationGroup appears in Avid Media Composer AAF files, when + * a clip with a different frame rate from the project was *linked* into Avid + * rather than beeing properly imported. + * + * "Audio Warp" OperationGroup is pointing to a Sequence with two ComponentAttributes: + * _MIXMATCH_RATE_NUM + * _MIXMATCH_RATE_DENOM + * + * Those parameters set the valid edit rate for SourceClip::StartTime (essence + * offset) and Component::Length, in total violation of the standard saying that + * TimelineMobSlot::EditRate shall always be used. + * +│ 02009││ │ ├──◻ AAFClassID_OperationGroup (OpIdent: Audio Warp; Length: 168) (MetaProps: ComponentAttributeList[0xffc9]) +│ 02283││ │ │ ├──◻ AAFClassID_ConstantValue (ParamDef: AvidMotionInputFormat; Type: AAFTypeID_Int32) : 2 +│ 02283││ │ │ ├──◻ AAFClassID_ConstantValue (ParamDef: AAFParameterDef_SpeedRatio; Type: AAFTypeID_Rational) : 1/2 +│ 02283││ │ │ ├──◻ AAFClassID_ConstantValue (ParamDef: AvidPhase; Type: AAFTypeID_Int32) : 0 +│ 02283││ │ │ ├──◻ AAFClassID_ConstantValue (ParamDef: AvidMotionOutputFormat; Type: AAFTypeID_Int32) : 0 +│ 02283││ │ │ └──◻ AAFClassID_ConstantValue (ParamDef: AvidMotionPulldown; Type: AAFTypeID_Int32) : 0 +│ 01628││ │ │ └──◻ AAFClassID_Sequence (Length: 336) (MetaProps: ComponentAttributeList[0xffc9]) +│ 01195││ │ │ └──◻ AAFClassID_SourceClip (Length: 336) +│ 01198││ │ │ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : UTS_LIMO_LIMO_3_2024_01_30_11_15_45.new.04 (MetaProps: MobAttributeList[0xfff9] ConvertFrameRate[0xfff8]) +│ 00513││ │ │ └──◻ AAFClassID_TimelineMobSlot [slot:1 track:1] (DataDef: AAFDataDef_Sound) +│ 01628││ │ │ └──◻ AAFClassID_Sequence (Length: 576) +│ 01359││ │ │ └──◻ AAFClassID_SourceClip (Length: 576) +│ 00272││ │ │ ├──◻ AAFClassID_SourceMob (UsageCode: n/a) (MetaProps: MobAttributeList[0xfff9]) +│ 02806││ │ │ │ ├──◻ AAFClassID_WAVEDescriptor (ContainerIdent : AAFContainerDef_AAF) +│ 03010││ │ │ │ │ └──◻ AAFClassID_NetworkLocator (URLString: file://10.87.230.71/mixage/AAF_Vers_Mixage/MONTAGE_06/4550985%20SUIVI%20AGRICULTEURS%20VERS%20PARIS.aaf) +│ ││ │ │ │ │ +│ 00532││ │ │ │ └──◻ AAFClassID_TimelineMobSlot [slot:1 track:1] (DataDef: AAFDataDef_Sound) +│ 01470││ │ │ │ └──◻ AAFClassID_SourceClip (Length: 576) +│ 03071││ │ │ └──◻ AAFClassID_EssenceData (Data: Data-2702) + + */ + + void* ComponentAttributeList = aaf_get_propertyValue (Sequence, aaf_get_PropertyIDByName (aafi->aafd, "ComponentAttributeList"), &AAFTypeID_TaggedValueStrongReferenceVector); + + if (ComponentAttributeList) { + int32_t* rateNum = aaf_get_TaggedValueByName (aafi->aafd, ComponentAttributeList, "_MIXMATCH_RATE_NUM", &AAFTypeID_Int32); + int32_t* rateDenom = aaf_get_TaggedValueByName (aafi->aafd, ComponentAttributeList, "_MIXMATCH_RATE_DENOM", &AAFTypeID_Int32); + + if (rateNum && rateDenom) { + aafi->ctx.avid_warp_clip_edit_rate = malloc (sizeof (aafRational_t)); + + if (!aafi->ctx.avid_warp_clip_edit_rate) { + error ("Out of memory"); + return -1; + } + + aafi->ctx.avid_warp_clip_edit_rate->numerator = *rateNum; + aafi->ctx.avid_warp_clip_edit_rate->denominator = *rateDenom; + debug ("Got Avid audio warp edit rate : %i/%i", + aafi->ctx.avid_warp_clip_edit_rate->numerator, + aafi->ctx.avid_warp_clip_edit_rate->denominator); + } + } + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Component, Components, i, __td) + { + parse_Component (aafi, Component, &__td); + } + + free (aafi->ctx.avid_warp_clip_edit_rate); + aafi->ctx.avid_warp_clip_edit_rate = NULL; + + return 0; +} + static int parse_Selector (AAF_Iface* aafi, aafObject* Selector, td* __ptd) { @@ -3013,28 +1560,403 @@ parse_Selector (AAF_Iface* aafi, aafObject* Selector, td* __ptd) struct trace_dump __td; __td_set (__td, __ptd, 1); - if (resolve_AAF (aafi)) { - return resolve_parse_aafObject_Selector (aafi, Selector, &__td); - } - aafObject* Selected = aaf_get_propertyValue (Selector, PID_Selector_Selected, &AAFTypeID_SegmentStrongReference); - if (Selected == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, Selector, &__td, "Missing PID_Selector_Selected"); + if (!Selected) { + TRACE_OBJ_ERROR (aafi, Selector, &__td, "Missing Selector::Selected"); return -1; } - // aafObject *Alternate = NULL; + TRACE_OBJ (aafi, Selector, &__td); + aafObject* Alternates = aaf_get_propertyValue (Selector, PID_Selector_Alternates, &AAFTypeID_SegmentStrongReferenceVector); - if (Alternates == NULL) { /* opt */ - // DUMP_OBJ_WARNING( aafi, Selector, &__td, "Missing PID_Selector_Alternates" ); + if (Alternates) { + __td.lv++; + TRACE_OBJ_INFO (aafi, Alternates, &__td, "Selector Alternates (dropping)"); + __td.lv--; } - DUMP_OBJ (aafi, Selector, &__td); + /* + * ComponentAttributeList is non-standard, used by Avid Media Composer and + * Davinci Resolve to describe a disabled (muted) clip. This way, any unaware + * implementation will parse Selected Object containing a Filler and ignore + * the disabled clip inside Alternates. + */ - /* without specific software implementation we stick to Selected and forget about Alternates */ - return aafi_parse_Segment (aafi, Selected, &__td); + void* ComponentAttributeList = aaf_get_propertyValue (Selector, aaf_get_PropertyIDByName (aafi->aafd, "ComponentAttributeList"), &AAFTypeID_TaggedValueStrongReferenceVector); + + if (ComponentAttributeList) { + int32_t* disabledClip = aaf_get_TaggedValueByName (aafi->aafd, ComponentAttributeList, "_DISABLE_CLIP_FLAG", &AAFTypeID_Int32); + + if (disabledClip) { + if (*disabledClip) { + aafi->ctx.current_clip_is_muted = 1; + } + + /* + * When Selector has _DISABLE_CLIP_FLAG, Alternates should point + * to a single Alternates Object containing the disabled clip. + */ + if (Alternates) { + return parse_Segment (aafi, Alternates, &__td); + } else { + return parse_Segment (aafi, Selected, &__td); + } + } + } else { + /* + * without specific software implementation, we stick to Selected Object + * and forget about any Alternates Objects. + */ + return parse_Segment (aafi, Selected, &__td); + } + + return -1; +} + +static int +parse_NestedScope (AAF_Iface* aafi, aafObject* NestedScope, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + + /* + * NestedScope seems to be only used for video clips in Avid Media Composer. + * Not sure how to handle it... + */ + + aafObject* Slot = NULL; + aafObject* Slots = aaf_get_propertyValue (NestedScope, PID_NestedScope_Slots, &AAFTypeID_SegmentStrongReferenceVector); + + if (!Slots) { + TRACE_OBJ_ERROR (aafi, NestedScope, &__td, "Missing NestedScope::Slots"); + return -1; + } + + TRACE_OBJ (aafi, NestedScope, &__td); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Slot, Slots, i, __td) + { + parse_Segment (aafi, Slot, &__td); + } + + return 0; +} + +static int +parse_OperationGroup (AAF_Iface* aafi, aafObject* OpGroup, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + + if (!aaf_get_property (OpGroup, PID_OperationGroup_InputSegments) && + !aaf_get_property (OpGroup, PID_OperationGroup_Parameters)) { + __td.eob = 1; + } + + aafObject* ParentMob = aaf_get_ObjectAncestor (OpGroup, &AAFClassID_Mob); + + if (!ParentMob) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Could not retrieve parent Mob"); + return -1; + } + + if (!aafUIDCmp (ParentMob->Class->ID, &AAFClassID_CompositionMob)) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "OperationGroup is currently supported only in CompositionMob, not in %s", aaft_ClassIDToText (aafi->aafd, ParentMob->Class->ID)); + return -1; + } + + int rc = 0; + + aafWeakRef_t* OperationDefWeakRef = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Operation, &AAFTypeID_OperationDefinitionWeakReference); + + if (!OperationDefWeakRef) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Missing OperationGroup::Operation"); + return -1; + } + + aafUID_t* OperationIdentification = aaf_get_OperationIdentificationByWeakRef (aafi->aafd, OperationDefWeakRef); + + if (!OperationIdentification) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Could not retrieve OperationIdentification"); + return -1; + } + + /* + * We need to check if OperationGroup is a direct child of TopLevelCompositionMob > TimelineMobSlot. + * - If it is, it means that the OperationGroup affect the current Track. + * - If it's not (eg. it's a child of a Sequence), then OperationGroup applies + * to all descendent clips. + * + * NOTE: OperationGroup can be a child of another OperationGroup. So we can't + * just check direct Parent, we need to loop. + */ + + aafObject* OperationGroupParent = OpGroup->Parent; + while (OperationGroupParent && aafUIDCmp (OperationGroupParent->Class->ID, &AAFClassID_OperationGroup)) { + OperationGroupParent = OperationGroupParent->Parent; + } + + if (!OperationGroupParent) { + error ("OperationGroup has no parent !"); + return -1; + } + + if (aafUIDCmp (OperationGroupParent->Class->ID, &AAFClassID_TimelineMobSlot) && + ParentMob == aafi->ctx.TopLevelCompositionMob) { + aafi->ctx.current_opgroup_affect_track = 1; + } else { + aafi->ctx.current_opgroup_affect_track = 0; + } + + if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioDissolve)) { + if (!aafUIDCmp (OpGroup->Parent->Class->ID, &AAFClassID_Transition)) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Parent should be AAFClassID_Transition"); + return -1; + } + + TRACE_OBJ (aafi, OpGroup, &__td); + + aafiTransition* Trans = aafi->ctx.current_transition; + + /* + * Mono Audio Dissolve (Fade, Cross Fade) + * + * The same parameter (curve/level) is applied to the outgoing fade on first + * clip (if any) and to the incoming fade on second clip (if any). + */ + + Trans->flags |= AAFI_TRANS_SINGLE_CURVE; + + aafObject* Param = NULL; + aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Param, Parameters, i, __td) + { + parse_Parameter (aafi, Param, &__td); + } + + /* + * Avid Media Composer doesn't use the standard method to set interpolation. Instead, + * it always sets InterpolationIdentification to Linear, and it sets the actual + * interpolation in both : + * - OperationGroup > ComponentAttributeList > _ATN_AUDIO_DISSOLVE_CURVETYPE + * - OperationGroup > Parameters > AAFClassID_ConstantValue (ParamDef: Curve Type; Type: AAFTypeID_Int32) : 1 + * + * Note: _ATN_AUDIO_DISSOLVE_CURVETYPE was observed since v8.4 (2015), however "Curve Type" was observed since v18.12.7. + * Using _ATN_AUDIO_DISSOLVE_CURVETYPE provides a better support for older Avid MC versions. + */ + + void* ComponentAttributeList = aaf_get_propertyValue (OpGroup, aaf_get_PropertyIDByName (aafi->aafd, "ComponentAttributeList"), &AAFTypeID_TaggedValueStrongReferenceVector); + + if (ComponentAttributeList) { + int32_t* curveType = aaf_get_TaggedValueByName (aafi->aafd, ComponentAttributeList, "_ATN_AUDIO_DISSOLVE_CURVETYPE", &AAFTypeID_Int32); + + if (curveType) { + switch (*curveType) { + case AVID_MEDIA_COMPOSER_CURVE_TYPE_LINEAR: + Trans->flags &= ~(AAFI_INTERPOL_MASK); + Trans->flags |= AAFI_INTERPOL_LINEAR; + break; + case AVID_MEDIA_COMPOSER_CURVE_TYPE_EQUAL_POWER: + Trans->flags &= ~(AAFI_INTERPOL_MASK); + Trans->flags |= AAFI_INTERPOL_POWER; + break; + default: + debug ("Unknown Avid Media Composer fade curve: %i", *curveType); + break; + } + } + } + + if (!(Trans->flags & AAFI_INTERPOL_MASK)) { + debug ("Setting fade interpolation to default Linear"); + Trans->flags |= AAFI_INTERPOL_LINEAR; + } + + aafi_dump_obj (aafi, NULL, &__td, 0, NULL, -1, ""); + } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_AudioChannelCombiner)) { + TRACE_OBJ (aafi, OpGroup, &__td); + + aafObject* InputSegment = NULL; + aafObject* InputSegments = aaf_get_propertyValue (OpGroup, PID_OperationGroup_InputSegments, &AAFTypeID_SegmentStrongReferenceVector); + + aafi->ctx.current_clip_is_combined = 1; + aafi->ctx.current_combined_clip_total_channel = InputSegments->Header->_entryCount; + aafi->ctx.current_combined_clip_channel_num = 0; + aafi->ctx.current_combined_clip_forced_length = 0; + + if (resolve_AAF (aafi)) { + /* + * This is clearly a violation of the standard (p 57). When Davinci Resolve + * exports multichannel clips, it does not set SourceClip::Length correctly. + * Instead, it's more like some sort of frame-rounded value which doesn't match + * the timeline. However, the correct value is set to OperationGroup::length... + */ + int64_t* length = aaf_get_propertyValue (OpGroup, PID_Component_Length, &AAFTypeID_LengthType); + aafi->ctx.current_combined_clip_forced_length = (length) ? *length : 0; + } + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&InputSegment, InputSegments, i, __td) + { + parse_Segment (aafi, InputSegment, &__td); + aafi->ctx.current_combined_clip_channel_num++; + } + + aafi_dump_obj (aafi, NULL, &__td, 0, NULL, -1, ""); + + aafiAudioTrack* current_track = aafi->ctx.current_track; + + aafiTrackFormat_e track_format = AAFI_TRACK_FORMAT_UNKNOWN; + + if (aafi->ctx.current_combined_clip_total_channel == 2) { + track_format = AAFI_TRACK_FORMAT_STEREO; + } else if (aafi->ctx.current_combined_clip_total_channel == 6) { + track_format = AAFI_TRACK_FORMAT_5_1; + } else if (aafi->ctx.current_combined_clip_total_channel == 8) { + track_format = AAFI_TRACK_FORMAT_7_1; + } else { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Unknown track format (%u)", aafi->ctx.current_combined_clip_total_channel); + RESET_CTX__AudioChannelCombiner (aafi->ctx); + return -1; + } + + if (current_track->format != AAFI_TRACK_FORMAT_NOT_SET && + current_track->format != track_format) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Track format (%u) does not match current clip (%u)", current_track->format, track_format); + RESET_CTX__AudioChannelCombiner (aafi->ctx); + return -1; + } + + current_track->format = track_format; + RESET_CTX__AudioChannelCombiner (aafi->ctx); + } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioGain)) { + aafObject* Param = NULL; + aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); + + if (!Parameters) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Missing OperationGroup::Parameters"); + rc = -1; + goto end; /* we still have to parse InputSegments, so we're not losing any clip */ + } + + TRACE_OBJ (aafi, OpGroup, &__td); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Param, Parameters, i, __td) + { + parse_Parameter (aafi, Param, &__td); + } + } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioPan)) { + /* TODO Should Only be Track-based (first Segment of TimelineMobSlot.) */ + + aafObject* Param = NULL; + aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); + + if (!Parameters) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Missing OperationGroup::Parameters"); + rc = -1; + goto end; /* we still have to parse InputSegments, so we're not losing any clip */ + } + + TRACE_OBJ (aafi, OpGroup, &__td); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Param, Parameters, i, __td) + { + parse_Parameter (aafi, Param, &__td); + } + } else if (aafUIDCmp (OperationIdentification, aaf_get_OperationDefIDByName (aafi->aafd, "Audio Warp"))) { + aafObject* Param = NULL; + aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); + + if (!Parameters) { + TRACE_OBJ_ERROR (aafi, OpGroup, &__td, "Missing OperationGroup::Parameters"); + rc = -1; + goto end; /* we still have to parse InputSegments, so we're not losing any clip */ + } + + TRACE_OBJ (aafi, OpGroup, &__td); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Param, Parameters, i, __td) + { + parse_Parameter (aafi, Param, &__td); + } + } else { + /* + * Unknown usage and implementation, not encountered yet: + * + * AAFOperationDef_MonoAudioMixdown + * AAFOperationDef_StereoAudioGain + * AAFOperationDef_TwoParameterMonoAudioDissolve + * AAFOperationDef_StereoAudioDissolve + */ + debug ("Unsupported OperationIdentification: %s", aaft_OperationDefToText (aafi->aafd, OperationIdentification)); + TRACE_OBJ_NO_SUPPORT (aafi, OpGroup, &__td); + + aafObject* Param = NULL; + aafObject* Parameters = aaf_get_propertyValue (OpGroup, PID_OperationGroup_Parameters, &AAFTypeID_ParameterStrongReferenceVector); + + if (!Parameters) { + // TRACE_OBJ_ERROR( aafi, OpGroup, &__td, "Missing OperationGroup::Parameters" ); + rc = -1; + goto end; /* we still have to parse InputSegments, so we're not losing any clip */ + } + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Param, Parameters, i, __td) + { + parse_Parameter (aafi, Param, &__td); + } + } + +end: + + /* + * Parses Segments in the OperationGroup::InputSegments, only if + * OperationGroup is not a Transition as a Transition has no InputSegments, + * and not an AudioChannelCombiner as they were already parsed. + */ + + if (!aafUIDCmp (OpGroup->Parent->Class->ID, &AAFClassID_Transition) && + !aafUIDCmp (OperationIdentification, &AAFOperationDef_AudioChannelCombiner)) { + aafObject* InputSegment = NULL; + aafObject* InputSegments = aaf_get_propertyValue (OpGroup, PID_OperationGroup_InputSegments, &AAFTypeID_SegmentStrongReferenceVector); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&InputSegment, InputSegments, i, __td) + { + parse_Segment (aafi, InputSegment, &__td); + } + } + + /* End of current OperationGroup context. */ + + aafObject* Obj = OpGroup; + for (; Obj != NULL && aafUIDCmp (Obj->Class->ID, &AAFClassID_ContentStorage) == 0; Obj = Obj->Parent) + if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_OperationGroup)) + break; + + if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioGain)) { + if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot)) { + if (aafi->ctx.current_clip_gain_is_used == 0) { + aafi_freeAudioGain (aafi->ctx.current_clip_gain); + } + + if (aafi->ctx.current_clip_variable_gain_is_used == 0) { + aafi_freeAudioGain (aafi->ctx.current_clip_variable_gain); + } + + RESET_CTX__AudioGain (aafi->ctx); + } + } + + return rc; } /* @@ -3060,7 +1982,7 @@ parse_Parameter (AAF_Iface* aafi, aafObject* Parameter, td* __ptd) return parse_VaryingValue (aafi, Parameter, &__td); } else { __td_set (__td, __ptd, 1); - DUMP_OBJ_ERROR (aafi, Parameter, &__td, "Parameter is neither of class Constant nor Varying : %ls", aaft_ClassIDToText (aafi->aafd, Parameter->Class->ID)); + TRACE_OBJ_ERROR (aafi, Parameter, &__td, "Parameter is neither of class Constant nor Varying : %s", aaft_ClassIDToText (aafi->aafd, Parameter->Class->ID)); } return -1; @@ -3072,131 +1994,141 @@ parse_ConstantValue (AAF_Iface* aafi, aafObject* ConstantValue, td* __ptd) struct trace_dump __td; __td_set (__td, __ptd, 1); - // __td.sub = 1; - if (!aaf_get_propertyValue (ConstantValue->Parent, PID_OperationGroup_InputSegments, &AAFTypeID_SegmentStrongReferenceVector)) { __td.eob = 1; } aafUID_t* ParamDef = aaf_get_propertyValue (ConstantValue, PID_Parameter_Definition, &AAFTypeID_AUID); - if (ParamDef == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Missing PID_Parameter_Definition"); + if (!ParamDef) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Missing Parameter::Definition"); return -1; } - aafUID_t* OperationIdentification = get_OperationGroup_OperationIdentification (aafi, ConstantValue->Parent); + aafWeakRef_t* OperationDefWeakRef = aaf_get_propertyValue (ConstantValue->Parent, PID_OperationGroup_Operation, &AAFTypeID_OperationDefinitionWeakReference); - if (OperationIdentification == NULL) { - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not retrieve OperationIdentification"); + if (!OperationDefWeakRef) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Missing OperationGroup::Operation"); return -1; } + aafUID_t* OperationIdentification = aaf_get_OperationIdentificationByWeakRef (aafi->aafd, OperationDefWeakRef); + + if (!OperationIdentification) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not retrieve OperationIdentification from parent"); + return -1; + } + + aafIndirect_t* Indirect = aaf_get_propertyValue (ConstantValue, PID_ConstantValue_Value, &AAFTypeID_Indirect); + + if (!Indirect) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Missing ConstantValue::Value"); + return -1; + } + + aafObject* ParentMob = aaf_get_ObjectAncestor (ConstantValue, &AAFClassID_Mob); + + aafUID_t* mobUsageCode = aaf_get_propertyValue (ParentMob, PID_Mob_UsageCode, &AAFTypeID_UsageType); + if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioGain) && aafUIDCmp (ParamDef, &AAFParameterDef_Amplitude)) { - aafIndirect_t* Indirect = aaf_get_propertyValue (ConstantValue, PID_ConstantValue_Value, &AAFTypeID_Indirect); + aafRational_t* value = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Rational); - if (Indirect == NULL) { - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Missing PID_ConstantValue_Value or wrong AAFTypeID"); + if (!value) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not retrieve Indirect value for ConstantValue::Value"); return -1; } - aafRational_t* multiplier = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Rational); + aafiAudioGain* Gain = aafi_newAudioGain (aafi, AAFI_AUDIO_GAIN_CONSTANT, 0, value); - if (multiplier == NULL) { - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not retrieve Indirect value for PID_ConstantValue_Value"); + if (!Gain) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not create new gain"); return -1; } - aafiAudioGain* Gain = calloc (sizeof (aafiAudioGain), sizeof (unsigned char)); - - Gain->pts_cnt = 1; - Gain->value = calloc (1, sizeof (aafRational_t*)); - Gain->flags |= AAFI_AUDIO_GAIN_CONSTANT; - - memcpy (&Gain->value[0], multiplier, sizeof (aafRational_t)); - - /* - * Loop through ancestors to find out who is the parent of OperationGroup. - * If it belongs to TimelineMobSlot, that means the Parameter is attached - * to a Track. If it belongs to a Component, the Parameter is attached to - * a clip. - * - * NOTE: We can't just check the Parent since we can have nested OperationGroups - * providing different effects like Pan, Gain, CustomFx.. Therefore looping - * is required. - */ - - aafObject* Obj = ConstantValue->Parent; // Start with the last OperationGroup - for (; Obj != NULL && aafUIDCmp (Obj->Class->ID, &AAFClassID_ContentStorage) == 0; Obj = Obj->Parent) - if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_OperationGroup)) - break; - - if (aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot)) { - /* Track-based Gain */ - aafi->ctx.current_track->gain = Gain; + if (aafUIDCmp (mobUsageCode, &AAFUsage_AdjustedClip)) { + /* + * « Some applications support the notion of an adjusted-clip in which an + * effect is applied directly to a clip and applies to all uses of that + * clip, e.g. an audio gain effect. » + * + * Only Avid Media Composer seems to make use of AdjustedClip, in a way that + * it doesn't affect the timeline composition. It looks like any gain applied + * to a source clip (inside a bin), is just audible when playing that clip + * in preview. + * + * Thus, we just ignore it. + */ + debug ("Ignoring AdjustedClip audio level: %i/%i (%+05.1lf dB) ", Gain->value[0].numerator, Gain->value[0].denominator, 20 * log10 (aafRationalToDouble (Gain->value[0]))); + TRACE_OBJ_WARNING (aafi, ConstantValue, &__td, "Ignoring AdjustedClip audio level"); + aafi_freeAudioGain (Gain); + } else if (aafi->ctx.current_opgroup_affect_track) { + /* + * Track-based Volume + */ + if (!aafi->ctx.current_track) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Current track not set, dropping this volume: %i/%i (%+05.1lf dB)", Gain->value[0].numerator, Gain->value[0].denominator, 20 * log10 (aafRationalToDouble (Gain->value[0]))); + aafi_freeAudioGain (Gain); + return -1; + } else if (aafi->ctx.current_track->gain) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Track volume was already set, dropping this one: %i/%i (%+05.1lf dB)", Gain->value[0].numerator, Gain->value[0].denominator, 20 * log10 (aafRationalToDouble (Gain->value[0]))); + aafi_freeAudioGain (Gain); + return -1; + } else { + aafi->ctx.current_track->gain = Gain; + TRACE_OBJ (aafi, ConstantValue, &__td); + } } else { - /* Clip-based Gain */ + /* + * Clip-based Gain + * Gain is saved in context and it will be set to all OperationGroup descendent clips. + */ if (aafi->ctx.current_clip_gain) { - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Clip gain was already set : +%05.1lf dB", 20 * log10 (aafRationalToFloat (aafi->ctx.current_clip_gain->value[0]))); - - // for ( int i = 0; i < aafi->ctx.current_clip_gain->pts_cnt; i++ ) { - // debug( " VaryingValue: _time: %f _value: %f", - // aafRationalToFloat( aafi->ctx.current_clip_gain->time[i] ), - // aafRationalToFloat( aafi->ctx.current_clip_gain->value[i] ) ); - // } - + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Clip gain was already set, dropping this one: %i/%i (%+05.1lf dB)", Gain->value[0].numerator, Gain->value[0].denominator, 20 * log10 (aafRationalToDouble (Gain->value[0]))); aafi_freeAudioGain (Gain); return -1; } else { aafi->ctx.current_clip_gain = Gain; - aafi->ctx.clips_using_gain = 0; + TRACE_OBJ (aafi, ConstantValue, &__td); } } - - DUMP_OBJ (aafi, ConstantValue, &__td); - } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioPan) && aafUIDCmp (ParamDef, &AAFParameterDef_Pan)) { - /* - * Pan automation shall be track-based. If an application has a different - * native representation (e.g., clip-based pan), it shall convert to and - * from its native representation when exporting and importing the composition. - */ + aafRational_t* value = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Rational); - aafIndirect_t* Indirect = aaf_get_propertyValue (ConstantValue, PID_ConstantValue_Value, &AAFTypeID_Indirect); - - if (Indirect == NULL) { - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Missing PID_ConstantValue_Value or wrong AAFTypeID"); + if (!value) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not retrieve Indirect value for ConstantValue::Value"); return -1; } - aafRational_t* multiplier = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Rational); - - if (multiplier == NULL) { - DUMP_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not retrieve Indirect value for PID_ConstantValue_Value"); + if (!aafi->ctx.current_opgroup_affect_track) { + /* + * « Pan automation shall be track-based. If an application has a different + * native representation (e.g., clip-based pan), it shall convert to and + * from its native representation when exporting and importing the composition. » + * + * NOTE: Never encountered clip-based pan AAF. + */ + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Pan shall be track based"); return -1; } - // if ( multiplier == NULL ) { - // DUMP_OBJ_ERROR( aafi, ConstantValue, &__td, "Missing PID_ConstantValue_Value or wrong AAFTypeID" ); - // return -1; - // } + if (!aafi->ctx.current_track) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Current track not set"); + return -1; + } - aafiAudioPan* Pan = calloc (sizeof (aafiAudioPan), sizeof (unsigned char)); + aafiAudioPan* Pan = aafi_newAudioPan (aafi, AAFI_AUDIO_GAIN_CONSTANT, 0, value); - Pan->pts_cnt = 1; - Pan->value = calloc (1, sizeof (aafRational_t*)); - Pan->flags |= AAFI_AUDIO_GAIN_CONSTANT; + if (!Pan) { + TRACE_OBJ_ERROR (aafi, ConstantValue, &__td, "Could not create new pan"); + return -1; + } - memcpy (&Pan->value[0], multiplier, sizeof (aafRational_t)); - - /* Pan is Track-based only. */ aafi->ctx.current_track->pan = Pan; - - DUMP_OBJ (aafi, ConstantValue, &__td); + TRACE_OBJ (aafi, ConstantValue, &__td); } else { - DUMP_OBJ_NO_SUPPORT (aafi, ConstantValue, &__td); + TRACE_OBJ_NO_SUPPORT (aafi, ConstantValue, &__td); } return 0; @@ -3208,31 +2140,43 @@ parse_VaryingValue (AAF_Iface* aafi, aafObject* VaryingValue, td* __ptd) struct trace_dump __td; __td_set (__td, __ptd, 1); - // __td.sub = 1; - if (!aaf_get_propertyValue (VaryingValue->Parent, PID_OperationGroup_InputSegments, &AAFTypeID_SegmentStrongReferenceVector)) { __td.eob = 1; } aafUID_t* ParamDef = aaf_get_propertyValue (VaryingValue, PID_Parameter_Definition, &AAFTypeID_AUID); - if (ParamDef == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Missing PID_Parameter_Definition"); + if (!ParamDef) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Missing Parameter::Definition"); return -1; } - aafUID_t* OperationIdentification = get_OperationGroup_OperationIdentification (aafi, VaryingValue->Parent); + aafWeakRef_t* OperationDefWeakRef = aaf_get_propertyValue (VaryingValue->Parent, PID_OperationGroup_Operation, &AAFTypeID_OperationDefinitionWeakReference); - if (OperationIdentification == NULL) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve OperationIdentification"); + if (!OperationDefWeakRef) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Missing OperationGroup::Operation"); + return -1; + } + + aafUID_t* OperationIdentification = aaf_get_OperationIdentificationByWeakRef (aafi->aafd, OperationDefWeakRef); + + if (!OperationIdentification) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve OperationIdentification from parent"); + return -1; + } + + aafWeakRef_t* InterpolationDefWeakRef = aaf_get_propertyValue (VaryingValue, PID_VaryingValue_Interpolation, &AAFTypeID_InterpolationDefinitionWeakReference); + + if (!InterpolationDefWeakRef) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Missing VaryingValue::Interpolation."); return -1; } aafiInterpolation_e interpolation = 0; - aafUID_t* InterpolationIdentification = get_Parameter_InterpolationIdentification (aafi, VaryingValue); + aafUID_t* InterpolationIdentification = aaf_get_InterpolationIdentificationByWeakRef (aafi->aafd, InterpolationDefWeakRef); - if (InterpolationIdentification == NULL) { - DUMP_OBJ_WARNING (aafi, VaryingValue, &__td, "Could not retrieve InterpolationIdentification: Setting to Linear"); + if (!InterpolationIdentification) { + TRACE_OBJ_WARNING (aafi, VaryingValue, &__td, "Could not retrieve InterpolationIdentification: Falling back to Linear"); interpolation = AAFI_INTERPOL_LINEAR; } else if (aafUIDCmp (InterpolationIdentification, &AAFInterpolationDef_None)) { interpolation = AAFI_INTERPOL_NONE; @@ -3247,67 +2191,78 @@ parse_VaryingValue (AAF_Iface* aafi, aafObject* VaryingValue, td* __ptd) } else if (aafUIDCmp (InterpolationIdentification, &AAFInterpolationDef_Log)) { interpolation = AAFI_INTERPOL_LOG; } else { - DUMP_OBJ_WARNING (aafi, VaryingValue, &__td, "Unknown value for InterpolationIdentification: Falling back to Linear"); + TRACE_OBJ_WARNING (aafi, VaryingValue, &__td, "Unknown InterpolationIdentification value: Falling back to Linear"); interpolation = AAFI_INTERPOL_LINEAR; } aafObject* Points = aaf_get_propertyValue (VaryingValue, PID_VaryingValue_PointList, &AAFTypeID_ControlPointStrongReferenceVector); - if (Points == NULL) { + if (!Points) { /* - * Some files like the ProTools and LogicPro break standard by having no + * Some AAF files from ProTools and LogicPro break standard by having no * PointList entry for AAFOperationDef_MonoAudioGain. */ - - DUMP_OBJ_WARNING (aafi, VaryingValue, &__td, "Missing PID_VaryingValue_PointList or list is empty"); + TRACE_OBJ_WARNING (aafi, VaryingValue, &__td, "Missing VaryingValue::PointList"); return -1; } - // if ( aafUIDCmp( VaryingValue->Parent->Parent->Class->ID, &AAFClassID_Transition ) ) if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioDissolve) && aafUIDCmp (ParamDef, &AAFParameterDef_Level)) { aafiTransition* Trans = aafi->ctx.current_transition; - Trans->flags |= interpolation; - Trans->pts_cnt_a = retrieve_ControlPoints (aafi, Points, &(Trans->time_a), &(Trans->value_a)); - - if (Trans->pts_cnt_a < 0) { - /* In that case, parse_OperationGroup() will set transition to default. */ - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve ControlPoints"); + if (!Trans) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Context current_transition not set"); return -1; } - // for ( int i = 0; i < Trans->pts_cnt_a; i++ ) { - // debug( "time_%i : %i/%i value_%i : %i/%i", i, Trans->time_a[i].numerator, Trans->time_a[i].denominator, i, Trans->value_a[i].numerator, Trans->value_a[i].denominator ); - // } + Trans->flags |= interpolation; - DUMP_OBJ (aafi, VaryingValue, &__td); + /* + * OperationGroup *might* contain a Parameter (ParameterDef_Level) specifying + * the fade curve. However, this parameter is optional regarding AAF_EditProtocol + * and there is most likely no implementation that exports custom fade curves. + * Thus, we only retrieve ParameterDef_Level to set interpolation, and we + * always set the fade as defined in AAF_EditProtocol, with only two points : + * + * « ParameterDef_Level (optional; default is a VaryingValue object + * with two control points: Value 0 at time 0, and value 1 at time 1) » + */ + + TRACE_OBJ (aafi, VaryingValue, &__td); } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioGain) && - aafUIDCmp (ParamDef, &AAFParameterDef_Amplitude)) { - aafiAudioGain* Gain = calloc (sizeof (aafiAudioGain), sizeof (unsigned char)); + (aafUIDCmp (ParamDef, &AAFParameterDef_Amplitude) || aafUIDCmp (ParamDef, aaf_get_ParamDefIDByName (aafi->aafd, "AvidControlClipRatio")))) { + aafiAudioGain* Gain = aafi_newAudioGain (aafi, 0, interpolation, NULL); - Gain->flags |= interpolation; - Gain->pts_cnt = retrieve_ControlPoints (aafi, Points, &Gain->time, &Gain->value); + if (!Gain) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not create new gain"); + return -1; + } - if (Gain->pts_cnt < 0) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve ControlPoints"); + int pts_cnt = retrieve_ControlPoints (aafi, Points, &Gain->time, &Gain->value); + + if (pts_cnt < 0) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve ControlPoints"); free (Gain); return -1; } + Gain->pts_cnt = (unsigned int)pts_cnt; + // for ( int i = 0; i < Gain->pts_cnt; i++ ) { // debug( "time_%i : %i/%i value_%i : %i/%i", i, Gain->time[i].numerator, Gain->time[i].denominator, i, Gain->value[i].numerator, Gain->value[i].denominator ); // } - /* If gain has 2 ControlPoints with both the same value, it means - * we have a flat gain curve. So we can assume constant gain here. */ + /* + * If gain has 2 ControlPoints with both the same value, it means + * we have a flat gain curve. So we can assume constant gain here. + */ if (Gain->pts_cnt == 2 && (Gain->value[0].numerator == Gain->value[1].numerator) && (Gain->value[0].denominator == Gain->value[1].denominator)) { - if (aafRationalToFloat (Gain->value[0]) == 1.0f) { + if (aafRationalToDouble (Gain->value[0]) == 1.0f) { /* - * Skipping any 1:1 gain allows not to miss any other actual gain (eg. Resolve 18.5.AAF) + * Skipping any 1:1 gain allows not to miss any other actual gain (eg. DR_Audio_Levels.aaf, Resolve 18.5.AAF) * │ 02412││ ├──◻ AAFClassID_OperationGroup (OpIdent: AAFOperationDef_MonoAudioGain; Length: 284630) err │ 03839││ │ ├──◻ AAFClassID_VaryingValue : : Value is continuous 1:1 (0db), skipping it. @@ -3322,7 +2277,7 @@ parse_VaryingValue (AAF_Iface* aafi, aafObject* VaryingValue, td* __ptd) │ 01342││ │ └──◻ AAFClassID_PCMDescriptor │ 01529││ │ └──◻ AAFClassID_NetworkLocator : file:///C:/Users/user/Desktop/libAAF/test/res/speech-sample.mp3 */ - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Value is continuous 1:1 (0db), skipping it"); + TRACE_OBJ_INFO (aafi, VaryingValue, &__td, "Value is continuous 1:1 (0db), skipping it."); aafi_freeAudioGain (Gain); return -1; } @@ -3331,133 +2286,673 @@ parse_VaryingValue (AAF_Iface* aafi, aafObject* VaryingValue, td* __ptd) Gain->flags |= AAFI_AUDIO_GAIN_VARIABLE; } - /* - * Loop through ancestors to find out who is the parent of OperationGroup. - * If it belongs to TimelineMobSlot, that means the Parameter is attached - * to a Track. If it belongs to a Component, the Parameter is attached to - * a clip. - * - * NOTE: We can't just check the Parent since we can have nested OperationGroups - * providing different effects like Pan, Gain, CustomFx.. Therefore looping - * is required. - */ - - aafObject* Obj = VaryingValue->Parent; // Start with the last OperationGroup - for (; Obj != NULL && aafUIDCmp (Obj->Class->ID, &AAFClassID_ContentStorage) == 0; Obj = Obj->Parent) - if (!aafUIDCmp (Obj->Class->ID, &AAFClassID_OperationGroup)) - break; - - if (aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot)) { - /* Track-based Gain */ - + if (aafi->ctx.current_opgroup_affect_track) { + /* + * Track-based Volume + */ + if (!aafi->ctx.current_track) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Current track not set, dropping this volume"); + aafi_freeAudioGain (Gain); + return -1; + } if (aafi->ctx.current_track->gain) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Track Gain was already set"); + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Track volume was already set"); aafi_freeAudioGain (Gain); return -1; } else { aafi->ctx.current_track->gain = Gain; - DUMP_OBJ (aafi, VaryingValue, &__td); + TRACE_OBJ (aafi, VaryingValue, &__td); } } else { - /* Clip-based Gain */ - + /* + * Clip-based Gain + * Gain is saved in context and it will be set to all OperationGroup descendent clips. + */ if (Gain->flags & AAFI_AUDIO_GAIN_CONSTANT) { if (aafi->ctx.current_clip_gain) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Clip gain was already set"); + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Clip gain was already set"); aafi_freeAudioGain (Gain); return -1; } else { aafi->ctx.current_clip_gain = Gain; - aafi->ctx.clips_using_gain = 0; - DUMP_OBJ (aafi, VaryingValue, &__td); + TRACE_OBJ (aafi, VaryingValue, &__td); } } else { - if (aafi->ctx.current_clip_automation) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Clip automation was already set"); + if (aafi->ctx.current_clip_variable_gain) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Clip automation was already set"); aafi_freeAudioGain (Gain); return -1; } else { - aafi->ctx.current_clip_automation = Gain; - aafi->ctx.clips_using_automation = 0; - DUMP_OBJ (aafi, VaryingValue, &__td); + aafi->ctx.current_clip_variable_gain = Gain; + TRACE_OBJ (aafi, VaryingValue, &__td); } } } } else if (aafUIDCmp (OperationIdentification, &AAFOperationDef_MonoAudioPan) && aafUIDCmp (ParamDef, &AAFParameterDef_Pan)) { - /* - * Pan automation shall be track-based. If an application has a different - * native representation (e.g., clip-based pan), it shall convert to and - * from its native representation when exporting and importing the composition. - */ + if (!aafi->ctx.current_opgroup_affect_track) { + /* + * « Pan automation shall be track-based. If an application has a different + * native representation (e.g., clip-based pan), it shall convert to and + * from its native representation when exporting and importing the composition. » + * + * NOTE: Never encountered clip-based pan AAF. + */ + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Pan shall be track based"); + return -1; + } - aafiAudioPan* Pan = calloc (sizeof (aafiAudioPan), sizeof (unsigned char)); + if (!aafi->ctx.current_track) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Current track not set"); + return -1; + } - Pan->flags |= AAFI_AUDIO_GAIN_VARIABLE; - Pan->flags |= interpolation; + if (aafi->ctx.current_track->pan) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Track Pan was already set"); + return -1; + } - Pan->pts_cnt = retrieve_ControlPoints (aafi, Points, &Pan->time, &Pan->value); + aafiAudioPan* Pan = aafi_newAudioPan (aafi, 0, interpolation, NULL); - if (Pan->pts_cnt < 0) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve ControlPoints"); + if (!Pan) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not create new pan"); + return -1; + } + + int pts_cnt = retrieve_ControlPoints (aafi, Points, &Pan->time, &Pan->value); + + if (pts_cnt < 0) { + TRACE_OBJ_ERROR (aafi, VaryingValue, &__td, "Could not retrieve ControlPoints"); free (Pan); return -1; } + Pan->pts_cnt = (unsigned int)pts_cnt; + // for ( int i = 0; i < Gain->pts_cnt; i++ ) { // debug( "time_%i : %i/%i value_%i : %i/%i", i, Gain->time[i].numerator, Gain->time[i].denominator, i, Gain->value[i].numerator, Gain->value[i].denominator ); // } - /* If Pan has 2 ControlPoints with both the same value, it means - * we have a constant Pan curve. So we can assume constant Pan here. */ + /* + * If Pan has 2 ControlPoints with both the same value, it means + * we have a constant Pan curve. So we can assume constant Pan here. + */ if (Pan->pts_cnt == 2 && (Pan->value[0].numerator == Pan->value[1].numerator) && (Pan->value[0].denominator == Pan->value[1].denominator)) { - // if ( aafRationalToFloat(Gain->value[0]) == 1.0f ) { - // /* - // * Pan is null, skip it. Skipping it allows not to set a useless gain then miss the real clip gain later (Resolve 18.5.AAF) - // */ - // aafi_freeAudioGain( Gain ); - // return -1; - // } Pan->flags |= AAFI_AUDIO_GAIN_CONSTANT; } else { Pan->flags |= AAFI_AUDIO_GAIN_VARIABLE; } - if (aafi->ctx.current_track->pan) { - DUMP_OBJ_ERROR (aafi, VaryingValue, &__td, "Track Pan was already set"); - aafi_freeAudioGain (Pan); - return -1; + aafi->ctx.current_track->pan = Pan; + TRACE_OBJ (aafi, VaryingValue, &__td); + } else { + TRACE_OBJ_NO_SUPPORT (aafi, VaryingValue, &__td); + } + + return 0; +} + +/* **************************************************************************** + * E s s e n c e D e s c r i p t o r + * **************************************************************************** + * + * EssenceDescriptor (abs) + * | + * |--> FileDescriptor (abs) + * | | + * | |--> WAVEDescriptor + * | |--> AIFCDescriptor + * | |--> SoundDescriptor + * | | | + * | | `--> PCMDescriptor + * | | + * | `--> DigitalImageDescriptor (abs) + * | | + * | `--> CDCIDescriptor + * | + * | + * |--> PhysicalDescriptor + * `--> TapeDescriptor + */ + +static int +parse_EssenceDescriptor (AAF_Iface* aafi, aafObject* EssenceDesc, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + + if (!aaf_get_property (EssenceDesc, PID_EssenceDescriptor_Locator)) + __td.eob = 1; + + if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_PCMDescriptor)) { + parse_PCMDescriptor (aafi, EssenceDesc, &__td); + } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_WAVEDescriptor)) { + parse_WAVEDescriptor (aafi, EssenceDesc, &__td); + } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_AIFCDescriptor)) { + parse_AIFCDescriptor (aafi, EssenceDesc, &__td); + } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_SoundDescriptor)) { + /* Compressed Audio (MP3, AAC ?). Not encountered yet (Davinci Resolve describes MP3 using PCMDescriptor...) */ + TRACE_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); + } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_AES3PCMDescriptor)) { + /* Not described in specs, not encountered yet. */ + TRACE_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); + } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_MultipleDescriptor)) { + /* + * A MultipleDescriptor contains a vector of FileDescriptor objects and is + * used when the file source consists of multiple tracks of essence (e.g MXF). + * Each essence track is described by a MobSlots object in the SourceMob and a + * FileDescriptor object. The FileDescriptor is linked to the MobSlot by + * setting the FileDescriptor::LinkedSlotID property equal to the + * MobSlot::SlotID property. + * + * -> test.aaf + * -> /test/private/thirdparty/2997fps-DFTC.aaf + */ + + TRACE_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); + } else if (aafUIDCmp (EssenceDesc->Class->ID, &AAFClassID_CDCIDescriptor)) { + parse_CDCIDescriptor (aafi, EssenceDesc, &__td); + } else { + TRACE_OBJ_NO_SUPPORT (aafi, EssenceDesc, &__td); + } + + /* + * Locators are a property of EssenceDescriptor. The property holds a vector of + * Locators object, that should provide information to help find a file that + * contains the essence (WAV, MXF, etc.) or to help find the physical media. + * + * A Locator can either be a NetworkLocator or a TextLocator. + * + * A NetworkLocator holds a URLString property : + * + * p.41 : Absolute Uniform Resource Locator (URL) complying with RFC 1738 or relative + * Uniform Resource Identifier (URI) complying with RFC 2396 for file containing + * the essence. If it is a relative URI, the base URI is determined from the URI + * of the AAF file itself. + * Informative note: A valid URL or URI uses a constrained character set and uses + * the / character as the path separator. + */ + + aafObject* Locator = NULL; + aafObject* Locators = aaf_get_propertyValue (EssenceDesc, PID_EssenceDescriptor_Locator, &AAFTypeID_LocatorStrongReferenceVector); + + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Locator, Locators, i, __td) + { + /* TODO retrieve all locators, then when searching file, try all parsed locators. */ + parse_Locator (aafi, Locator, &__td); + } + + return 0; +} + +static int +parse_PCMDescriptor (AAF_Iface* aafi, aafObject* PCMDescriptor, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + aafiAudioEssenceFile* audioEssenceFile = (aafiAudioEssenceFile*)aafi->ctx.current_audio_essence; + + if (!audioEssenceFile) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "aafi->ctx.current_audio_essence not set"); + return -1; + } + + audioEssenceFile->type = AAFI_ESSENCE_TYPE_PCM; + + /* Duration of the essence in sample units (not edit units !) */ + aafPosition_t* length = aaf_get_propertyValue (PCMDescriptor, PID_FileDescriptor_Length, &AAFTypeID_PositionType); + + if (!length) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing FileDescriptor::Length"); + return -1; + } + + audioEssenceFile->length = *length; + + uint32_t* channels = aaf_get_propertyValue (PCMDescriptor, PID_SoundDescriptor_Channels, &AAFTypeID_UInt32); + + if (!channels) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing SoundDescriptor::Channels"); + return -1; + } + + if (*channels >= USHRT_MAX) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "SoundDescriptor::Channels bigger than USHRT_MAX"); + return -1; + } + + audioEssenceFile->channels = *(uint16_t*)channels; + + aafRational_t* samplerate = aaf_get_propertyValue (PCMDescriptor, PID_FileDescriptor_SampleRate, &AAFTypeID_Rational); + + if (!samplerate) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing FileDescriptor::SampleRate"); + return -1; + } + + if (samplerate->denominator != 1) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "FileDescriptor::SampleRate should be integer but is %i/%i", samplerate->numerator, samplerate->denominator); + return -1; + } + + if (samplerate->numerator < 0) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "FileDescriptor::SampleRate value is invalid : %i", samplerate->numerator); + return -1; + } + + audioEssenceFile->samplerate = (uint32_t)samplerate->numerator; + + audioEssenceFile->samplerateRational->numerator = samplerate->numerator; + audioEssenceFile->samplerateRational->denominator = samplerate->denominator; + + uint32_t* samplesize = aaf_get_propertyValue (PCMDescriptor, PID_SoundDescriptor_QuantizationBits, &AAFTypeID_UInt32); + + if (!samplesize) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "Missing SoundDescriptor::QuantizationBits"); + return -1; + } + + if (*samplesize >= USHRT_MAX) { + TRACE_OBJ_ERROR (aafi, PCMDescriptor, &__td, "SoundDescriptor::QuantizationBits bigger than USHRT_MAX : %u", samplesize); + return -1; + } + + TRACE_OBJ (aafi, PCMDescriptor, &__td); + + audioEssenceFile->samplesize = *(uint16_t*)samplesize; + + return 0; +} + +static int +parse_WAVEDescriptor (AAF_Iface* aafi, aafObject* WAVEDescriptor, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + aafiAudioEssenceFile* audioEssenceFile = (aafiAudioEssenceFile*)aafi->ctx.current_audio_essence; + + if (!audioEssenceFile) { + TRACE_OBJ_ERROR (aafi, WAVEDescriptor, &__td, "aafi->ctx.current_audio_essence not set"); + return -1; + } + + audioEssenceFile->type = AAFI_ESSENCE_TYPE_WAVE; + + aafProperty* summary = aaf_get_property (WAVEDescriptor, PID_WAVEDescriptor_Summary); + + if (!summary) { + TRACE_OBJ_ERROR (aafi, WAVEDescriptor, &__td, "Missing WAVEDescriptor::Summary"); + return -1; + } + + audioEssenceFile->summary = summary; + + /* + * NOTE : Summary is parsed later in "post-processing" aafi_retrieveData(), + * to be sure clips and essences are linked, so we are able to fallback on + * essence stream in case summary does not contain the full header part. + * + * TODO parse it here + */ + + TRACE_OBJ (aafi, WAVEDescriptor, &__td); + + return 0; +} + +static int +parse_AIFCDescriptor (AAF_Iface* aafi, aafObject* AIFCDescriptor, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + aafiAudioEssenceFile* audioEssenceFile = (aafiAudioEssenceFile*)aafi->ctx.current_audio_essence; + + if (!audioEssenceFile) { + TRACE_OBJ_ERROR (aafi, AIFCDescriptor, &__td, "aafi->ctx.current_audio_essence not set"); + return -1; + } + + audioEssenceFile->type = AAFI_ESSENCE_TYPE_AIFC; + + aafProperty* summary = aaf_get_property (AIFCDescriptor, PID_AIFCDescriptor_Summary); + + if (!summary) { + TRACE_OBJ_ERROR (aafi, AIFCDescriptor, &__td, "Missing AIFCDescriptor::Summary"); + return -1; + } + + audioEssenceFile->summary = summary; + + /* + * NOTE : Summary is parsed later in "post-processing" aafi_retrieveData(), + * to be sure clips and essences are linked, so we are able to fallback on + * essence stream in case summary does not contain the full header part. + */ + + TRACE_OBJ (aafi, AIFCDescriptor, &__td); + + return 0; +} + +static int +parse_DigitalImageDescriptor (AAF_Iface* aafi, aafObject* DIDescriptor, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + /* TODO parse and save content to videoEssenceFile */ + + aafiVideoEssence* videoEssenceFile = aafi->ctx.current_video_essence; + + if (!videoEssenceFile) { + TRACE_OBJ_ERROR (aafi, DIDescriptor, &__td, "aafi->ctx.current_video_essence not set"); + return -1; + } + + /* + * « Informative note: In the case of picture essence, the Sample Rate is usually the frame rate. The value should be + * numerically exact, for example {25,1} or {30000, 1001}. » + * + * « Informative note: Care should be taken if a sample rate of {2997,100} is encountered, since this may have been intended + * as a (mistaken) approximation to the exact value. » + */ + + aafRational_t* framerate = aaf_get_propertyValue (DIDescriptor, PID_FileDescriptor_SampleRate, &AAFTypeID_Rational); + + if (!framerate) { + TRACE_OBJ_ERROR (aafi, DIDescriptor, &__td, "Missing FileDescriptor::SampleRate (framerate)"); + return -1; + } + + videoEssenceFile->framerate = framerate; + + debug ("Video framerate : %i/%i", framerate->numerator, framerate->denominator); + + /* + * All mandatory properties below are treated as optional, because we assume that + * video will be an external file so we are not using those, and because some AAF + * implementations does not even set those mandatory properties (eg. Davinci Resolve). + * + * TODO: parse PID_FileDescriptor_Length ? + */ + + return 0; +} + +static int +parse_CDCIDescriptor (AAF_Iface* aafi, aafObject* CDCIDescriptor, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + /* TODO parse CDCI class */ + + int rc = parse_DigitalImageDescriptor (aafi, CDCIDescriptor, __ptd); + + if (!rc) + TRACE_OBJ (aafi, CDCIDescriptor, &__td); + + return rc; +} + +/* + * Locator (abs) + * | + * ,---------------. + * | | + * NetworkLocator TextLocator + */ + +static int +parse_Locator (AAF_Iface* aafi, aafObject* Locator, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + __td.eob = 1; + + if (aafUIDCmp (Locator->Class->ID, &AAFClassID_NetworkLocator)) { + parse_NetworkLocator (aafi, Locator, &__td); + } else if (aafUIDCmp (Locator->Class->ID, &AAFClassID_TextLocator)) { + /* + * A TextLocator object provides information to the user to help locate the file + * containing the essence or to locate the physical media. The TextLocator is not + * intended for applications to use without user intervention. + * + * Not encountered yet. + */ + + TRACE_OBJ_NO_SUPPORT (aafi, Locator, &__td); + + char* name = aaf_get_propertyValue (Locator, PID_TextLocator_Name, &AAFTypeID_String); + debug ("Got an AAFClassID_TextLocator : \"%s\"", name); + free (name); + } else { + TRACE_OBJ_NO_SUPPORT (aafi, Locator, &__td); + } + + return 0; +} + +static int +parse_NetworkLocator (AAF_Iface* aafi, aafObject* NetworkLocator, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 0); + + /* + * This holds an URI pointing to the essence file, when it is not embedded. + * However, sometimes it holds an URI to the AAF file itself when essence is + * embedded so it's not a reliable way to guess if essence is embedded or not. + */ + + char* original_file_path = aaf_get_propertyValue (NetworkLocator, PID_NetworkLocator_URLString, &AAFTypeID_String); + + if (original_file_path == NULL) { + TRACE_OBJ_ERROR (aafi, NetworkLocator, &__td, "Missing NetworkLocator::URLString"); + goto err; + } + + if (aafi->ctx.current_audio_essence) { + if (aafi->ctx.current_audio_essence->original_file_path) { + TRACE_OBJ_ERROR (aafi, NetworkLocator, &__td, "File path was already set"); + goto err; } else { - aafi->ctx.current_track->pan = Pan; - DUMP_OBJ (aafi, VaryingValue, &__td); + aafi->ctx.current_audio_essence->original_file_path = original_file_path; + } + } else if (aafi->ctx.current_video_essence) { + if (aafi->ctx.current_video_essence->original_file_path) { + TRACE_OBJ_ERROR (aafi, NetworkLocator, &__td, "File path was already set"); + goto err; + } else { + aafi->ctx.current_video_essence->original_file_path = original_file_path; } } else { - DUMP_OBJ (aafi, VaryingValue, &__td); + TRACE_OBJ_ERROR (aafi, NetworkLocator, &__td, "No current essence set"); + goto err; } + TRACE_OBJ (aafi, NetworkLocator, &__td); + + return 0; + +err: + free (original_file_path); + + return -1; +} + +static int +parse_EssenceData (AAF_Iface* aafi, aafObject* EssenceData, td* __ptd) +{ + struct trace_dump __td; + __td_set (__td, __ptd, 1); + __td.eob = 1; + + int rc = 0; + + char* streamName = NULL; + char* dataPath = NULL; + + aafiAudioEssenceFile* audioEssenceFile = (aafiAudioEssenceFile*)aafi->ctx.current_audio_essence; + + if (!audioEssenceFile) { + TRACE_OBJ_ERROR (aafi, EssenceData, &__td, "aafi->ctx.current_audio_essence not set"); + return -1; + } + + streamName = aaf_get_propertyValue (EssenceData, PID_EssenceData_Data, &AAFTypeID_String); + + if (!streamName) { + TRACE_OBJ_ERROR (aafi, EssenceData, &__td, "Missing EssenceData::Data"); + goto err; + } + + char* path = aaf_get_ObjectPath (EssenceData); + + if (!path) { + TRACE_OBJ_ERROR (aafi, EssenceData, &__td, "Could not retrieve EssenceData node path"); + goto err; + } + + dataPath = laaf_util_build_path (AAF_DIR_SEP_STR, path, streamName, NULL); + + if (!dataPath) { + TRACE_OBJ_ERROR (aafi, EssenceData, &__td, "Could not build Data stream path"); + goto err; + } + + cfbNode* DataNode = cfb_getNodeByPath (aafi->aafd->cfbd, dataPath, 0); + + if (!DataNode) { + TRACE_OBJ_ERROR (aafi, EssenceData, &__td, "Could not retrieve Data stream node: %s", dataPath); + goto err; + } + + TRACE_OBJ (aafi, EssenceData, &__td); + + debug ("Embedded data stream : %s", dataPath); + + audioEssenceFile->node = DataNode; + audioEssenceFile->is_embedded = 1; + + rc = 0; + + goto end; + +err: + rc = -1; + +end: + + free (streamName); + free (dataPath); + + return rc; +} + +static int +retrieve_UserComments (AAF_Iface* aafi, aafObject* UserComments, aafiMetaData** metadataList) +{ + aafObject* UserComment = NULL; + + int error = 0; + + AAF_foreach_ObjectInSet (&UserComment, UserComments, NULL) + { + char* text = NULL; + char* name = NULL; + + if (!aafUIDCmp (UserComment->Class->ID, &AAFClassID_TaggedValue)) { + warning ("Parsing UserComments: Expected TaggedValue but got %s", aaft_ClassIDToText (aafi->aafd, UserComment->Class->ID)); + goto UserCommentError; + } + + name = aaf_get_propertyValue (UserComment, PID_TaggedValue_Name, &AAFTypeID_String); + + if (!name) { + warning ("Parsing UserComments: Missing TaggedValue::Name"); + goto UserCommentError; + } + + aafIndirect_t* Indirect = aaf_get_propertyValue (UserComment, PID_TaggedValue_Value, &AAFTypeID_Indirect); + + if (!Indirect) { + warning ("Parsing UserComments: Missing TaggedValue::Value"); + goto UserCommentError; + } + + text = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_String); + + if (!text) { + warning ("Parsing UserComments: Could not retrieve Indirect value for TaggedValue::Value"); + goto UserCommentError; + } + + aafiMetaData* Comment = aafi_newMetadata (aafi, metadataList); + + if (!Comment) { + warning ("Parsing UserComments: Could not create new UserComment"); + goto UserCommentError; + } + + Comment->name = name; + Comment->text = text; + + continue; + + UserCommentError: + + error++; + + free (name); + free (text); + } + + if (error) + return -1; + return 0; } static int retrieve_ControlPoints (AAF_Iface* aafi, aafObject* Points, aafRational_t* times[], aafRational_t* values[]) { + /* + * We do not handle trace here, because there could possibly be hundreds of + * ControlPoints to print, plus retrieve_ControlPoints() is being called before + * VaryingValue Object is logged. + */ + *times = calloc (Points->Header->_entryCount, sizeof (aafRational_t)); *values = calloc (Points->Header->_entryCount, sizeof (aafRational_t)); + if (!*times || !*values) { + error ("Out of memory"); + return -1; + } + aafObject* Point = NULL; unsigned int i = 0; - aaf_foreach_ObjectInSet (&Point, Points, &AAFClassID_ControlPoint) + AAF_foreach_ObjectInSet (&Point, Points, NULL) { + if (!aafUIDCmp (Point->Class->ID, &AAFClassID_ControlPoint)) { + error ("Object is not AAFClassID_ControlPoint : %s", aaft_ClassIDToText (aafi->aafd, Point->Class->ID)); + continue; + } + aafRational_t* time = aaf_get_propertyValue (Point, PID_ControlPoint_Time, &AAFTypeID_Rational); - if (time == NULL) { - // aafi_trace_obj( aafi, Points, ANSI_COLOR_RED ); - error ("Missing ControlPoint::Time."); + if (!time) { + error ("Missing ControlPoint::Time"); free (*times); *times = NULL; @@ -3467,13 +2962,10 @@ retrieve_ControlPoints (AAF_Iface* aafi, aafObject* Points, aafRational_t* times return -1; } - // aafRational_t *value = aaf_get_propertyIndirectValue( Point, PID_ControlPoint_Value, &AAFTypeID_Rational ); - aafIndirect_t* Indirect = aaf_get_propertyValue (Point, PID_ControlPoint_Value, &AAFTypeID_Indirect); - if (Indirect == NULL) { - // DUMP_OBJ_ERROR( aafi, ConstantValue, &__td, "Missing PID_ConstantValue_Value or wrong AAFTypeID" ); - error ("Missing ControlPoint::Value or wrong AAFTypeID"); + if (!Indirect) { + error ("Missing Indirect ControlPoint::Value"); free (*times); *times = NULL; @@ -3485,9 +2977,8 @@ retrieve_ControlPoints (AAF_Iface* aafi, aafObject* Points, aafRational_t* times aafRational_t* value = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Rational); - if (value == NULL) { - // aafi_trace_obj( aafi, Points, ANSI_COLOR_RED ); - error ("Could not retrieve Indirect value for PID_ControlPoint_Value"); + if (!value) { + error ("Could not retrieve Indirect value for ControlPoint::Value"); free (*times); *times = NULL; @@ -3504,480 +2995,11 @@ retrieve_ControlPoints (AAF_Iface* aafi, aafObject* Points, aafRational_t* times } if (Points->Header->_entryCount != i) { - // aafi_trace_obj( aafi, Points, ANSI_COLOR_YELLOW ); - warning ("Points _entryCount (%i) does not match iteration (%i).", Points->Header->_entryCount, i); - return i; + warning ("ControlPoints _entryCount (%i) does not match iteration (%i).", Points->Header->_entryCount, i); + return (int)i; } - // aafi_trace_obj( aafi, Points, ANSI_COLOR_MAGENTA ); - - return Points->Header->_entryCount; -} - -/* **************************************************************************** - * M o b - * **************************************************************************** - - * Mob (abs) - * | - * |--> CompositionMob - * |--> MasterMob - * `--> SourceMob - */ - -static int -parse_Mob (AAF_Iface* aafi, aafObject* Mob) -{ - // int dl = DUMP_INIT(aafi); - // __td(NULL); - static td __td; - __td.fn = __LINE__; - __td.pfn = 0; - __td.lv = 0; - __td.ll = calloc (1024, sizeof (int)); /* TODO free */ - __td.ll[0] = 0; - // aafi->ctx.trace_leveloop = __td.ll; // keep track of __td.ll for free - - int rc = 0; - - aafObject* MobSlots = aaf_get_propertyValue (Mob, PID_Mob_Slots, &AAFTypeID_MobSlotStrongReferenceVector); - - if (MobSlots == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, Mob, &__td, "Missing PID_Mob_Slots"); - goto err; - } - - if (aafUIDCmp (Mob->Class->ID, &AAFClassID_CompositionMob)) { - aafUID_t* UsageCode = aaf_get_propertyValue (Mob, PID_Mob_UsageCode, &AAFTypeID_UsageType); - - if (aafUIDCmp (UsageCode, &AAFUsage_AdjustedClip)) { - DUMP_OBJ_ERROR (aafi, Mob, &__td, "Skipping AAFUsage_AdjustedClip"); - goto err; - } - - parse_CompositionMob (aafi, Mob, &__td); - } else if (aafUIDCmp (Mob->Class->ID, &AAFClassID_MasterMob)) { - DUMP_OBJ (aafi, Mob, &__td); - } else if (aafUIDCmp (Mob->Class->ID, &AAFClassID_SourceMob)) { - DUMP_OBJ (aafi, Mob, &__td); - } - - /* - * Loops through MobSlots - */ - - aafObject* MobSlot = NULL; - - int i = 0; - - aaf_foreach_ObjectInSet (&MobSlot, MobSlots, NULL) - { - __td.ll[__td.lv] = MobSlots->Header->_entryCount - i++; - parse_MobSlot (aafi, MobSlot, &__td); - } - - goto end; - -err: - rc = -1; - -end: - free (__td.ll); - - return rc; -} - -static int -parse_CompositionMob (AAF_Iface* aafi, aafObject* CompoMob, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 0); - - DUMP_OBJ (aafi, CompoMob, &__td); - - aafi->compositionName = aaf_get_propertyValue (CompoMob, PID_Mob_Name, &AAFTypeID_String); /* opt */ - - aafObject* UserComment = NULL; - aafObject* UserComments = aaf_get_propertyValue (CompoMob, PID_Mob_UserComments, &AAFTypeID_TaggedValueStrongReferenceVector); /* opt */ - - aaf_foreach_ObjectInSet (&UserComment, UserComments, NULL) - { - /* TODO: implement retrieve_TaggedValue() ? */ - - wchar_t* name = aaf_get_propertyValue (UserComment, PID_TaggedValue_Name, &AAFTypeID_String); - - if (name == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, UserComment, &__td, "Missing PID_TaggedValue_Name"); - continue; - } - - aafIndirect_t* Indirect = aaf_get_propertyValue (UserComment, PID_TaggedValue_Value, &AAFTypeID_Indirect); - - if (Indirect == NULL) { - DUMP_OBJ_ERROR (aafi, UserComment, &__td, "Missing PID_TaggedValue_Value"); - continue; - } - - wchar_t* text = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_String); - - if (text == NULL) { - DUMP_OBJ_ERROR (aafi, UserComment, &__td, "Could not retrieve Indirect value for PID_TaggedValue_Value"); - continue; - } - - aafiUserComment* Comment = aafi_newUserComment (aafi, &aafi->Comments); - - Comment->name = name; - Comment->text = text; - } - - return 0; -} - -static int -parse_SourceMob (AAF_Iface* aafi, aafObject* SourceMob, td* __ptd) -{ - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - __td.hc = 1; - - /* TODO find a better way to check if we're parsing audio */ - - // aafUID_t *DataDefinition = get_Component_DataDefinition( aafi, SourceMob ); - // - // if ( DataDefinition == NULL ) /* req */ { - // error( "Could not retrieve MobSlot::Segment DataDefinition." ); - // return -1; - // } - // - // - // - // if ( aafUIDCmp( DataDefinition, &AAFDataDef_Sound ) || - // aafUIDCmp( DataDefinition, &AAFDataDef_LegacySound ) ) - - if (aafi->ctx.current_essence) { - if (aafi->ctx.current_essence == NULL) { - DUMP_OBJ_ERROR (aafi, SourceMob, &__td, "ctx->current_essence no set"); - return -1; - } - - aafiAudioEssence* audioEssence = (aafiAudioEssence*)aafi->ctx.current_essence; - - aafMobID_t* MobID = aaf_get_propertyValue (SourceMob, PID_Mob_MobID, &AAFTypeID_MobIDType); - - if (MobID == NULL) { - DUMP_OBJ_ERROR (aafi, SourceMob, &__td, "Missing PID_Mob_MobID"); - return -1; - } - - memcpy (audioEssence->umid, MobID, sizeof (aafMobID_t)); - - aafTimeStamp_t* CreationTime = aaf_get_propertyValue (SourceMob, PID_Mob_CreationTime, &AAFTypeID_TimeStamp); - - if (CreationTime == NULL) { - DUMP_OBJ_ERROR (aafi, SourceMob, &__td, "Missing PID_Mob_CreationTime"); - return -1; - } - - snprintf (audioEssence->originationDate, sizeof (audioEssence->originationDate), "%04u:%02u:%02u", - (CreationTime->date.year <= 9999) ? CreationTime->date.year : 0, - (CreationTime->date.month <= 99) ? CreationTime->date.month : 0, - (CreationTime->date.day <= 99) ? CreationTime->date.day : 0); - - snprintf (audioEssence->originationTime, sizeof (audioEssence->originationTime), "%02u:%02u:%02u", - (CreationTime->time.hour <= 99) ? CreationTime->time.hour : 0, - (CreationTime->time.minute <= 99) ? CreationTime->time.minute : 0, - (CreationTime->time.second <= 99) ? CreationTime->time.second : 0); - } - - aafObject* EssenceDesc = aaf_get_propertyValue (SourceMob, PID_SourceMob_EssenceDescription, &AAFTypeID_EssenceDescriptorStrongReference); - - if (EssenceDesc == NULL) { - DUMP_OBJ_ERROR (aafi, SourceMob, &__td, "Could not retrieve EssenceDescription"); - return -1; - } - - DUMP_OBJ (aafi, SourceMob, &__td); - - parse_EssenceDescriptor (aafi, EssenceDesc, &__td); - - return 0; -} - -static aafiAudioTrack* -get_audio_track_by_tracknumber (AAF_Iface* aafi, int tracknumber) -{ - aafiAudioTrack* audioTrack = NULL; - int count = 0; - - foreach_audioTrack (audioTrack, aafi) - { - if (++count == tracknumber) - return audioTrack; - } - - return NULL; -} - -/* **************************************************************************** - * M o b S l o t - * **************************************************************************** - * - * MobSlot (abs) - * | - * |--> TimelineMobSlot - * |--> EventMobSlot - * `--> StaticMobSlot - */ - -static int -parse_MobSlot (AAF_Iface* aafi, aafObject* MobSlot, td* __ptd) -{ - // debug( "MS : %p", __ptd->ll ); - - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - __td.hc = 1; - - aafObject* Segment = aaf_get_propertyValue (MobSlot, PID_MobSlot_Segment, &AAFTypeID_SegmentStrongReference); - - if (Segment == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "Missing PID_MobSlot_Segment"); - return -1; - } - - aafUID_t* DataDefinition = get_Component_DataDefinition (aafi, Segment); - - if (DataDefinition == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "Could not retrieve DataDefinition"); - return -1; - } - - if (aafUIDCmp (MobSlot->Class->ID, &AAFClassID_TimelineMobSlot)) { - /* - * Each TimelineMobSlot represents a track, either audio or video. - * - * The Timeline MobSlot::Segment should hold a Sequence of Components. - * This Sequence represents the timeline track. Therefore, each SourceClip - * contained in the Sequence::Components represents a clip on the timeline. - * - * CompositionMob can have TimelineMobSlots, StaticMobSlots, EventMobSlots - */ - - aafRational_t* edit_rate = aaf_get_propertyValue (MobSlot, PID_TimelineMobSlot_EditRate, &AAFTypeID_Rational); - - if (edit_rate == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "Missing PID_TimelineMobSlot_EditRate"); - return -1; - } - - if (aafUIDCmp (/*aafi->ctx.*/ MobSlot->Parent->Class->ID, &AAFClassID_CompositionMob)) { - /* - * There should be only one Composition, since a CompositionMob represents the overall - * composition (i.e project). Observations on files confirm that. - * - * However, the AAF Edit Protocol says that there could be multiple CompositionMobs - * (Mob::UsageCode TopLevel), containing other CompositionMobs (Mob::UsageCode LowerLevel). - * This was not encountered yet, even on Avid exports with AAF_EditProtocol enabled. - * - * TODO: update note - * TODO: implement multiple TopLevel compositions support - */ - - if (aafUIDCmp (DataDefinition, &AAFDataDef_Sound) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacySound)) { - /* - * p.11 : In a CompositionMob or MasterMob, PhysicalTrackNumber is the - * output channel number that the MobSlot should be routed to when played. - */ - - if (!aafi->ctx.is_inside_derivation_chain) { - uint32_t tracknumber = 0; - uint32_t* track_num = aaf_get_propertyValue (MobSlot, PID_MobSlot_PhysicalTrackNumber, &AAFTypeID_UInt32); - - if (track_num == NULL) { /* opt */ - tracknumber = aafi->Audio->track_count + 1; - } else { - tracknumber = *track_num; - } - - aafiAudioTrack* track = get_audio_track_by_tracknumber (aafi, tracknumber); - - if (!track) { - track = aafi_newAudioTrack (aafi); - } - - track->number = tracknumber; - - aafi->Audio->track_count += 1; - - aafi->ctx.current_track = track; - - track->name = aaf_get_propertyValue (MobSlot, PID_MobSlot_SlotName, &AAFTypeID_String); - - track->edit_rate = edit_rate; - } - - // aaf_dump_ObjectProperties( aafi->aafd, MobSlot ); - - /* - * The following seems to be ProTools proprietary. - * If a track is multi-channel, it specifies its format : 2 (stereo), 6 (5.1) or 8 (7.1). - * - * In the current implementation we don't need this. We guess the format at the OperationGroup level with the - * AAFOperationDef_AudioChannelCombiner OperationDefinition, which also looks to be ProTools specific. - */ - - // aafPID_t PIDTimelineMobAttributeList = aaf_get_PropertyIDByName( aafi->aafd, "TimelineMobAttributeList" ); - // // aafPID_t PIDTimelineMobAttributeList = aaf_get_PropertyIDByName( aafi->aafd, "MobAttributeList" ); - // - // if ( PIDTimelineMobAttributeList != 0 ) { - // aafObject *TaggedValues = aaf_get_propertyValue( aafi->ctx.MobSlot, PIDTimelineMobAttributeList ); - // aafObject *TaggedValue = NULL; - // - // aaf_foreach_ObjectInSet( &TaggedValue, TaggedValues, NULL ) { - // char *name = aaf_get_propertyValueText( TaggedValue, PID_TaggedValue_Name ); - // - // debug( "TaggedValue %s", name ); - // - // if ( strncmp( "_TRACK_FORMAT", name, 13 ) == 0 ) { - // uint32_t *format = (uint32_t*)aaf_get_propertyIndirectValue( TaggedValue, PID_TaggedValue_Value ); - // - // if ( format != NULL ) - // aafi->ctx.current_track->format = *format; - // - // debug( "Format : %u", aafi->ctx.current_track->format ); - // } - // - // free( name ); - // } - // } - - DUMP_OBJ (aafi, MobSlot, &__td); - - /* Reset timeline position */ - // aafi->ctx.current_track->current_pos = 0; - - aafi_parse_Segment (aafi, Segment, &__td); - } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Timecode) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacyTimecode)) { - DUMP_OBJ (aafi, MobSlot, &__td); - aafi_parse_Segment (aafi, Segment, &__td); - } else if (aafUIDCmp (DataDefinition, &AAFDataDef_Picture) || - aafUIDCmp (DataDefinition, &AAFDataDef_LegacyPicture)) { - // debug( "%ls", aaft_ClassIDToText(aafi->aafd, Segment->Class->ID) ); - - /* ADP NESTED SCOPE */ - - // aafObject *NSSegment = NULL; - // aafObject *NSSegments = aaf_get_propertyValue( Segment, PID_NestedScope_Slots ); - // - // aaf_foreach_ObjectInSet( &NSSegment, NSSegments, NULL ) { - // aaf_dump_ObjectProperties( aafi->aafd, NSSegment ); - // } - - if (aafi->Video->Tracks) { - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "Current implementation supports only one video track"); - return -1; - } - - /* - * p.11 : In a CompositionMob or MasterMob, PhysicalTrackNumber is the output channel number that the - * MobSlot should be routed to when played. - */ - - uint32_t tracknumber = 0; - uint32_t* track_num = aaf_get_propertyValue (MobSlot, PID_MobSlot_PhysicalTrackNumber, &AAFTypeID_UInt32); - - if (track_num == NULL) { /* opt */ - tracknumber = 1; /* Current implementation supports only one video track. */ - } else { - tracknumber = *track_num; - } - - aafiVideoTrack* track = aafi_newVideoTrack (aafi); - - track->number = tracknumber; - - track->name = aaf_get_propertyValue (MobSlot, PID_MobSlot_SlotName, &AAFTypeID_String); - - track->edit_rate = edit_rate; - - DUMP_OBJ (aafi, MobSlot, &__td); - - aafi_parse_Segment (aafi, Segment, &__td); - - /* update session_end if needed */ - // session_end = ( aafi->ctx.current_track->current_pos > session_end ) ? aafi->ctx.current_track->current_pos : session_end; - } else { - DUMP_OBJ_NO_SUPPORT (aafi, MobSlot, &__td); - } - - } else if (aafUIDCmp (MobSlot->Parent->Class->ID, &AAFClassID_MasterMob)) { - /* Retrieve Essences */ - - // if ( aafUIDCmp( DataDefinition, &AAFDataDef_Sound ) || - // aafUIDCmp( DataDefinition, &AAFDataDef_LegacySound ) ) - // { - DUMP_OBJ (aafi, MobSlot, &__td); - aafi_parse_Segment (aafi, Segment, &__td); - - // } - // else if ( aafUIDCmp( DataDefinition, &AAFDataDef_Picture ) || - // aafUIDCmp( DataDefinition, &AAFDataDef_LegacyPicture ) ) - // { - // aafi_parse_Segment( aafi, Segment ); - // - // retrieve_EssenceData( aafi ); - // } - // else { - // aafi_trace_obj( aafi, MobSlot, ANSI_COLOR_YELLOW ); - // debug( "%ls", aaft_DataDefToText( aafi->aafd, DataDefinition ) ); - // } - } else if (aafUIDCmp (MobSlot->Parent->Class->ID, &AAFClassID_SourceMob)) { - if (aafi->ctx.current_essence != NULL) { - aafiAudioEssence* audioEssence = (aafiAudioEssence*)aafi->ctx.current_essence; - - aafPosition_t* Origin = aaf_get_propertyValue (MobSlot, PID_TimelineMobSlot_Origin, &AAFTypeID_PositionType); - - if (Origin == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "Missing PID_TimelineMobSlot_Origin"); - return -1; - } - - audioEssence->timeReference = *Origin; - audioEssence->mobSlotEditRate = edit_rate; - - DUMP_OBJ (aafi, MobSlot, &__td); - } else { - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "aafi->ctx.current_essence no set"); - } - } else { - /* Not in CompositionMob, MasterMob, or SourceMob. Can not happen. */ - DUMP_OBJ_NO_SUPPORT (aafi, MobSlot, &__td); - } - - } else if (aafUIDCmp (MobSlot->Class->ID, &AAFClassID_EventMobSlot)) { - aafRational_t* edit_rate = aaf_get_propertyValue (MobSlot, PID_EventMobSlot_EditRate, &AAFTypeID_Rational); - - if (edit_rate == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, MobSlot, &__td, "Missing PID_EventMobSlot_EditRate"); - return -1; - } - - aafi->ctx.current_markers_edit_rate = edit_rate; - - DUMP_OBJ (aafi, MobSlot, &__td); - - return aafi_parse_Segment (aafi, Segment, &__td); - } else { - /* Not AAFClassID_TimelineMobSlot */ - DUMP_OBJ_NO_SUPPORT (aafi, MobSlot, &__td); - } - - return 0; + return (int)Points->Header->_entryCount; } int @@ -3985,48 +3007,57 @@ aafi_retrieveData (AAF_Iface* aafi) { /* this __td is only here for debug/error, normal trace is printed from parse_Mob() */ static td __td; - __td.fn = __LINE__; - __td.pfn = 0; - __td.lv = 0; - __td.ll = calloc (1024, sizeof (int)); + __td.fn = __LINE__; + __td.pfn = 0; + __td.lv = 0; + __td.ll = calloc (1024, sizeof (int)); + if (!__td.ll) { + error ("Out of memory"); + return -1; + } __td.ll[0] = 0; int compositionMobParsed = 0; aafObject* Mob = NULL; - aaf_foreach_ObjectInSet (&Mob, aafi->aafd->Mobs, NULL) + uint32_t i = 0; + AAFI_foreach_ObjectInSet (&Mob, aafi->aafd->Mobs, i, __td) { if (aafUIDCmp (Mob->Class->ID, &AAFClassID_MasterMob) || aafUIDCmp (Mob->Class->ID, &AAFClassID_SourceMob)) { - // DUMP_OBJ_WARNING( aafi, Mob, &__td, "PRINTS FOR DEBUG ONLY: Will be parsed later" ); + // TRACE_OBJ_WARNING( aafi, Mob, &__td, " PRINTS FOR DEBUG ONLY: Will be parsed later" ); continue; } if (!aafUIDCmp (Mob->Class->ID, &AAFClassID_CompositionMob)) { /* there should not be anything other than MasterMob, SourceMob or CompositionMob */ - DUMP_OBJ_NO_SUPPORT (aafi, Mob, &__td); + TRACE_OBJ_NO_SUPPORT (aafi, Mob, &__td); continue; } aafUID_t* UsageCode = aaf_get_propertyValue (Mob, PID_Mob_UsageCode, &AAFTypeID_UsageType); - if (aafUIDCmp (aafi->aafd->Header.OperationalPattern, &AAFOPDef_EditProtocol) && - !aafUIDCmp (UsageCode, &AAFUsage_TopLevel)) { + if (!aafUIDCmp (UsageCode, &AAFUsage_TopLevel) && (aafUIDCmp (aafi->aafd->Header.OperationalPattern, &AAFOPDef_EditProtocol) || UsageCode)) { /* * If we run against AAFOPDef_EditProtocol, we process only TopLevels CompositionMobs. * If there is more than one, we have multiple Compositions in a single AAF. */ + // TRACE_OBJ_WARNING( aafi, Mob, &__td, " PRINTS FOR DEBUG ONLY: Will be parsed later" ); continue; } if (compositionMobParsed) { - DUMP_OBJ_ERROR (aafi, Mob, &__td, "Multiple top level CompositionMob not supported yet"); + TRACE_OBJ_ERROR (aafi, Mob, &__td, "Multiple top level CompositionMob not supported yet"); continue; } RESET_CONTEXT (aafi->ctx); - parse_Mob (aafi, Mob); + __td.fn = __LINE__; + __td.pfn = 0; + __td.lv = 0; + + parse_Mob (aafi, Mob, &__td); if (aafUIDCmp (UsageCode, &AAFUsage_TopLevel)) { compositionMobParsed = 1; @@ -4039,10 +3070,10 @@ aafi_retrieveData (AAF_Iface* aafi) /* TODO, shouldn't we leave aafi->Timecode as NULL ? */ warning ("No timecode found in file. Setting to 00:00:00:00 @ 25fps"); - aafiTimecode* tc = calloc (sizeof (aafiTimecode), sizeof (unsigned char)); + aafiTimecode* tc = calloc (1, sizeof (aafiTimecode)); - if (tc == NULL) { - error ("calloc() : %s", strerror (errno)); + if (!tc) { + error ("Out of memory"); return -1; } @@ -4056,20 +3087,20 @@ aafi_retrieveData (AAF_Iface* aafi) /* Post processing */ - aafiAudioEssence* audioEssence = NULL; + aafiAudioEssenceFile* audioEssenceFile = NULL; - foreachEssence (audioEssence, aafi->Audio->Essences) + AAFI_foreachAudioEssenceFile (aafi, audioEssenceFile) { - if (!audioEssence->is_embedded) { - audioEssence->usable_file_path = aafi_locate_external_essence_file (aafi, audioEssence->original_file_path, aafi->ctx.options.media_location); + if (!audioEssenceFile->is_embedded) { + audioEssenceFile->usable_file_path = aafi_locate_external_essence_file (aafi, audioEssenceFile->original_file_path, aafi->ctx.options.media_location); - if (audioEssence->usable_file_path == NULL) { - error ("Could not locate external audio essence file '%ls'", audioEssence->original_file_path); + if (audioEssenceFile->usable_file_path == NULL) { + warning ("Could not locate external audio essence file '%s'", audioEssenceFile->original_file_path); } } - if (audioEssence->summary || audioEssence->usable_file_path) { - aafi_parse_audio_essence (aafi, audioEssence); + if (audioEssenceFile->summary || audioEssenceFile->usable_file_path) { + aafi_parse_audio_essence (aafi, audioEssenceFile); } } @@ -4079,45 +3110,45 @@ aafi_retrieveData (AAF_Iface* aafi) uint32_t maxOccurence = 0; - foreachEssence (audioEssence, aafi->Audio->Essences) + AAFI_foreachAudioEssenceFile (aafi, audioEssenceFile) { - uint32_t count = 1; - aafiAudioEssence* ae = NULL; + uint32_t count = 1; + aafiAudioEssenceFile* ae = NULL; - if (audioEssence->samplerate == aafi->Audio->samplerate && - audioEssence->samplesize == aafi->Audio->samplesize) { + if (audioEssenceFile->samplerate == aafi->Audio->samplerate && + audioEssenceFile->samplesize == aafi->Audio->samplesize) { continue; } - foreachEssence (ae, audioEssence->next) + AAFI_foreachEssence (audioEssenceFile->next, ae) { - if (audioEssence->samplerate == ae->samplerate && audioEssence->samplesize == ae->samplesize) { + if (audioEssenceFile->samplerate == ae->samplerate && audioEssenceFile->samplesize == ae->samplesize) { count++; } } - debug ("Essence count @ %u Hz / %u bits : %i", audioEssence->samplerate, audioEssence->samplesize, count); + debug ("Essence count @ %u Hz / %u bits : %i", audioEssenceFile->samplerate, audioEssenceFile->samplesize, count); if (count > maxOccurence) { maxOccurence = count; - aafi->Audio->samplesize = audioEssence->samplesize; - aafi->Audio->samplerate = audioEssence->samplerate; - aafi->Audio->samplerateRational = audioEssence->samplerateRational; + aafi->Audio->samplesize = audioEssenceFile->samplesize; + aafi->Audio->samplerate = audioEssenceFile->samplerate; + aafi->Audio->samplerateRational = audioEssenceFile->samplerateRational; } } - aafiVideoEssence* videoEssence = NULL; + aafiVideoEssence* videoEssenceFile = NULL; - foreachEssence (videoEssence, aafi->Video->Essences) + AAFI_foreachVideoEssence (aafi, videoEssenceFile) { - if (videoEssence->original_file_path == NULL) { + if (videoEssenceFile->original_file_path == NULL) { continue; } - videoEssence->usable_file_path = aafi_locate_external_essence_file (aafi, videoEssence->original_file_path, aafi->ctx.options.media_location); + videoEssenceFile->usable_file_path = aafi_locate_external_essence_file (aafi, videoEssenceFile->original_file_path, aafi->ctx.options.media_location); - if (videoEssence->usable_file_path == NULL) { - error ("Could not locate external video essence file '%ls'", videoEssence->original_file_path); + if (videoEssenceFile->usable_file_path == NULL) { + error ("Could not locate external video essence file '%s'", videoEssenceFile->original_file_path); continue; } } @@ -4125,16 +3156,16 @@ aafi_retrieveData (AAF_Iface* aafi) aafPosition_t trackEnd = 0; aafiAudioTrack* audioTrack = NULL; - foreach_audioTrack (audioTrack, aafi) + AAFI_foreachAudioTrack (aafi, audioTrack) { if (aafi->compositionLength_editRate) { - trackEnd = laaf_util_converUnit (audioTrack->current_pos, audioTrack->edit_rate, aafi->compositionLength_editRate); + trackEnd = aafi_convertUnit (audioTrack->current_pos, audioTrack->edit_rate, aafi->compositionLength_editRate); } else { trackEnd = audioTrack->current_pos; } if (trackEnd > aafi->compositionLength) { - debug ("Setting compositionLength with audio track \"%ls\" (%u) : %" PRIi64, audioTrack->name, audioTrack->number, audioTrack->current_pos); + debug ("Setting compositionLength with audio track \"%s\" (%u) : %" PRIi64, audioTrack->name, audioTrack->number, audioTrack->current_pos); aafi->compositionLength = audioTrack->current_pos; aafi->compositionLength_editRate = audioTrack->edit_rate; } @@ -4142,7 +3173,7 @@ aafi_retrieveData (AAF_Iface* aafi) aafiTimelineItem* audioItem = NULL; aafiAudioClip* audioClip = NULL; - foreach_Item (audioItem, audioTrack) + AAFI_foreachTrackItem (audioTrack, audioItem) { if (audioItem->type == AAFI_TRANS) { continue; @@ -4155,16 +3186,16 @@ aafi_retrieveData (AAF_Iface* aafi) aafiVideoTrack* videoTrack = NULL; - foreach_videoTrack (videoTrack, aafi) + AAFI_foreachVideoTrack (aafi, videoTrack) { if (aafi->compositionLength_editRate) { - trackEnd = laaf_util_converUnit (videoTrack->current_pos, videoTrack->edit_rate, aafi->compositionLength_editRate); + trackEnd = aafi_convertUnit (videoTrack->current_pos, videoTrack->edit_rate, aafi->compositionLength_editRate); } else { trackEnd = videoTrack->current_pos; } if (trackEnd > aafi->compositionLength) { - debug ("Setting compositionLength with video track \"%ls\" (%u) : %" PRIi64, videoTrack->name, videoTrack->number, videoTrack->current_pos); + debug ("Setting compositionLength with video track \"%s\" (%u) : %" PRIi64, videoTrack->name, videoTrack->number, videoTrack->current_pos); aafi->compositionLength = videoTrack->current_pos; aafi->compositionLength_editRate = videoTrack->edit_rate; } @@ -4180,6 +3211,436 @@ aafi_retrieveData (AAF_Iface* aafi) return 0; } +void +aafi_dump_obj (AAF_Iface* aafi, aafObject* Obj, struct trace_dump* __td, int state, const char* func, int line, const char* fmt, ...) +{ + va_list args; + struct aafLog* log = aafi->log; + + if (aafi->ctx.options.trace == 0) { + enum verbosityLevel_e verbtype = VERB_QUIET; + + switch (state) { + case TD_ERROR: + verbtype = VERB_ERROR; + break; + case TD_WARNING: + case TD_NOT_SUPPORTED: + verbtype = VERB_WARNING; + break; + // case TD_INFO: + // case TD_OK: verbtype = VERB_DEBUG; break; + default: + return; + } + + if (aafi->log->verb < verbtype) { + return; + } + + char* buf = NULL; + + va_start (args, fmt); + + int rc = laaf_util_vsnprintf_realloc (&buf, NULL, 0, fmt, args); + + va_end (args); + + if (rc < 0) { + LOG_BUFFER_WRITE (log, "laaf_util_vsnprintf_realloc() error"); + return; + } + + laaf_write_log (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __FILENAME__, func, line, buf); + + free (buf); + + return; + } + + if (Obj) { + switch (state) { + case TD_ERROR: + LOG_BUFFER_WRITE (log, "%serr %s%s %s", ANSI_COLOR_RED (log), ANSI_COLOR_DARKGREY (log), TREE_LINE, ANSI_COLOR_RED (log)); + break; + case TD_WARNING: + LOG_BUFFER_WRITE (log, "%swrn %s%s %s", ANSI_COLOR_YELLOW (log), ANSI_COLOR_DARKGREY (log), TREE_LINE, ANSI_COLOR_YELLOW (log)); + break; + case TD_NOT_SUPPORTED: + LOG_BUFFER_WRITE (log, "%suns %s%s %s", ANSI_COLOR_ORANGE (log), ANSI_COLOR_DARKGREY (log), TREE_LINE, ANSI_COLOR_ORANGE (log)); + break; + default: + LOG_BUFFER_WRITE (log, " %s%s ", ANSI_COLOR_DARKGREY (log), TREE_LINE); + break; + } + LOG_BUFFER_WRITE (log, "%05i", line); + } else { + LOG_BUFFER_WRITE (log, " %s%s%s ", ANSI_COLOR_DARKGREY (log), TREE_LINE, ANSI_COLOR_RESET (log)); + } + + LOG_BUFFER_WRITE (log, "%s%s%s", ANSI_COLOR_DARKGREY (log), TREE_LINE, ANSI_COLOR_RESET (log)); /* │ */ + + /* Print left padding and vertical lines */ + + if (__td->lv > 0) { + for (int i = 0; i < __td->lv; i++) { + /* current level iteration has more than one entry remaining in loop */ + + if (__td->ll[i] > 1) { + /* next level iteration is current trace */ + + if (i + 1 == __td->lv) { + if (Obj) { + LOG_BUFFER_WRITE (log, "%s ", TREE_ENTRY); /* ├── */ + } else { + LOG_BUFFER_WRITE (log, "%s ", TREE_PADDED_LINE); /* │ */ + } + } else { + LOG_BUFFER_WRITE (log, "%s ", TREE_PADDED_LINE); /* │ */ + } + } else if (i + 1 == __td->lv && Obj) { + LOG_BUFFER_WRITE (log, "%s ", TREE_LAST_ENTRY); /* └── */ + } else { + LOG_BUFFER_WRITE (log, " "); + } + } + } + + if (Obj) { + switch (state) { + case TD_ERROR: + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_RED (log)); + break; + case TD_WARNING: + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_YELLOW (log)); + break; + case TD_NOT_SUPPORTED: + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_ORANGE (log)); + break; + case TD_INFO: + case TD_OK: + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_CYAN (log)); + break; + } + + LOG_BUFFER_WRITE (log, "%s ", aaft_ClassIDToText (aafi->aafd, Obj->Class->ID)); + + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_RESET (log)); + + if (aaf_ObjectInheritsClass (Obj, &AAFClassID_Mob)) { + aafMobID_t* mobID = aaf_get_propertyValue (Obj, PID_Mob_MobID, &AAFTypeID_MobIDType); + char* name = aaf_get_propertyValue (Obj, PID_Mob_Name, &AAFTypeID_String); + aafUID_t* usageCode = aaf_get_propertyValue (Obj, PID_Mob_UsageCode, &AAFTypeID_UsageType); + + LOG_BUFFER_WRITE (log, "(UsageCode: %s%s%s) %s%s", + ANSI_COLOR_DARKGREY (log), + aaft_UsageCodeToText (usageCode), + ANSI_COLOR_RESET (log), + (name && name[0] != 0x00) ? ": " : "", + (name) ? name : ""); + + free (name); + + LOG_BUFFER_WRITE (log, " MobID: %s%s%s", + ANSI_COLOR_DARKGREY (log), + (mobID) ? aaft_MobIDToText (mobID) : "none", + ANSI_COLOR_RESET (log)); + } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_TimelineMobSlot)) { + aafObject* Segment = aaf_get_propertyValue (Obj, PID_MobSlot_Segment, &AAFTypeID_SegmentStrongReference); + char* name = aaf_get_propertyValue (Obj, PID_MobSlot_SlotName, &AAFTypeID_String); + uint32_t* slotID = aaf_get_propertyValue (Obj, PID_MobSlot_SlotID, &AAFTypeID_UInt32); + uint32_t* trackNo = aaf_get_propertyValue (Obj, PID_MobSlot_PhysicalTrackNumber, &AAFTypeID_UInt32); + aafUID_t* DataDefinition = NULL; + + aafWeakRef_t* dataDefWeakRef = aaf_get_propertyValue (Segment, PID_Component_DataDefinition, &AAFTypeID_DataDefinitionWeakReference); + + if (dataDefWeakRef) { + DataDefinition = aaf_get_DataIdentificationByWeakRef (aafi->aafd, dataDefWeakRef); + } + + LOG_BUFFER_WRITE (log, "[slot:%s%i%s track:%s%i%s] (DataDef: %s%s%s) %s%s ", + ANSI_COLOR_BOLD (log), + (slotID) ? (int)(*slotID) : -1, + ANSI_COLOR_RESET (log), + ANSI_COLOR_BOLD (log), + (trackNo) ? (int)(*trackNo) : -1, + ANSI_COLOR_RESET (log), + (state == TD_NOT_SUPPORTED) ? ANSI_COLOR_ORANGE (log) : ANSI_COLOR_DARKGREY (log), + aaft_DataDefToText (aafi->aafd, DataDefinition), + ANSI_COLOR_RESET (log), + (name && name[0] != 0x00) ? ": " : "", + (name) ? name : ""); + + free (name); + } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_OperationGroup)) { + aafUID_t* OperationIdentification = NULL; + + aafWeakRef_t* OperationDefWeakRef = aaf_get_propertyValue (Obj, PID_OperationGroup_Operation, &AAFTypeID_OperationDefinitionWeakReference); + + if (OperationDefWeakRef) { + OperationIdentification = aaf_get_OperationIdentificationByWeakRef (aafi->aafd, OperationDefWeakRef); + } + + int64_t* length = aaf_get_propertyValue (Obj, PID_Component_Length, &AAFTypeID_LengthType); + + LOG_BUFFER_WRITE (log, "(OpIdent: %s%s%s; Length: %s%li%s) ", + (state == TD_NOT_SUPPORTED) ? ANSI_COLOR_ORANGE (log) : ANSI_COLOR_DARKGREY (log), + aaft_OperationDefToText (aafi->aafd, OperationIdentification), + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + (length) ? *length : -1, + ANSI_COLOR_RESET (log)); + } else if (aaf_ObjectInheritsClass (Obj, &AAFClassID_Component)) { + int64_t* length = aaf_get_propertyValue (Obj, PID_Component_Length, &AAFTypeID_LengthType); + + LOG_BUFFER_WRITE (log, "(Length: %s%li%s", + ANSI_COLOR_DARKGREY (log), + (length) ? *length : -1, + ANSI_COLOR_RESET (log)); + + if (aafUIDCmp (Obj->Class->ID, &AAFClassID_Transition)) { + aafPosition_t* cutPoint = aaf_get_propertyValue (Obj, PID_Transition_CutPoint, &AAFTypeID_PositionType); + + if (cutPoint) { + LOG_BUFFER_WRITE (log, "; CutPoint: %s%li%s", + ANSI_COLOR_DARKGREY (log), + *cutPoint, + ANSI_COLOR_RESET (log)); + } + } + + LOG_BUFFER_WRITE (log, ")"); + } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_ConstantValue)) { + aafIndirect_t* Indirect = aaf_get_propertyValue (Obj, PID_ConstantValue_Value, &AAFTypeID_Indirect); + + if (Indirect) { + aafUID_t* ParamDef = aaf_get_propertyValue (Obj, PID_Parameter_Definition, &AAFTypeID_AUID); + + LOG_BUFFER_WRITE (log, "(ParamDef: %s%s%s; Type: %s%s%s) ", + (state == TD_NOT_SUPPORTED) ? ANSI_COLOR_ORANGE (log) : ANSI_COLOR_DARKGREY (log), + aaft_ParameterToText (aafi->aafd, ParamDef), + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + aaft_TypeIDToText (&Indirect->TypeDef), + ANSI_COLOR_RESET (log)); + + LOG_BUFFER_WRITE (log, ": %s%s%s", + ANSI_COLOR_DARKGREY (log), + aaft_IndirectValueToText (aafi->aafd, Indirect), + ANSI_COLOR_RESET (log)); + + if (aafUIDCmp (ParamDef, &AAFParameterDef_Amplitude) && + aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Rational)) { + aafRational_t* value = aaf_get_indirectValue (aafi->aafd, Indirect, NULL); + + LOG_BUFFER_WRITE (log, " %s(%+05.1lf dB)%s", + ANSI_COLOR_DARKGREY (log), + 20 * log10 (aafRationalToDouble (*value)), + ANSI_COLOR_RESET (log)); + } + + __td->eob = 0; + } + } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_VaryingValue)) { + aafUID_t* ParamDef = aaf_get_propertyValue (Obj, PID_Parameter_Definition, &AAFTypeID_AUID); + aafUID_t* InterpolationIdentification = NULL; + + aafWeakRef_t* InterpolationDefWeakRef = aaf_get_propertyValue (Obj, PID_VaryingValue_Interpolation, &AAFTypeID_InterpolationDefinitionWeakReference); + + if (InterpolationDefWeakRef) { + InterpolationIdentification = aaf_get_InterpolationIdentificationByWeakRef (aafi->aafd, InterpolationDefWeakRef); + } + + LOG_BUFFER_WRITE (log, " (ParamDef: %s%s%s; Interpol: %s%s%s) ", + (state == TD_NOT_SUPPORTED) ? ANSI_COLOR_ORANGE (log) : ANSI_COLOR_DARKGREY (log), + aaft_ParameterToText (aafi->aafd, ParamDef), + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + aaft_InterpolationToText (InterpolationIdentification), + ANSI_COLOR_RESET (log)); + + __td->eob = 0; + } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_NetworkLocator)) { + char* url = aaf_get_propertyValue (Obj, PID_NetworkLocator_URLString, &AAFTypeID_String); + + if (url) { + LOG_BUFFER_WRITE (log, "(URLString: %s%s%s)", + ANSI_COLOR_DARKGREY (log), + url, + ANSI_COLOR_RESET (log)); + + free (url); + } + } else if (aafUIDCmp (Obj->Class->ID, &AAFClassID_EssenceData)) { + char* streamName = aaf_get_propertyValue (Obj, PID_EssenceData_Data, &AAFTypeID_String); + + if (streamName) { + LOG_BUFFER_WRITE (log, "(Data: %s%s%s)", + ANSI_COLOR_DARKGREY (log), + streamName, + ANSI_COLOR_RESET (log)); + + free (streamName); + } + } else if (aaf_ObjectInheritsClass (Obj, &AAFClassID_FileDescriptor)) { + aafUID_t* ContainerFormat = NULL; + + aafWeakRef_t* ContainerDefWeakRef = aaf_get_propertyValue (Obj, PID_FileDescriptor_ContainerFormat, &AAFTypeID_ClassDefinitionWeakReference); + + if (ContainerDefWeakRef) { + ContainerFormat = aaf_get_ContainerIdentificationByWeakRef (aafi->aafd, ContainerDefWeakRef); + } + + LOG_BUFFER_WRITE (log, "(ContainerIdent : %s%s%s)", + ANSI_COLOR_DARKGREY (log), + aaft_ContainerToText (ContainerFormat), + ANSI_COLOR_RESET (log)); + } + + if (state == TD_INFO) { + LOG_BUFFER_WRITE (log, ": %s", ANSI_COLOR_CYAN (log)); + } else if (state == TD_WARNING) { + LOG_BUFFER_WRITE (log, ": %s", ANSI_COLOR_YELLOW (log)); + } else if (state == TD_ERROR) { + LOG_BUFFER_WRITE (log, ": %s", ANSI_COLOR_RED (log)); + } + + va_start (args, fmt); + + int rc = laaf_util_vsnprintf_realloc (&log->_msg, &log->_msg_size, log->_msg_pos, fmt, args); + + if (rc < 0) { + LOG_BUFFER_WRITE (log, "laaf_util_vsnprintf_realloc() error"); + } else { + log->_msg_pos += (size_t)rc; + } + + va_end (args); + + if (state == TD_ERROR || state == TD_INFO) { + LOG_BUFFER_WRITE (log, "."); + } + + int hasUnknownProps = 0; + + if (!aafi->ctx.options.dump_class_aaf_properties) { + aafProperty* Prop = NULL; + + for (Prop = Obj->Properties; Prop != NULL; Prop = Prop->next) { + if (Prop->def->meta) { + LOG_BUFFER_WRITE (log, "%s%s %s[0x%04x]", ANSI_COLOR_RESET (log), (!hasUnknownProps) ? " (MetaProps:" : "", aaft_PIDToText (aafi->aafd, Prop->pid), Prop->pid); + hasUnknownProps++; + } + } + + if (hasUnknownProps) { + LOG_BUFFER_WRITE (log, ")"); + } + } + + if (aafi->ctx.options.dump_tagged_value) { + if (aaf_ObjectInheritsClass (Obj, &AAFClassID_Mob)) { + aafObject* UserComments = aaf_get_propertyValue (Obj, PID_Mob_UserComments, &AAFTypeID_TaggedValueStrongReferenceVector); + aafObject* Attributes = aaf_get_propertyValue (Obj, PID_Mob_Attributes, &AAFTypeID_TaggedValueStrongReferenceVector); + + if (UserComments) { + LOG_BUFFER_WRITE (log, "\n Mob::UserComments:\n"); + aaf_dump_TaggedValueSet (aafi->aafd, UserComments, " "); + } + if (Attributes) { + LOG_BUFFER_WRITE (log, "\n Mob::Attributes:\n"); + aaf_dump_TaggedValueSet (aafi->aafd, Attributes, " "); + } + } else if (aaf_ObjectInheritsClass (Obj, &AAFClassID_Component)) { + aafObject* UserComments = aaf_get_propertyValue (Obj, PID_Component_UserComments, &AAFTypeID_TaggedValueStrongReferenceVector); + aafObject* Attributes = aaf_get_propertyValue (Obj, PID_Component_Attributes, &AAFTypeID_TaggedValueStrongReferenceVector); + + if (UserComments) { + LOG_BUFFER_WRITE (log, "\n Component::UserComments:\n"); + aaf_dump_TaggedValueSet (aafi->aafd, UserComments, " "); + } + if (Attributes) { + LOG_BUFFER_WRITE (log, "\n Component::Attributes:\n"); + aaf_dump_TaggedValueSet (aafi->aafd, Attributes, " "); + } + } + } + + if (aafi->ctx.options.dump_meta && hasUnknownProps) { + LOG_BUFFER_WRITE (log, "\n\n%s", ANSI_COLOR_MAGENTA (log)); + LOG_BUFFER_WRITE (log, " ======================================================================\n"); + LOG_BUFFER_WRITE (log, " AAF Meta Properties Dump\n"); + LOG_BUFFER_WRITE (log, " ======================================================================\n"); + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_RESET (log)); + + aafProperty* Prop = NULL; + + for (Prop = Obj->Properties; Prop != NULL; Prop = Prop->next) { + if (Prop->def->meta) { + if (aafi->ctx.options.dump_meta) { + if (Prop->sf == SF_STRONG_OBJECT_REFERENCE_VECTOR) { + LOG_BUFFER_WRITE (log, "\n"); + LOG_BUFFER_WRITE (log, " [%s0x%04x%s] %s (%s)\n", + ANSI_COLOR_MAGENTA (log), + Prop->pid, + ANSI_COLOR_RESET (log), + aaft_PIDToText (aafi->aafd, Prop->pid), + aaft_StoredFormToText (Prop->sf)); + + void* propValue = aaf_get_propertyValue (Obj, Prop->pid, &AAFTypeID_TaggedValueStrongReferenceVector); + + log->color_reset = ANSI_COLOR_MAGENTA (log); + aaf_dump_TaggedValueSet (aafi->aafd, propValue, " "); + log->color_reset = NULL; + } else { + LOG_BUFFER_WRITE (log, "\n"); + aaf_dump_ObjectProperty (aafi->aafd, Prop, " "); + } + } + } + } + } + + if (aafi->ctx.options.dump_class_raw_properties && strcmp (aaft_ClassIDToText (aafi->aafd, Obj->Class->ID), aafi->ctx.options.dump_class_raw_properties) == 0) { + LOG_BUFFER_WRITE (log, "\n\n"); + LOG_BUFFER_WRITE (log, " ======================================================================\n"); + LOG_BUFFER_WRITE (log, " CFB Object Properties Dump\n"); + LOG_BUFFER_WRITE (log, " ======================================================================\n"); + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_DARKGREY (log)); + LOG_BUFFER_WRITE (log, " %s\n", aaft_ClassIDToText (aafi->aafd, Obj->Class->ID)); + LOG_BUFFER_WRITE (log, " %s/properties\n", aaf_get_ObjectPath (Obj)); + LOG_BUFFER_WRITE (log, "%s\n\n", ANSI_COLOR_RESET (log)); + + aaf_dump_nodeStreamProperties (aafi->aafd, cfb_getChildNode (aafi->aafd->cfbd, "properties", Obj->Node), " "); + + LOG_BUFFER_WRITE (log, "\n"); + } + + if (aafi->ctx.options.dump_class_aaf_properties && strcmp (aaft_ClassIDToText (aafi->aafd, Obj->Class->ID), aafi->ctx.options.dump_class_aaf_properties) == 0) { + LOG_BUFFER_WRITE (log, "\n\n"); + LOG_BUFFER_WRITE (log, " ======================================================================\n"); + LOG_BUFFER_WRITE (log, " AAF Properties Dump\n"); + LOG_BUFFER_WRITE (log, " ======================================================================\n"); + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_DARKGREY (log)); + LOG_BUFFER_WRITE (log, " %s\n", aaft_ClassIDToText (aafi->aafd, Obj->Class->ID)); + LOG_BUFFER_WRITE (log, " %s/properties\n", aaf_get_ObjectPath (Obj)); + LOG_BUFFER_WRITE (log, "%s\n\n", ANSI_COLOR_RESET (log)); + + aaf_dump_ObjectProperties (aafi->aafd, Obj, " "); + + LOG_BUFFER_WRITE (log, "\n"); + } + + LOG_BUFFER_WRITE (log, "%s", ANSI_COLOR_RESET (log)); + } + + log->debug_callback (log, (void*)aafi, DEBUG_SRC_ID_TRACE, 0, "", "", 0, log->_msg, log->user); + + /* if end of branch, print one line padding */ + if (Obj && (__td->eob || state == TD_ERROR)) + aafi_dump_obj (aafi, NULL, __td, 0, NULL, -1, ""); +} + /** * @} */ diff --git a/libs/aaf/AAFIface.c b/libs/aaf/AAFIface.c index 34d53b9e1c..528730f066 100644 --- a/libs/aaf/AAFIface.c +++ b/libs/aaf/AAFIface.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -39,13 +39,14 @@ */ #include +#include #include #include #include #include "aaf/AAFIParser.h" #include "aaf/AAFIface.h" -#include "aaf/debug.h" +#include "aaf/log.h" #include "aaf/utils.h" #ifdef _WIN32 @@ -55,47 +56,47 @@ #endif #define debug(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) AAF_Iface* aafi_alloc (AAF_Data* aafd) { - AAF_Iface* aafi = calloc (sizeof (AAF_Iface), sizeof (unsigned char)); + AAF_Iface* aafi = calloc (1, sizeof (AAF_Iface)); - if (aafi == NULL) { + if (!aafi) { return NULL; } - aafi->dbg = laaf_new_debug (); + aafi->log = laaf_new_log (); - if (aafi->dbg == NULL) { + if (!aafi->log) { goto err; } - aafi->Audio = calloc (sizeof (aafiAudio), sizeof (unsigned char)); + aafi->Audio = calloc (1, sizeof (aafiAudio)); - if (aafi->Audio == NULL) { + if (!aafi->Audio) { goto err; } - aafi->Video = calloc (sizeof (aafiVideo), sizeof (unsigned char)); + aafi->Video = calloc (1, sizeof (aafiVideo)); - if (aafi->Video == NULL) { + if (!aafi->Video) { goto err; } - if (aafd != NULL) { + if (aafd) { aafi->aafd = aafd; } else { - aafi->aafd = aaf_alloc (aafi->dbg); + aafi->aafd = aaf_alloc (aafi->log); - if (aafi->aafd == NULL) { + if (!aafi->aafd) { goto err; } } @@ -109,19 +110,30 @@ err: } void -aafi_set_debug (AAF_Iface* aafi, verbosityLevel_e v, int ansicolor, FILE* fp, void (*callback) (struct dbg* dbg, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user), void* user) +aafi_set_debug (AAF_Iface* aafi, verbosityLevel_e v, int ansicolor, FILE* fp, void (*callback) (struct aafLog* log, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user), void* user) { - aafi->dbg->verb = v; - aafi->dbg->ansicolor = ansicolor; - aafi->dbg->fp = fp; + if (!aafi) { + return; + } + + aafi->log->verb = v; + aafi->log->ansicolor = ansicolor; + aafi->log->fp = fp; if (callback) { - aafi->dbg->debug_callback = callback; + aafi->log->debug_callback = callback; } if (user) { - aafi->dbg->user = user; + aafi->log->user = user; } + +#ifdef _WIN32 + /* we dont want junk bytes to be printed to a windows file */ + if (fp != stdout && fp != stderr) { + aafi->log->ansicolor = 0; + } +#endif } int @@ -130,17 +142,17 @@ aafi_set_option_int (AAF_Iface* aafi, const char* optname, int val) if (strcmp (optname, "trace") == 0) { aafi->ctx.options.trace = val; return 0; - } else if (strcmp (optname, "trace_meta") == 0) { - aafi->ctx.options.trace_meta = val; + } else if (strcmp (optname, "dump_meta") == 0) { + aafi->ctx.options.dump_meta = val; return 0; - } else if (strcmp (optname, "forbid_nonlatin_filenames") == 0) { - aafi->ctx.options.forbid_nonlatin_filenames = val; + } else if (strcmp (optname, "dump_tagged_value") == 0) { + aafi->ctx.options.dump_tagged_value = val; return 0; } else if (strcmp (optname, "protools") == 0) { aafi->ctx.options.protools = val; return 0; - } else if (strcmp (optname, "resolve") == 0) { - aafi->ctx.options.resolve = val; + } else if (strcmp (optname, "mobid_essence_filename") == 0) { + aafi->ctx.options.mobid_essence_filename = val; return 0; } @@ -151,43 +163,28 @@ int aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val) { if (strcmp (optname, "media_location") == 0) { - if (aafi->ctx.options.media_location) { - free (aafi->ctx.options.media_location); - } + free (aafi->ctx.options.media_location); + aafi->ctx.options.media_location = laaf_util_c99strdup (val); - aafi->ctx.options.media_location = (val) ? laaf_util_c99strdup (val) : NULL; + if (val && !aafi->ctx.options.media_location) { + return -1; + } return 0; } else if (strcmp (optname, "dump_class_aaf_properties") == 0) { - if (aafi->ctx.options.dump_class_aaf_properties) { - free (aafi->ctx.options.dump_class_aaf_properties); - aafi->ctx.options.dump_class_aaf_properties = NULL; - } + free (aafi->ctx.options.dump_class_aaf_properties); + aafi->ctx.options.dump_class_aaf_properties = laaf_util_c99strdup (val); - if (val == NULL) { - return 0; - } - - aafi->ctx.options.dump_class_aaf_properties = laaf_util_str2wstr (val); - - if (aafi->ctx.options.dump_class_aaf_properties == NULL) { + if (val && !aafi->ctx.options.dump_class_aaf_properties) { return -1; } return 0; } else if (strcmp (optname, "dump_class_raw_properties") == 0) { - if (aafi->ctx.options.dump_class_raw_properties) { - free (aafi->ctx.options.dump_class_raw_properties); - aafi->ctx.options.dump_class_raw_properties = NULL; - } + free (aafi->ctx.options.dump_class_raw_properties); + aafi->ctx.options.dump_class_raw_properties = laaf_util_c99strdup (val); - if (val == NULL) { - return 0; - } - - aafi->ctx.options.dump_class_raw_properties = laaf_util_str2wstr (val); - - if (aafi->ctx.options.dump_class_raw_properties == NULL) { + if (val && !aafi->ctx.options.dump_class_raw_properties) { return -1; } @@ -197,81 +194,10 @@ aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val) return 1; } -void -aafi_release (AAF_Iface** aafi) -{ - if (*aafi == NULL) { - return; - } - - aaf_release (&(*aafi)->aafd); - - if ((*aafi)->compositionName != NULL) { - free ((*aafi)->compositionName); - } - - if ((*aafi)->Comments) { - aafi_freeUserComments (&((*aafi)->Comments)); - } - - if ((*aafi)->Audio != NULL) { - if ((*aafi)->Audio->Tracks != NULL) { - aafi_freeAudioTracks (&(*aafi)->Audio->Tracks); - } - - if ((*aafi)->Audio->Essences != NULL) { - aafi_freeAudioEssences (&(*aafi)->Audio->Essences); - } - - free ((*aafi)->Audio); - } - - if ((*aafi)->Video != NULL) { - if ((*aafi)->Video->Tracks != NULL) { - aafi_freeVideoTracks (&(*aafi)->Video->Tracks); - } - - if ((*aafi)->Video->Essences != NULL) { - aafi_freeVideoEssences (&(*aafi)->Video->Essences); - } - - free ((*aafi)->Video); - } - - if ((*aafi)->Markers) { - aafi_freeMarkers (&(*aafi)->Markers); - } - - if ((*aafi)->ctx.options.dump_class_aaf_properties) { - free ((*aafi)->ctx.options.dump_class_aaf_properties); - } - - if ((*aafi)->ctx.options.dump_class_raw_properties) { - free ((*aafi)->ctx.options.dump_class_raw_properties); - } - - if ((*aafi)->ctx.options.media_location) { - free ((*aafi)->ctx.options.media_location); - } - - if ((*aafi)->Timecode != NULL) { - free ((*aafi)->Timecode); - } - - if ((*aafi)->dbg) { - laaf_free_debug ((*aafi)->dbg); - } - - free (*aafi); - - *aafi = NULL; -} - int aafi_load_file (AAF_Iface* aafi, const char* file) { - if (aaf_load_file (aafi->aafd, file)) { - error ("Could not load file : %s\n", file); + if (!aafi || !file || aaf_load_file (aafi->aafd, file)) { return 1; } @@ -280,9 +206,84 @@ aafi_load_file (AAF_Iface* aafi, const char* file) return 0; } -aafiTransition* -aafi_get_fadein (aafiTimelineItem* audioItem) +void +aafi_release (AAF_Iface** aafi) { + if (!aafi || !(*aafi)) { + return; + } + + aaf_release (&(*aafi)->aafd); + + if ((*aafi)->Audio != NULL) { + aafi_freeAudioTracks (&(*aafi)->Audio->Tracks); + aafi_freeAudioEssences (&(*aafi)->Audio->essenceFiles); + + free ((*aafi)->Audio); + } + + if ((*aafi)->Video != NULL) { + aafi_freeVideoTracks (&(*aafi)->Video->Tracks); + aafi_freeVideoEssences (&(*aafi)->Video->essenceFiles); + + free ((*aafi)->Video); + } + + aafi_freeMarkers (&(*aafi)->Markers); + aafi_freeMetadata (&((*aafi)->metadata)); + + free ((*aafi)->compositionName); + + free ((*aafi)->ctx.options.dump_class_aaf_properties); + free ((*aafi)->ctx.options.dump_class_raw_properties); + free ((*aafi)->ctx.options.media_location); + free ((*aafi)->Timecode); + + laaf_free_log ((*aafi)->log); + + free (*aafi); + + *aafi = NULL; +} + +aafiAudioClip* +aafi_timelineItemToAudioClip (aafiTimelineItem* audioItem) +{ + if (!audioItem || audioItem->type != AAFI_AUDIO_CLIP) { + return NULL; + } + + return audioItem->data; +} + +aafiTransition* +aafi_timelineItemToCrossFade (aafiTimelineItem* audioItem) +{ + if (!audioItem || audioItem->type != AAFI_TRANS) { + return NULL; + } + + aafiTransition* Trans = audioItem->data; + + if (!Trans || !(Trans->flags & AAFI_TRANS_XFADE)) + return NULL; + + return Trans; +} + +aafiTransition* +aafi_getFadeIn (aafiAudioClip* audioClip) +{ + if (!audioClip) { + return NULL; + } + + aafiTimelineItem* audioItem = audioClip->timelineItem; + + if (!audioItem) { + return NULL; + } + if (audioItem->prev != NULL && audioItem->prev->type == AAFI_TRANS) { aafiTransition* Trans = audioItem->prev->data; @@ -295,8 +296,18 @@ aafi_get_fadein (aafiTimelineItem* audioItem) } aafiTransition* -aafi_get_fadeout (aafiTimelineItem* audioItem) +aafi_getFadeOut (aafiAudioClip* audioClip) { + if (!audioClip) { + return NULL; + } + + aafiTimelineItem* audioItem = audioClip->timelineItem; + + if (!audioItem) { + return NULL; + } + if (audioItem->next != NULL && audioItem->next->type == AAFI_TRANS) { aafiTransition* Trans = audioItem->next->data; @@ -308,347 +319,219 @@ aafi_get_fadeout (aafiTimelineItem* audioItem) return NULL; } -aafiTransition* -aafi_get_xfade (aafiTimelineItem* audioItem) -{ - if (audioItem->prev != NULL && - audioItem->prev->type == AAFI_TRANS) { - aafiTransition* Trans = audioItem->prev->data; - - if (Trans->flags & AAFI_TRANS_XFADE) - return Trans; - } - - return NULL; -} - -aafiMarker* -aafi_newMarker (AAF_Iface* aafi, aafRational_t* editRate, aafPosition_t start, aafPosition_t length, wchar_t* name, wchar_t* comment, uint16_t*(RGBColor[3])) -{ - aafiMarker* marker = malloc (sizeof (aafiMarker)); - - marker->edit_rate = editRate; - marker->start = start; - marker->length = length; - - marker->name = name; - marker->comment = comment; - - marker->prev = NULL; - marker->next = NULL; - - if (RGBColor) { - marker->RGBColor[0] = (*RGBColor)[0]; - marker->RGBColor[1] = (*RGBColor)[1]; - marker->RGBColor[2] = (*RGBColor)[2]; - } - - if (aafi->Markers != NULL) { - aafiMarker* tmp = aafi->Markers; - - for (; tmp != NULL; tmp = tmp->next) - if (tmp->next == NULL) - break; - - tmp->next = marker; - marker->prev = marker; - } else { - aafi->Markers = marker; - marker->prev = NULL; - } - - return marker; -} - -void -aafi_freeMarkers (aafiMarker** Markers) -{ - aafiMarker* marker = NULL; - aafiMarker* nextMarker = NULL; - - for (marker = (*Markers); marker != NULL; marker = nextMarker) { - nextMarker = marker->next; - - if (marker->name) - free (marker->name); - - if (marker->comment) - free (marker->comment); - - free (marker); - } - - *Markers = NULL; -} - -aafiTimelineItem* -aafi_newTimelineItem (AAF_Iface* aafi, void* track, int itemType) -{ - aafiTimelineItem* item = NULL; - - if (itemType == AAFI_AUDIO_CLIP) { - item = calloc (sizeof (aafiTimelineItem), sizeof (char)); - - if (item == NULL) { - error ("%s.", strerror (errno)); - return NULL; - } - - item->type = AAFI_AUDIO_CLIP; - - item->data = calloc (sizeof (aafiAudioClip), sizeof (char)); - - aafiAudioClip* audioClip = item->data; - - audioClip->track = (aafiAudioTrack*)track; - audioClip->Item = item; - } else if (itemType == AAFI_VIDEO_CLIP) { - item = calloc (sizeof (aafiTimelineItem), sizeof (char)); - - if (item == NULL) { - error ("%s.", strerror (errno)); - return NULL; - } - - item->type = AAFI_VIDEO_CLIP; - - item->data = calloc (sizeof (aafiVideoClip), sizeof (char)); - - aafiVideoClip* videoClip = item->data; - - videoClip->track = (aafiVideoTrack*)track; - } else if (itemType == AAFI_TRANS) { - item = calloc (sizeof (aafiTimelineItem), sizeof (char)); - - if (item == NULL) { - error ("%s.", strerror (errno)); - return NULL; - } - - item->type = AAFI_TRANS; - - item->data = calloc (sizeof (aafiTransition), sizeof (char)); - } - - if (itemType == AAFI_AUDIO_CLIP || itemType == AAFI_TRANS) { - if (track != NULL) { - /* Add to track's item list */ - - if (((aafiAudioTrack*)track)->Items != NULL) { - aafiTimelineItem* tmp = ((aafiAudioTrack*)track)->Items; - - for (; tmp != NULL; tmp = tmp->next) - if (tmp->next == NULL) - break; - - tmp->next = item; - item->prev = tmp; - } else { - ((aafiAudioTrack*)track)->Items = item; - item->prev = NULL; - } - } - } else if (itemType == AAFI_VIDEO_CLIP) { - if (track != NULL) { - /* Add to track's item list */ - - if (((aafiVideoTrack*)track)->Items != NULL) { - aafiTimelineItem* tmp = ((aafiVideoTrack*)track)->Items; - - for (; tmp != NULL; tmp = tmp->next) - if (tmp->next == NULL) - break; - - tmp->next = item; - item->prev = tmp; - } else { - ((aafiVideoTrack*)track)->Items = item; - item->prev = NULL; - } - } - } - - return item; -} - int -aafi_removeTimelineItem (AAF_Iface* aafi, aafiTimelineItem* item) +aafi_get_clipIndex (aafiAudioClip* audioClip) { - if (item->prev != NULL) { - item->prev->next = item->next; + if (!audioClip) { + return 0; } - if (item->next != NULL) { - item->next->prev = item->prev; - } + int index = 0; + struct aafiTimelineItem* timelineItem = NULL; + struct aafiAudioTrack* track = audioClip->track; - aafiAudioTrack* audioTrack = NULL; - - foreach_audioTrack (audioTrack, aafi) + AAFI_foreachTrackItem (track, timelineItem) { - if (audioTrack->Items == item) { - audioTrack->Items = item->next; + if (timelineItem->type == AAFI_AUDIO_CLIP) { + index++; + } + if (timelineItem->data == audioClip) { + return index; } } - aafi_freeTimelineItem (&item); - return 0; } -void -aafi_freeAudioGain (aafiAudioGain* gain) +aafPosition_t +aafi_convertUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate) { - if (gain == NULL) { - return; + if (!valueEditRate || !destEditRate) { + return value; } - if (gain->time != NULL) { - free (gain->time); + if (valueEditRate->numerator == destEditRate->numerator && + valueEditRate->denominator == destEditRate->denominator) { + /* same rate, no conversion */ + return value; } - if (gain->value != NULL) { - free (gain->value); + double valueEditRateFloat = ((valueEditRate->denominator == 0) ? 0.0 : ((float)valueEditRate->numerator / (float)valueEditRate->denominator)); + double destEditRateFloat = ((destEditRate->denominator == 0) ? 0.0 : ((float)destEditRate->numerator / (float)destEditRate->denominator)); + + if (valueEditRateFloat == 0) { + return 0; } - free (gain); + return (aafPosition_t) ((double)value * (destEditRateFloat / valueEditRateFloat)); } -void -aafi_freeAudioPan (aafiAudioPan* pan) +uint64_t +aafi_convertUnitUint64 (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate) { - aafi_freeAudioGain ((aafiAudioGain*)pan); + if (!valueEditRate || !destEditRate) { + if (value < 0) { + /* TODO is ULONG_MAX ok for max uint64_t ? */ + return ULONG_MAX; + } + + return (uint64_t)value; + } + + if (valueEditRate->numerator == destEditRate->numerator && + valueEditRate->denominator == destEditRate->denominator) { + /* same rate, no conversion */ + if (value < 0) { + /* TODO is ULONG_MAX ok for max uint64_t ? */ + return ULONG_MAX; + } + + return (uint64_t)value; + } + + double valueEditRateFloat = ((valueEditRate->denominator == 0) ? 0.0 : ((float)valueEditRate->numerator / (float)valueEditRate->denominator)); + double destEditRateFloat = ((destEditRate->denominator == 0) ? 0.0 : ((float)destEditRate->numerator / (float)destEditRate->denominator)); + + if (valueEditRateFloat == 0) { + return 0; + } + + return (uint64_t) ((double)value * (destEditRateFloat / valueEditRateFloat)); } -void -aafi_freeAudioClip (aafiAudioClip* audioClip) +int +aafi_removeTimelineItem (AAF_Iface* aafi, aafiTimelineItem* timelineItem) { - if (audioClip->gain != NULL) { - aafi_freeAudioGain (audioClip->gain); + if (!timelineItem) { + return 0; } - if (audioClip->automation != NULL) { - aafi_freeAudioGain (audioClip->automation); + if (timelineItem->prev != NULL) { + timelineItem->prev->next = timelineItem->next; } - aafi_freeAudioEssencePointer (audioClip->essencePointerList); + if (timelineItem->next != NULL) { + timelineItem->next->prev = timelineItem->prev; + } + + aafiAudioTrack* audioTrack = NULL; + + AAFI_foreachAudioTrack (aafi, audioTrack) + { + if (audioTrack->timelineItems == timelineItem) { + audioTrack->timelineItems = timelineItem->next; + } + } + + aafi_freeTimelineItem (timelineItem); + + return 0; } -void -aafi_freeAudioEssencePointer (aafiAudioEssencePointer* essencePointer) +int +aafi_getAudioEssencePointerChannelCount (aafiAudioEssencePointer* essencePointerList) { - aafiAudioEssencePointer* next = NULL; + /* + * If essencePointerList holds a single multichannel essence file and if + * essencePointer->essenceChannel is set, then clip is mono and audio comes + * from essencePointer->essenceChannel of essencePointer.essenceFile. + * + * If essencePointerList holds a single multichannel essence file and if + * essencePointer->essenceChannel is null, then clip is multichannel and + * clip channel count equals essence->channels. + * + * If essencePointerList holds multiple pointers to multiple essence files, + * then each file should be mono and describe a clip channel. Thus, clip + * channel count equals pointers count. + */ - while (essencePointer) { - next = essencePointer->next; - free (essencePointer); - essencePointer = next; + // if ( !essencePointerList ) { + // return 0; + // } + + int essencePointerCount = 0; + aafiAudioEssencePointer* essencePointer = NULL; + + AAFI_foreachEssencePointer (essencePointerList, essencePointer) + { + essencePointerCount++; } + + return (essencePointerCount > 1) ? essencePointerCount : (essencePointerList->essenceChannel) ? 1 + : essencePointerList->essenceFile->channels; } -void -aafi_freeTimelineItem (aafiTimelineItem** item) +int +aafi_applyGainOffset (AAF_Iface* aafi, aafiAudioGain** gain, aafiAudioGain* offset) { - if ((*item)->type == AAFI_TRANS) { - aafi_freeTransition ((aafiTransition*)((*item)->data)); - free ((*item)->data); - } else if ((*item)->type == AAFI_AUDIO_CLIP) { - aafi_freeAudioClip ((aafiAudioClip*)((*item)->data)); - free ((*item)->data); - } else if ((*item)->type == AAFI_VIDEO_CLIP) { - free ((*item)->data); + if ((offset->flags & AAFI_AUDIO_GAIN_MASK) & AAFI_AUDIO_GAIN_VARIABLE) { + debug ("Variable gain offset is not supported"); + return -1; } - free (*item); + if (*gain == NULL) { + /* + * apply offset as new gain + */ - *item = NULL; -} + debug ("Applying gain to clip as a new gain"); -void -aafi_freeTimelineItems (aafiTimelineItem** items) -{ - aafiTimelineItem* item = NULL; - aafiTimelineItem* nextItem = NULL; + (*gain) = aafi_newAudioGain (aafi, offset->flags & AAFI_AUDIO_GAIN_MASK, offset->flags & AAFI_INTERPOL_MASK, NULL); - for (item = (*items); item != NULL; item = nextItem) { - nextItem = item->next; - aafi_freeTimelineItem (&item); - } + (*gain)->time = calloc ((uint64_t)offset->pts_cnt, sizeof (aafRational_t)); + (*gain)->value = calloc ((uint64_t)offset->pts_cnt, sizeof (aafRational_t)); - *items = NULL; -} + if (!(*gain)->time || !(*gain)->value) { + error ("Out of memory"); + aafi_freeAudioGain (*gain); + return -1; + } -aafiUserComment* -aafi_newUserComment (AAF_Iface* aafi, aafiUserComment** CommentList) -{ - aafiUserComment* UserComment = calloc (sizeof (aafiUserComment), 1); - - if (UserComment == NULL) { - error ("%s.", strerror (errno)); - return NULL; - } - - if (CommentList != NULL) { - UserComment->next = *CommentList; - *CommentList = UserComment; + for (unsigned int i = 0; i < (*gain)->pts_cnt; i++) { + (*gain)->value[i].numerator = offset->value[0].numerator; + (*gain)->value[i].denominator = offset->value[0].denominator; + // debug( "Setting (*gain)->value[%i] = %i/%i", + // i, + // (*gain)->value[i].numerator, + // (*gain)->value[i].denominator ); + } } else { - *CommentList = UserComment; - } + /* + * update existing constant or variable gain + */ - return UserComment; -} + debug ("Applying gain to clip: %i/%i (%+05.1lf dB) ", + (*gain)->value[0].numerator, + (*gain)->value[0].denominator, + 20 * log10 (aafRationalToDouble ((*gain)->value[0]))); -void -aafi_freeUserComments (aafiUserComment** CommentList) -{ - aafiUserComment* UserComment = *CommentList; - aafiUserComment* tmp = NULL; - - while (UserComment != NULL) { - tmp = UserComment; - UserComment = UserComment->next; - - if (tmp->name != NULL) { - free (tmp->name); + for (unsigned int i = 0; i < (*gain)->pts_cnt; i++) { + /* + * most of the time, gain values are made of very high numbers and denominator + * is the same accross all gains in file. Thus, we devide both gain numbers + * by offset denominator, so we fit inside uint32_t. + */ + (*gain)->value[i].numerator = (int32_t) (((int64_t) (*gain)->value[i].numerator * (int64_t)offset->value[0].numerator) / (int64_t)offset->value[0].denominator); + (*gain)->value[i].denominator = (int32_t) (((int64_t) (*gain)->value[i].denominator * (int64_t)offset->value[0].denominator) / (int64_t)offset->value[0].denominator); + // debug( "Setting (*gain)->value[%i] = %i/%i * %i/%i", + // i, + // (*gain)->value[i].numerator, + // (*gain)->value[i].denominator, + // offset->value[0].numerator, + // offset->value[0].denominator ); } - - if (tmp->text != NULL) { - free (tmp->text); - } - - free (tmp); } - *CommentList = NULL; -} - -void -aafi_freeTransition (aafiTransition* Transition) -{ - if (Transition->value_a != NULL) { - free (Transition->value_a); - } - - if (Transition->value_b != NULL) { - free (Transition->value_b); - } - - if (Transition->time_a != NULL) { - free (Transition->time_a); - } - - if (Transition->time_b != NULL) { - free (Transition->time_b); - } + return 0; } aafiAudioTrack* aafi_newAudioTrack (AAF_Iface* aafi) { - aafiAudioTrack* track = calloc (sizeof (aafiAudioTrack), sizeof (unsigned char)); + aafiAudioTrack* track = calloc (1, sizeof (aafiAudioTrack)); - if (track == NULL) { - error ("%s.", strerror (errno)); + if (!track) { + error ("Out of memory"); return NULL; } @@ -673,48 +556,13 @@ aafi_newAudioTrack (AAF_Iface* aafi) return track; } -void -aafi_freeAudioTracks (aafiAudioTrack** tracks) -{ - if (*(tracks) == NULL) { - return; - } - - aafiAudioTrack* track = NULL; - aafiAudioTrack* nextTrack = NULL; - - for (track = (*tracks); track != NULL; track = nextTrack) { - nextTrack = track->next; - - if (track->name != NULL) { - free (track->name); - } - - if (track->gain != NULL) { - aafi_freeAudioGain (track->gain); - } - - if (track->pan != NULL) { - aafi_freeAudioPan (track->pan); - } - - if (track->Items != NULL) { - aafi_freeTimelineItems (&(track->Items)); - } - - free (track); - } - - *tracks = NULL; -} - aafiVideoTrack* aafi_newVideoTrack (AAF_Iface* aafi) { - aafiVideoTrack* track = calloc (sizeof (aafiVideoTrack), sizeof (unsigned char)); + aafiVideoTrack* track = calloc (1, sizeof (aafiVideoTrack)); - if (track == NULL) { - error ("%s.", strerror (errno)); + if (!track) { + error ("Out of memory"); return NULL; } @@ -738,71 +586,213 @@ aafi_newVideoTrack (AAF_Iface* aafi) return track; } -void -aafi_freeVideoTracks (aafiVideoTrack** tracks) +aafiTimelineItem* +aafi_newTimelineItem (AAF_Iface* aafi, void* track, int itemType, void* data) { - if (*(tracks) == NULL) { - return; + aafiTimelineItem* timelineItem = calloc (1, sizeof (aafiTimelineItem)); + + if (!timelineItem) { + error ("Out of memory"); + return NULL; } - aafiVideoTrack* track = NULL; - aafiVideoTrack* nextTrack = NULL; + timelineItem->type = itemType; + timelineItem->data = data; - for (track = (*tracks); track != NULL; track = nextTrack) { - nextTrack = track->next; + if (itemType == AAFI_AUDIO_CLIP || itemType == AAFI_TRANS) { + if (track != NULL) { + /* Add to track's timelineItem list */ - if (track->name != NULL) { - free (track->name); + if (((aafiAudioTrack*)track)->timelineItems != NULL) { + aafiTimelineItem* tmp = ((aafiAudioTrack*)track)->timelineItems; + + for (; tmp != NULL; tmp = tmp->next) + if (tmp->next == NULL) + break; + + tmp->next = timelineItem; + timelineItem->prev = tmp; + } else { + ((aafiAudioTrack*)track)->timelineItems = timelineItem; + timelineItem->prev = NULL; + } } + } else if (itemType == AAFI_VIDEO_CLIP) { + if (track != NULL) { + /* Add to track's timelineItem list */ - if (track->Items != NULL) { - aafi_freeTimelineItems (&(track->Items)); + if (((aafiVideoTrack*)track)->timelineItems != NULL) { + aafiTimelineItem* tmp = ((aafiVideoTrack*)track)->timelineItems; + + for (; tmp != NULL; tmp = tmp->next) + if (tmp->next == NULL) + break; + + tmp->next = timelineItem; + timelineItem->prev = tmp; + } else { + ((aafiVideoTrack*)track)->timelineItems = timelineItem; + timelineItem->prev = NULL; + } } - - free (track); } - *tracks = NULL; + return timelineItem; } -aafiAudioEssence* -aafi_newAudioEssence (AAF_Iface* aafi) +aafiAudioClip* +aafi_newAudioClip (AAF_Iface* aafi, aafiAudioTrack* track) { - aafiAudioEssence* audioEssence = calloc (sizeof (aafiAudioEssence), sizeof (char)); + aafiAudioClip* audioClip = calloc (1, sizeof (aafiAudioClip)); - if (audioEssence == NULL) { - error ("%s.", strerror (errno)); + if (!audioClip) { + error ("Out of memory"); return NULL; } - audioEssence->samplerateRational = malloc (sizeof (aafRational_t)); + audioClip->track = track; + audioClip->timelineItem = aafi_newTimelineItem (aafi, track, AAFI_AUDIO_CLIP, audioClip); - if (audioEssence->samplerateRational == NULL) { + if (!audioClip->timelineItem) { + error ("Could not create new timelineItem"); + free (audioClip); return NULL; } - audioEssence->samplerateRational->numerator = 1; - audioEssence->samplerateRational->denominator = 1; + return audioClip; +} - audioEssence->next = aafi->Audio->Essences; +aafiVideoClip* +aafi_newVideoClip (AAF_Iface* aafi, aafiVideoTrack* track) +{ + aafiVideoClip* videoClip = calloc (1, sizeof (aafiVideoClip)); - aafi->Audio->Essences = audioEssence; + if (!videoClip) { + error ("Out of memory"); + return NULL; + } - return audioEssence; + videoClip->track = track; + videoClip->timelineItem = aafi_newTimelineItem (aafi, track, AAFI_VIDEO_CLIP, videoClip); + + if (!videoClip->timelineItem) { + error ("Could not create new timelineItem"); + free (videoClip); + return NULL; + } + + return videoClip; +} + +aafiTransition* +aafi_newTransition (AAF_Iface* aafi, aafiAudioTrack* track) +{ + aafiTransition* trans = calloc (1, sizeof (aafiTransition)); + + if (!trans) { + error ("Out of memory"); + return NULL; + } + + trans->timelineItem = aafi_newTimelineItem (aafi, track, AAFI_TRANS, trans); + + if (!trans->timelineItem) { + error ("Could not create new timelineItem"); + free (trans); + return NULL; + } + + trans->time_a = calloc (2, sizeof (aafRational_t)); + trans->value_a = calloc (2, sizeof (aafRational_t)); + + if (!trans->time_a || !trans->value_a) { + error ("Out of memory"); + aafi_freeTimelineItem (trans->timelineItem); + return NULL; + } + + return trans; +} + +aafiMarker* +aafi_newMarker (AAF_Iface* aafi, aafRational_t* editRate, aafPosition_t start, aafPosition_t length, char* name, char* comment, uint16_t*(RGBColor[])) +{ + aafiMarker* marker = calloc (sizeof (aafiMarker), 1); + + if (!marker) { + error ("Out of memory"); + return NULL; + } + + marker->edit_rate = editRate; + marker->start = start; + marker->length = length; + + marker->name = name; + marker->comment = comment; + + marker->prev = NULL; + marker->next = NULL; + + if (RGBColor && *RGBColor) { + marker->RGBColor[0] = (*RGBColor)[0]; + marker->RGBColor[1] = (*RGBColor)[1]; + marker->RGBColor[2] = (*RGBColor)[2]; + } + + if (aafi->Markers != NULL) { + aafiMarker* tmp = aafi->Markers; + + for (; tmp != NULL; tmp = tmp->next) + if (tmp->next == NULL) + break; + + tmp->next = marker; + marker->prev = marker; + } else { + aafi->Markers = marker; + marker->prev = NULL; + } + + return marker; +} + +aafiMetaData* +aafi_newMetadata (AAF_Iface* aafi, aafiMetaData** CommentList) +{ + if (!CommentList) { + return NULL; + } + + aafiMetaData* UserComment = calloc (1, sizeof (aafiMetaData)); + + if (!UserComment) { + error ("Out of memory"); + return NULL; + } + + if (*CommentList != NULL) { + UserComment->next = *CommentList; + *CommentList = UserComment; + } else { + *CommentList = UserComment; + } + + return UserComment; } aafiAudioEssencePointer* -aafi_newAudioEssencePointer (AAF_Iface* aafi, aafiAudioEssencePointer** list, aafiAudioEssence* audioEssence, uint32_t* essenceChannelNum) +aafi_newAudioEssencePointer (AAF_Iface* aafi, aafiAudioEssencePointer** list, aafiAudioEssenceFile* audioEssenceFile, uint32_t* essenceChannelNum) { - aafiAudioEssencePointer* essencePointer = calloc (sizeof (aafiAudioEssencePointer), sizeof (char)); + aafiAudioEssencePointer* essencePointer = calloc (1, sizeof (aafiAudioEssencePointer)); - if (essencePointer == NULL) { - error ("%s.", strerror (errno)); + if (!essencePointer) { + error ("Out of memory"); return NULL; } essencePointer->aafi = aafi; - essencePointer->essence = audioEssence; + essencePointer->essenceFile = audioEssenceFile; essencePointer->essenceChannel = (essenceChannelNum) ? *essenceChannelNum : 0; if (*list) { @@ -821,122 +811,320 @@ aafi_newAudioEssencePointer (AAF_Iface* aafi, aafiAudioEssencePointer** list, aa return *list; } -void -aafi_freeAudioEssences (aafiAudioEssence** audioEssence) +aafiAudioEssenceFile* +aafi_newAudioEssence (AAF_Iface* aafi) { - if (*(audioEssence) == NULL) { - return; + aafiAudioEssenceFile* audioEssenceFile = calloc (1, sizeof (aafiAudioEssenceFile)); + + if (!audioEssenceFile) { + error ("Out of memory"); + goto err; } - aafiAudioEssence* nextAudioEssence = NULL; + audioEssenceFile->samplerateRational = malloc (sizeof (aafRational_t)); - for (; (*audioEssence) != NULL; *audioEssence = nextAudioEssence) { - nextAudioEssence = (*audioEssence)->next; - - if ((*audioEssence)->original_file_path != NULL) { - free ((*audioEssence)->original_file_path); - } - - if ((*audioEssence)->usable_file_path != NULL) { - free ((*audioEssence)->usable_file_path); - } - - if ((*audioEssence)->file_name != NULL) { - free ((*audioEssence)->file_name); - } - - if ((*audioEssence)->unique_file_name != NULL) { - free ((*audioEssence)->unique_file_name); - } - - if ((*audioEssence)->samplerateRational != NULL) { - free ((*audioEssence)->samplerateRational); - } - - free (*audioEssence); + if (!audioEssenceFile->samplerateRational) { + error ("Out of memory"); + goto err; } - *audioEssence = NULL; + audioEssenceFile->samplerateRational->numerator = 1; + audioEssenceFile->samplerateRational->denominator = 1; + + audioEssenceFile->next = aafi->Audio->essenceFiles; + + aafi->Audio->essenceFiles = audioEssenceFile; + aafi->Audio->essenceCount++; + + return audioEssenceFile; + +err: + if (audioEssenceFile) { + free (audioEssenceFile->samplerateRational); + free (audioEssenceFile); + } + + return NULL; } aafiVideoEssence* aafi_newVideoEssence (AAF_Iface* aafi) { - aafiVideoEssence* videoEssence = calloc (sizeof (aafiVideoEssence), sizeof (char)); + aafiVideoEssence* videoEssenceFile = calloc (1, sizeof (aafiVideoEssence)); - if (videoEssence == NULL) { - error ("%s.", strerror (errno)); + if (!videoEssenceFile) { + error ("Out of memory"); return NULL; } - videoEssence->next = aafi->Video->Essences; + videoEssenceFile->next = aafi->Video->essenceFiles; - aafi->Video->Essences = videoEssence; + aafi->Video->essenceFiles = videoEssenceFile; - return videoEssence; + return videoEssenceFile; +} + +aafiAudioGain* +aafi_newAudioGain (AAF_Iface* aafi, enum aafiAudioGain_e type, enum aafiInterpolation_e interpol, aafRational_t* singleValue) +{ + aafiAudioGain* Gain = calloc (1, sizeof (aafiAudioGain)); + + if (!Gain) { + error ("Out of memory"); + return NULL; + } + + Gain->flags |= type; + Gain->flags |= interpol; + + if (singleValue) { + Gain->pts_cnt = 1; + Gain->value = calloc (1, sizeof (aafRational_t)); + + if (!Gain->value) { + error ("Out of memory"); + free (Gain); + return NULL; + } + + memcpy (&Gain->value[0], singleValue, sizeof (aafRational_t)); + } + + return Gain; +} + +aafiAudioGain* +aafi_newAudioPan (AAF_Iface* aafi, enum aafiAudioGain_e type, enum aafiInterpolation_e interpol, aafRational_t* singleValue) +{ + return aafi_newAudioGain (aafi, type, interpol, singleValue); } void -aafi_freeVideoEssences (aafiVideoEssence** videoEssence) +aafi_freeAudioTracks (aafiAudioTrack** tracks) { - if (*(videoEssence) == NULL) { + if (!tracks || !(*tracks)) { + return; + } + + aafiAudioTrack* track = NULL; + aafiAudioTrack* nextTrack = NULL; + + for (track = (*tracks); track != NULL; track = nextTrack) { + nextTrack = track->next; + + free (track->name); + aafi_freeAudioGain (track->gain); + aafi_freeAudioPan (track->pan); + aafi_freeTimelineItems (&track->timelineItems); + + free (track); + } + + *tracks = NULL; +} + +void +aafi_freeVideoTracks (aafiVideoTrack** tracks) +{ + if (*(tracks) == NULL) { + return; + } + + aafiVideoTrack* track = NULL; + aafiVideoTrack* nextTrack = NULL; + + for (track = (*tracks); track != NULL; track = nextTrack) { + nextTrack = track->next; + + free (track->name); + aafi_freeTimelineItems (&track->timelineItems); + + free (track); + } + + *tracks = NULL; +} + +void +aafi_freeTimelineItems (aafiTimelineItem** timelineItems) +{ + aafiTimelineItem* timelineItem = NULL; + aafiTimelineItem* nextItem = NULL; + + for (timelineItem = (*timelineItems); timelineItem != NULL; timelineItem = nextItem) { + nextItem = timelineItem->next; + aafi_freeTimelineItem (timelineItem); + } + + *timelineItems = NULL; +} + +void +aafi_freeTimelineItem (aafiTimelineItem* timelineItem) +{ + if (!timelineItem) { + return; + } + + if (timelineItem->type == AAFI_TRANS) { + aafi_freeTransition (timelineItem->data); + } else if (timelineItem->type == AAFI_AUDIO_CLIP) { + aafi_freeAudioClip (timelineItem->data); + } else if (timelineItem->type == AAFI_VIDEO_CLIP) { + free (timelineItem->data); + } + + free (timelineItem); +} + +void +aafi_freeAudioClip (aafiAudioClip* audioClip) +{ + if (!audioClip) { + return; + } + + free (audioClip->subClipName); + + aafi_freeAudioGain (audioClip->gain); + aafi_freeAudioGain (audioClip->automation); + aafi_freeMetadata (&(audioClip->metadata)); + + aafi_freeAudioEssencePointer (audioClip->essencePointerList); + + free (audioClip); +} + +void +aafi_freeTransition (aafiTransition* Transition) +{ + if (!Transition) { + return; + } + + free (Transition->value_a); + free (Transition->value_b); + free (Transition->time_a); + free (Transition->time_b); + + free (Transition); +} + +void +aafi_freeMarkers (aafiMarker** Markers) +{ + aafiMarker* marker = NULL; + aafiMarker* nextMarker = NULL; + + for (marker = (*Markers); marker != NULL; marker = nextMarker) { + nextMarker = marker->next; + + free (marker->name); + free (marker->comment); + + free (marker); + } + + *Markers = NULL; +} + +void +aafi_freeMetadata (aafiMetaData** CommentList) +{ + aafiMetaData* UserComment = *CommentList; + aafiMetaData* tmp = NULL; + + while (UserComment != NULL) { + tmp = UserComment; + UserComment = UserComment->next; + + free (tmp->name); + free (tmp->text); + + free (tmp); + } + + *CommentList = NULL; +} + +void +aafi_freeAudioEssencePointer (aafiAudioEssencePointer* essencePointer) +{ + aafiAudioEssencePointer* next = NULL; + + while (essencePointer) { + next = essencePointer->next; + free (essencePointer); + essencePointer = next; + } +} + +void +aafi_freeAudioEssences (aafiAudioEssenceFile** audioEssenceFile) +{ + if (*(audioEssenceFile) == NULL) { + return; + } + + aafiAudioEssenceFile* nextAudioEssence = NULL; + + for (; (*audioEssenceFile) != NULL; *audioEssenceFile = nextAudioEssence) { + nextAudioEssence = (*audioEssenceFile)->next; + + free ((*audioEssenceFile)->original_file_path); + free ((*audioEssenceFile)->usable_file_path); + free ((*audioEssenceFile)->name); + free ((*audioEssenceFile)->unique_name); + free ((*audioEssenceFile)->samplerateRational); + + aafi_freeMetadata (&((*audioEssenceFile)->metadata)); + + free (*audioEssenceFile); + } + + *audioEssenceFile = NULL; +} + +void +aafi_freeVideoEssences (aafiVideoEssence** videoEssenceFile) +{ + if (*(videoEssenceFile) == NULL) { return; } aafiVideoEssence* nextVideoEssence = NULL; - for (; (*videoEssence) != NULL; *videoEssence = nextVideoEssence) { - nextVideoEssence = (*videoEssence)->next; + for (; (*videoEssenceFile) != NULL; *videoEssenceFile = nextVideoEssence) { + nextVideoEssence = (*videoEssenceFile)->next; - if ((*videoEssence)->original_file_path != NULL) { - free ((*videoEssence)->original_file_path); - } + free ((*videoEssenceFile)->original_file_path); + free ((*videoEssenceFile)->usable_file_path); + free ((*videoEssenceFile)->name); + free ((*videoEssenceFile)->unique_name); - if ((*videoEssence)->usable_file_path != NULL) { - free ((*videoEssence)->usable_file_path); - } - - if ((*videoEssence)->file_name != NULL) { - free ((*videoEssence)->file_name); - } - - if ((*videoEssence)->unique_file_name != NULL) { - free ((*videoEssence)->unique_file_name); - } - - free (*videoEssence); + free (*videoEssenceFile); } - *videoEssence = NULL; + *videoEssenceFile = NULL; } -int -aafi_getAudioEssencePointerChannelCount (aafiAudioEssencePointer* essencePointerList) +void +aafi_freeAudioGain (aafiAudioGain* gain) { - /* - * If essencePointerList holds a single multichannel essence file and if - * essencePointer->essenceChannel is set, then clip is mono and audio comes - * from essencePointer->essenceChannel of essencePointer->essence file. - * - * If essencePointerList holds a single multichannel essence file and if - * essencePointer->essenceChannel is null, then clip is multichannel and - * clip channel count equals essence->channels. - * - * If essencePointerList holds multiple pointers to multiple essence files, - * then each file should be mono and describe a clip channel. Thus, clip - * channel count equals pointers count. - */ - - int essencePointerCount = 0; - aafiAudioEssencePointer* essencePointer = NULL; - - AAFI_foreachAudioEssencePointer (essencePointer, essencePointerList) - { - essencePointerCount++; + if (gain == NULL) { + return; } - return (essencePointerCount > 1) ? essencePointerCount : (essencePointerList->essenceChannel) ? 1 - : essencePointerList->essence->channels; + free (gain->time); + free (gain->value); + + free (gain); +} + +void +aafi_freeAudioPan (aafiAudioPan* pan) +{ + aafi_freeAudioGain ((aafiAudioGain*)pan); } /** diff --git a/libs/aaf/AAFToText.c b/libs/aaf/AAFToText.c index 8edd0436f0..d3dda48283 100644 --- a/libs/aaf/AAFToText.c +++ b/libs/aaf/AAFToText.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -18,8 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include -#include +#include #include "aaf/AAFDefs/AAFClassDefUIDs.h" #include "aaf/AAFDefs/AAFCompressionDefs.h" @@ -40,28 +41,70 @@ #include "aaf/AAFClass.h" #include "aaf/utils.h" -const wchar_t* +#define debug(...) \ + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_DEBUG, __VA_ARGS__) + +#define warning(...) \ + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_WARNING, __VA_ARGS__) + +#define error(...) \ + AAF_LOG (aafd->log, aafd, DEBUG_SRC_ID_AAF_CORE, VERB_ERROR, __VA_ARGS__) + +const char* aaft_MobIDToText (aafMobID_t* mobid) { - static wchar_t str[127]; + size_t strsz = 200; + static char str[200]; - uint32_t i = 0; + size_t i = 0; uint32_t offset = 0; + int rc = 0; for (i = 0; i < sizeof (aafMobID_t); i++) { - if (i == 12) - offset += swprintf (str + offset, (2 * sizeof (aafMobID_t)), L" - "); - if (i == 13) - offset += swprintf (str + offset, (2 * sizeof (aafMobID_t)), L" - "); - if (i == 14) - offset += swprintf (str + offset, (2 * sizeof (aafMobID_t)), L" - "); - if (i == 15) - offset += swprintf (str + offset, (2 * sizeof (aafMobID_t)), L" - "); + switch (i) { + case 12: + case 13: + case 14: + case 15: + rc = snprintf (str + offset, strsz - offset, " - "); - offset += swprintf (str + offset, 127, L"%02x", ((unsigned char*)mobid)[i]); + assert (rc > 0 && (size_t)rc < strsz - offset); + // if ( rc < 0 || (size_t)rc >= strsz-offset ) { + // fprintf( stderr, "snprintf() error" ); + // return NULL; + // } + + offset += (uint32_t)rc; + + break; + + default: + break; + } + + rc = snprintf (str + offset, strsz - offset, "%02x", ((unsigned char*)mobid)[i]); + + assert (rc > 0 && (size_t)rc < strsz - offset); + + // if ( rc < 0 || (size_t)rc >= strsz-offset ) { + // fprintf( stderr, "snprintf() error" ); + // return "NULL"; + // } + + offset += (uint32_t)rc; if (i == 15) { - offset += swprintf (str + offset, 127, L" - "); + rc = snprintf (str + offset, strsz - offset, " - "); + + assert (rc > 0 && (size_t)rc < strsz - offset); + + // if ( rc < 0 || (size_t)rc >= strsz-offset ) { + // fprintf( stderr, "snprintf() error" ); + // return "NULL"; + // } + + offset += (uint32_t)rc; + break; } } @@ -70,15 +113,22 @@ aaft_MobIDToText (aafMobID_t* mobid) memcpy (&material, ((unsigned char*)mobid) + i, sizeof (aafUID_t)); - offset += swprintf (str + offset, 127, L"%" WPRIws, AUIDToText (&material)); + rc = snprintf (str + offset, strsz - offset, "%s", AUIDToText (&material)); + + assert (rc >= 0 && (size_t)rc < strsz - offset); + + // if ( rc < 0 || (size_t)rc >= strsz-offset ) { + // fprintf( stderr, "snprintf() error" ); + // return "NULL"; + // } return str; } -const wchar_t* +const char* aaft_TimestampToText (aafTimeStamp_t* ts) { - static wchar_t str[24]; + static char str[32]; if (ts == NULL) { str[0] = 'n'; @@ -86,23 +136,30 @@ aaft_TimestampToText (aafTimeStamp_t* ts) str[2] = 'a'; str[3] = '\0'; } else { - swprintf (str, sizeof (str), L"%04i-%02u-%02u %02u:%02u:%02u.%02u", - ts->date.year, - ts->date.month, - ts->date.day, - ts->time.hour, - ts->time.minute, - ts->time.second, - ts->time.fraction); + int rc = snprintf (str, sizeof (str), "%04i-%02u-%02u %02u:%02u:%02u.%02u", + ts->date.year, + ts->date.month, + ts->date.day, + ts->time.hour, + ts->time.minute, + ts->time.second, + ts->time.fraction); + + assert (rc > 0 && (size_t)rc < sizeof (str)); + + // if ( rc < 0 || (size_t)rc >= sizeof(str) ) { + // fprintf( stderr, "snprintf() error" ); + // return "NULL"; + // } } return str; } -const wchar_t* +const char* aaft_VersionToText (aafVersionType_t* vers) { - static wchar_t str[16]; + static char str[16]; if (vers == NULL) { str[0] = 'n'; @@ -110,18 +167,25 @@ aaft_VersionToText (aafVersionType_t* vers) str[2] = 'a'; str[3] = '\0'; } else { - swprintf (str, sizeof (str), L"%i.%i", - vers->major, - vers->minor); + int rc = snprintf (str, sizeof (str), "%i.%i", + vers->major, + vers->minor); + + assert (rc > 0 && (size_t)rc < sizeof (str)); + + // if ( rc < 0 || (size_t)rc >= sizeof(str) ) { + // fprintf( stderr, "snprintf() error" ); + // return "NULL"; + // } } return str; } -const wchar_t* +const char* aaft_ProductVersionToText (aafProductVersion_t* vers) { - static wchar_t str[64]; + static char str[64]; if (vers == NULL) { str[0] = 'n'; @@ -129,1726 +193,1772 @@ aaft_ProductVersionToText (aafProductVersion_t* vers) str[2] = 'a'; str[3] = '\0'; } else { - swprintf (str, sizeof (str), L"%u.%u.%u.%u %" WPRIws L" (%i)", - vers->major, - vers->minor, - vers->tertiary, - vers->patchLevel, - aaft_ProductReleaseTypeToText (vers->type), - vers->type); + int rc = snprintf (str, sizeof (str), "%u.%u.%u.%u %s (%i)", + vers->major, + vers->minor, + vers->tertiary, + vers->patchLevel, + aaft_ProductReleaseTypeToText (vers->type), + vers->type); + + assert (rc > 0 && (size_t)rc < sizeof (str)); + + // if ( rc < 0 || (size_t)rc >= sizeof(str) ) { + // fprintf( stderr, "snprintf() error" ); + // return "NULL"; + // } } return str; } -const wchar_t* +const char* aaft_FileKindToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; /* NOTE: AAFUID_NULL = AAFFileKind_DontCare */ if (aafUIDCmp (auid, &AAFFileKind_DontCare)) - return L"AAFFileKind_DontCare"; + return "AAFFileKind_DontCare"; if (aafUIDCmp (auid, &AAFFileKind_Aaf512Binary)) - return L"AAFFileKind_Aaf512Binary"; + return "AAFFileKind_Aaf512Binary"; if (aafUIDCmp (auid, &AAFFileKind_Aaf4KBinary)) - return L"AAFFileKind_Aaf4KBinary"; + return "AAFFileKind_Aaf4KBinary"; if (aafUIDCmp (auid, &AAFFileKind_AafXmlText)) - return L"AAFFileKind_AafXmlText"; + return "AAFFileKind_AafXmlText"; if (aafUIDCmp (auid, &AAFFileKind_AafKlvBinary)) - return L"AAFFileKind_AafKlvBinary"; + return "AAFFileKind_AafKlvBinary"; if (aafUIDCmp (auid, &AAFFileKind_AafM512Binary)) - return L"AAFFileKind_AafM512Binary"; + return "AAFFileKind_AafM512Binary"; if (aafUIDCmp (auid, &AAFFileKind_AafS512Binary)) - return L"AAFFileKind_AafS512Binary"; + return "AAFFileKind_AafS512Binary"; if (aafUIDCmp (auid, &AAFFileKind_AafG512Binary)) - return L"AAFFileKind_AafG512Binary"; + return "AAFFileKind_AafG512Binary"; if (aafUIDCmp (auid, &AAFFileKind_AafM4KBinary)) - return L"AAFFileKind_AafM4KBinary"; + return "AAFFileKind_AafM4KBinary"; if (aafUIDCmp (auid, &AAFFileKind_AafS4KBinary)) - return L"AAFFileKind_AafS4KBinary"; + return "AAFFileKind_AafS4KBinary"; if (aafUIDCmp (auid, &AAFFileKind_AafG4KBinary)) - return L"AAFFileKind_AafG4KBinary"; + return "AAFFileKind_AafG4KBinary"; if (aafUIDCmp (auid, &AAFFileKind_Pathological)) - return L"AAFFileKind_Pathological"; + return "AAFFileKind_Pathological"; - return L"Unknown AAFFileKind"; + return "Unknown AAFFileKind"; } -const wchar_t* +const char* aaft_TapeCaseTypeToText (aafTapeCaseType_t t) { switch (t) { case AAFTapeCaseNull: - return L"AAFTapeCaseNull"; + return "AAFTapeCaseNull"; case AAFThreeFourthInchVideoTape: - return L"AAFThreeFourthInchVideoTape"; + return "AAFThreeFourthInchVideoTape"; case AAFVHSVideoTape: - return L"AAFVHSVideoTape"; + return "AAFVHSVideoTape"; case AAF8mmVideoTape: - return L"AAF8mmVideoTape"; + return "AAF8mmVideoTape"; case AAFBetacamVideoTape: - return L"AAFBetacamVideoTape"; + return "AAFBetacamVideoTape"; case AAFCompactCassette: - return L"AAFCompactCassette"; + return "AAFCompactCassette"; case AAFDATCartridge: - return L"AAFDATCartridge"; + return "AAFDATCartridge"; case AAFNagraAudioTape: - return L"AAFNagraAudioTape"; + return "AAFNagraAudioTape"; } - return L"Unknown TapeCaseType"; + return "Unknown TapeCaseType"; } -const wchar_t* +const char* aaft_VideoSignalTypeToText (aafVideoSignalType_t v) { switch (v) { case AAFVideoSignalNull: - return L"AAFVideoSignalNull"; + return "AAFVideoSignalNull"; case AAFNTSCSignal: - return L"AAFNTSCSignal"; + return "AAFNTSCSignal"; case AAFPALSignal: - return L"AAFPALSignal"; + return "AAFPALSignal"; case AAFSECAMSignal: - return L"AAFSECAMSignal"; + return "AAFSECAMSignal"; } - return L"Unknown VideoSignalType"; + return "Unknown VideoSignalType"; } -const wchar_t* +const char* aaft_TapeFormatTypeToText (aafTapeFormatType_t t) { switch (t) { case AAFTapeFormatNull: - return L"AAFTapeFormatNull"; + return "AAFTapeFormatNull"; case AAFBetacamFormat: - return L"AAFBetacamFormat"; + return "AAFBetacamFormat"; case AAFBetacamSPFormat: - return L"AAFBetacamSPFormat"; + return "AAFBetacamSPFormat"; case AAFVHSFormat: - return L"AAFVHSFormat"; + return "AAFVHSFormat"; case AAFSVHSFormat: - return L"AAFSVHSFormat"; + return "AAFSVHSFormat"; case AAF8mmFormat: - return L"AAF8mmFormat"; + return "AAF8mmFormat"; case AAFHi8Format: - return L"AAFHi8Format"; + return "AAFHi8Format"; } - return L"Unknown TapeFormatType"; + return "Unknown TapeFormatType"; } -const wchar_t* +const char* aaft_FilmTypeToText (aafFilmType_t f) { switch (f) { case AAFFtNull: - return L"AAFFtNull"; + return "AAFFtNull"; case AAFFt35MM: - return L"AAFFt35MM"; + return "AAFFt35MM"; case AAFFt16MM: - return L"AAFFt16MM"; + return "AAFFt16MM"; case AAFFt8MM: - return L"AAFFt8MM"; + return "AAFFt8MM"; case AAFFt65MM: - return L"AAFFt65MM"; + return "AAFFt65MM"; } - return L"Unknown FilmType"; + return "Unknown FilmType"; } -const wchar_t* +const char* aaft_SignalStandardToText (aafSignalStandard_t s) { switch (s) { case AAFSignalStandard_None: - return L"AAFSignalStandard_None"; + return "AAFSignalStandard_None"; case AAFSignalStandard_ITU601: - return L"AAFSignalStandard_ITU601"; + return "AAFSignalStandard_ITU601"; case AAFSignalStandard_ITU1358: - return L"AAFSignalStandard_ITU1358"; + return "AAFSignalStandard_ITU1358"; case AAFSignalStandard_SMPTE347M: - return L"AAFSignalStandard_SMPTE347M"; + return "AAFSignalStandard_SMPTE347M"; case AAFSignalStandard_SMPTE274M: - return L"AAFSignalStandard_SMPTE274M"; + return "AAFSignalStandard_SMPTE274M"; case AAFSignalStandard_SMPTE296M: - return L"AAFSignalStandard_SMPTE296M"; + return "AAFSignalStandard_SMPTE296M"; case AAFSignalStandard_SMPTE349M: - return L"AAFSignalStandard_SMPTE349M"; + return "AAFSignalStandard_SMPTE349M"; } - return L"Unknown SignalStandard"; + return "Unknown SignalStandard"; } -const wchar_t* +const char* aaft_FieldNumberToText (aafFieldNumber_t f) { switch (f) { case AAFUnspecifiedField: - return L"AAFUnspecifiedField"; + return "AAFUnspecifiedField"; case AAFFieldOne: - return L"AAFFieldOne"; + return "AAFFieldOne"; case AAFFieldTwo: - return L"AAFFieldTwo"; + return "AAFFieldTwo"; } - return L"Unknown FieldNumber"; + return "Unknown FieldNumber"; } -const wchar_t* +const char* aaft_AlphaTransparencyToText (aafAlphaTransparency_t a) { switch (a) { case AAFMinValueTransparent: - return L"AAFMinValueTransparent"; + return "AAFMinValueTransparent"; case AAFMaxValueTransparent: - return L"AAFMaxValueTransparent"; + return "AAFMaxValueTransparent"; } - return L"Unknown AlphaTransparency"; + return "Unknown AlphaTransparency"; } -const wchar_t* +const char* aaft_FrameLayoutToText (aafFrameLayout_t f) { switch (f) { case AAFFullFrame: - return L"AAFFullFrame"; + return "AAFFullFrame"; case AAFSeparateFields: - return L"AAFSeparateFields"; + return "AAFSeparateFields"; case AAFOneField: - return L"AAFOneField"; + return "AAFOneField"; case AAFMixedFields: - return L"AAFMixedFields"; + return "AAFMixedFields"; case AAFSegmentedFrame: - return L"AAFSegmentedFrame"; + return "AAFSegmentedFrame"; } - return L"Unknown FrameLayout"; + return "Unknown FrameLayout"; } -const wchar_t* +const char* aaft_ColorSitingToText (aafColorSiting_t c) { switch (c) { case AAFCoSiting: - return L"AAFCoSiting"; + return "AAFCoSiting"; case AAFAveraging: - return L"AAFAveraging"; + return "AAFAveraging"; case AAFThreeTap: - return L"AAFThreeTap"; + return "AAFThreeTap"; case AAFQuincunx: - return L"AAFQuincunx"; + return "AAFQuincunx"; case AAFRec601: - return L"AAFRec601"; + return "AAFRec601"; case AAFUnknownSiting: - return L"AAFUnknownSiting"; + return "AAFUnknownSiting"; } - return L"Unknown ColorSiting"; + return "Unknown ColorSiting"; } -const wchar_t* +const char* aaft_ProductReleaseTypeToText (aafProductReleaseType_t t) { switch (t) { case AAFVersionUnknown: - return L"AAFVersionUnknown"; + return "AAFVersionUnknown"; case AAFVersionReleased: - return L"AAFVersionReleased"; + return "AAFVersionReleased"; case AAFVersionDebug: - return L"AAFVersionDebug"; + return "AAFVersionDebug"; case AAFVersionPatched: - return L"AAFVersionPatched"; + return "AAFVersionPatched"; case AAFVersionBeta: - return L"AAFVersionBeta"; + return "AAFVersionBeta"; case AAFVersionPrivateBuild: - return L"AAFVersionPrivateBuild"; + return "AAFVersionPrivateBuild"; } - return L"Unknown ProductReleaseType"; + return "Unknown ProductReleaseType"; } -const wchar_t* +const char* aaft_FadeTypeToText (aafFadeType_t f) { switch (f) { case AAFFadeNone: - return L"AAFFadeNone"; + return "AAFFadeNone"; case AAFFadeLinearAmp: - return L"AAFFadeLinearAmp"; + return "AAFFadeLinearAmp"; case AAFFadeLinearPower: - return L"AAFFadeLinearPower"; + return "AAFFadeLinearPower"; } - return L"Unknown FadeType"; + return "Unknown FadeType"; } -const wchar_t* +const char* aaft_BoolToText (aafBoolean_t b) { switch (b) { case 1: - return L"True"; + return "True"; case 0: - return L"False"; + return "False"; } - return L"Unknown Boolean"; + return "Unknown Boolean"; } -const wchar_t* +const char* aaft_OperationCategoryToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFOperationCategory_Effect)) - return L"AAFOperationCategory_Effect"; + return "AAFOperationCategory_Effect"; - return L"Unknown AAFOperationCategory"; + return "Unknown AAFOperationCategory"; } -const wchar_t* +const char* aaft_PluginCategoryToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFPluginCategory_Effect)) - return L"AAFPluginCategory_Effect"; + return "AAFPluginCategory_Effect"; if (aafUIDCmp (auid, &AAFPluginCategory_Codec)) - return L"AAFPluginCategory_Codec"; + return "AAFPluginCategory_Codec"; if (aafUIDCmp (auid, &AAFPluginCategory_Interpolation)) - return L"AAFPluginCategory_Interpolation"; + return "AAFPluginCategory_Interpolation"; - return L"Unknown AAFPluginCategory"; + return "Unknown AAFPluginCategory"; } -const wchar_t* +const char* aaft_ScanningDirectionToText (aafScanningDirection_t s) { switch (s) { case AAFScanningDirection_LeftToRightTopToBottom: - return L"AAFScanningDirection_LeftToRightTopToBottom"; + return "AAFScanningDirection_LeftToRightTopToBottom"; case AAFScanningDirection_RightToLeftTopToBottom: - return L"AAFScanningDirection_RightToLeftTopToBottom"; + return "AAFScanningDirection_RightToLeftTopToBottom"; case AAFScanningDirection_LeftToRightBottomToTop: - return L"AAFScanningDirection_LeftToRightBottomToTop"; + return "AAFScanningDirection_LeftToRightBottomToTop"; case AAFScanningDirection_RightToLeftBottomToTop: - return L"AAFScanningDirection_RightToLeftBottomToTop"; + return "AAFScanningDirection_RightToLeftBottomToTop"; case AAFScanningDirection_TopToBottomLeftToRight: - return L"AAFScanningDirection_TopToBottomLeftToRight"; + return "AAFScanningDirection_TopToBottomLeftToRight"; case AAFScanningDirection_TopToBottomRightToLeft: - return L"AAFScanningDirection_TopToBottomRightToLeft"; + return "AAFScanningDirection_TopToBottomRightToLeft"; case AAFScanningDirection_BottomToTopLeftToRight: - return L"AAFScanningDirection_BottomToTopLeftToRight"; + return "AAFScanningDirection_BottomToTopLeftToRight"; case AAFScanningDirection_BottomToTopRightToLeft: - return L"AAFScanningDirection_BottomToTopRightToLeft"; + return "AAFScanningDirection_BottomToTopRightToLeft"; } - return L"Unknown AAFScanningDirection"; + return "Unknown AAFScanningDirection"; } -const wchar_t* +const char* aaft_ByteOrderToText (int16_t bo) { switch (bo) { case AAF_HEADER_BYTEORDER_LE: case AAF_PROPERTIES_BYTEORDER_LE: - return L"Little-Endian"; + return "Little-Endian"; case AAF_HEADER_BYTEORDER_BE: case AAF_PROPERTIES_BYTEORDER_BE: - return L"Big-Endian"; + return "Big-Endian"; } - return L"Unknown ByteOrder"; + return "Unknown ByteOrder"; } -const wchar_t* +const char* aaft_ElectroSpatialToText (aafElectroSpatialFormulation_t e) { switch (e) { case AAFElectroSpatialFormulation_Default: - return L"AAFElectroSpatialFormulation_Default"; + return "AAFElectroSpatialFormulation_Default"; case AAFElectroSpatialFormulation_TwoChannelMode: - return L"AAFElectroSpatialFormulation_TwoChannelMode"; + return "AAFElectroSpatialFormulation_TwoChannelMode"; case AAFElectroSpatialFormulation_SingleChannelMode: - return L"AAFElectroSpatialFormulation_SingleChannelMode"; + return "AAFElectroSpatialFormulation_SingleChannelMode"; case AAFElectroSpatialFormulation_PrimarySecondaryMode: - return L"AAFElectroSpatialFormulation_PrimarySecondaryMode"; + return "AAFElectroSpatialFormulation_PrimarySecondaryMode"; case AAFElectroSpatialFormulation_StereophonicMode: - return L"AAFElectroSpatialFormulation_StereophonicMode"; + return "AAFElectroSpatialFormulation_StereophonicMode"; case AAFElectroSpatialFormulation_SingleChannelDoubleSamplingFrequencyMode: - return L"AAFElectroSpatialFormulation_SingleChannelDoubleSamplingFrequencyMode"; + return "AAFElectroSpatialFormulation_SingleChannelDoubleSamplingFrequencyMode"; case AAFElectroSpatialFormulation_StereoLeftChannelDoubleSamplingFrequencyMode: - return L"AAFElectroSpatialFormulation_StereoLeftChannelDoubleSamplingFrequencyMode"; + return "AAFElectroSpatialFormulation_StereoLeftChannelDoubleSamplingFrequencyMode"; case AAFElectroSpatialFormulation_StereoRightChannelDoubleSamplingFrequencyMode: - return L"AAFElectroSpatialFormulation_StereoRightChannelDoubleSamplingFrequencyMode"; + return "AAFElectroSpatialFormulation_StereoRightChannelDoubleSamplingFrequencyMode"; case AAFElectroSpatialFormulation_MultiChannelMode: - return L"AAFElectroSpatialFormulation_MultiChannelMode"; + return "AAFElectroSpatialFormulation_MultiChannelMode"; } - return L"Unknown AAFElectroSpatialFormulation"; + return "Unknown AAFElectroSpatialFormulation"; } -const wchar_t* +const char* aaft_StoredFormToText (enum aafStoredForm_e sf) { switch (sf) { case SF_DATA: - return L"SF_DATA"; + return "SF_DATA"; case SF_DATA_STREAM: - return L"SF_DATA_STREAM"; + return "SF_DATA_STREAM"; case SF_STRONG_OBJECT_REFERENCE: - return L"SF_STRONG_OBJECT_REFERENCE"; + return "SF_STRONG_OBJECT_REFERENCE"; case SF_STRONG_OBJECT_REFERENCE_VECTOR: - return L"SF_STRONG_OBJECT_REFERENCE_VECTOR"; + return "SF_STRONG_OBJECT_REFERENCE_VECTOR"; case SF_STRONG_OBJECT_REFERENCE_SET: - return L"SF_STRONG_OBJECT_REFERENCE_SET"; + return "SF_STRONG_OBJECT_REFERENCE_SET"; case SF_WEAK_OBJECT_REFERENCE: - return L"SF_WEAK_OBJECT_REFERENCE"; + return "SF_WEAK_OBJECT_REFERENCE"; case SF_WEAK_OBJECT_REFERENCE_VECTOR: - return L"SF_WEAK_OBJECT_REFERENCE_VECTOR"; + return "SF_WEAK_OBJECT_REFERENCE_VECTOR"; case SF_WEAK_OBJECT_REFERENCE_SET: - return L"SF_WEAK_OBJECT_REFERENCE_SET"; + return "SF_WEAK_OBJECT_REFERENCE_SET"; case SF_WEAK_OBJECT_REFERENCE_STORED_OBJECT_ID: - return L"SF_WEAK_OBJECT_REFERENCE_STORED_OBJECT_ID"; + return "SF_WEAK_OBJECT_REFERENCE_STORED_OBJECT_ID"; case SF_UNIQUE_OBJECT_ID: - return L"SF_UNIQUE_OBJECT_ID"; + return "SF_UNIQUE_OBJECT_ID"; case SF_OPAQUE_STREAM: - return L"SF_OPAQUE_STREAM"; + return "SF_OPAQUE_STREAM"; } - return L"Unknown StoredForm"; + return "Unknown StoredForm"; } -const wchar_t* +const char* aaft_OPDefToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFOPDef_EditProtocol)) - return L"AAFOPDef_EditProtocol"; + return "AAFOPDef_EditProtocol"; if (aafUIDCmp (auid, &AAFOPDef_Unconstrained)) - return L"AAFOPDef_Unconstrained"; + return "AAFOPDef_Unconstrained"; - return L"Unknown AAFOPDef"; + return "Unknown AAFOPDef"; } -const wchar_t* +const char* aaft_TypeIDToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFTypeID_UInt8)) - return L"AAFTypeID_UInt8"; + return "AAFTypeID_UInt8"; if (aafUIDCmp (auid, &AAFTypeID_UInt16)) - return L"AAFTypeID_UInt16"; + return "AAFTypeID_UInt16"; if (aafUIDCmp (auid, &AAFTypeID_UInt32)) - return L"AAFTypeID_UInt32"; + return "AAFTypeID_UInt32"; if (aafUIDCmp (auid, &AAFTypeID_UInt64)) - return L"AAFTypeID_UInt64"; + return "AAFTypeID_UInt64"; if (aafUIDCmp (auid, &AAFTypeID_Int8)) - return L"AAFTypeID_Int8"; + return "AAFTypeID_Int8"; if (aafUIDCmp (auid, &AAFTypeID_Int16)) - return L"AAFTypeID_Int16"; + return "AAFTypeID_Int16"; if (aafUIDCmp (auid, &AAFTypeID_Int32)) - return L"AAFTypeID_Int32"; + return "AAFTypeID_Int32"; if (aafUIDCmp (auid, &AAFTypeID_Int64)) - return L"AAFTypeID_Int64"; + return "AAFTypeID_Int64"; if (aafUIDCmp (auid, &AAFTypeID_PositionType)) - return L"AAFTypeID_PositionType"; + return "AAFTypeID_PositionType"; if (aafUIDCmp (auid, &AAFTypeID_LengthType)) - return L"AAFTypeID_LengthType"; + return "AAFTypeID_LengthType"; if (aafUIDCmp (auid, &AAFTypeID_JPEGTableIDType)) - return L"AAFTypeID_JPEGTableIDType"; + return "AAFTypeID_JPEGTableIDType"; if (aafUIDCmp (auid, &AAFTypeID_PhaseFrameType)) - return L"AAFTypeID_PhaseFrameType"; + return "AAFTypeID_PhaseFrameType"; if (aafUIDCmp (auid, &AAFTypeID_AUID)) - return L"AAFTypeID_AUID"; + return "AAFTypeID_AUID"; if (aafUIDCmp (auid, &AAFTypeID_MobIDType)) - return L"AAFTypeID_MobIDType"; + return "AAFTypeID_MobIDType"; if (aafUIDCmp (auid, &AAFTypeID_Boolean)) - return L"AAFTypeID_Boolean"; + return "AAFTypeID_Boolean"; if (aafUIDCmp (auid, &AAFTypeID_Character)) - return L"AAFTypeID_Character"; + return "AAFTypeID_Character"; if (aafUIDCmp (auid, &AAFTypeID_String)) - return L"AAFTypeID_String"; + return "AAFTypeID_String"; if (aafUIDCmp (auid, &AAFTypeID_ProductReleaseType)) - return L"AAFTypeID_ProductReleaseType"; + return "AAFTypeID_ProductReleaseType"; if (aafUIDCmp (auid, &AAFTypeID_TapeFormatType)) - return L"AAFTypeID_TapeFormatType"; + return "AAFTypeID_TapeFormatType"; if (aafUIDCmp (auid, &AAFTypeID_VideoSignalType)) - return L"AAFTypeID_VideoSignalType"; + return "AAFTypeID_VideoSignalType"; if (aafUIDCmp (auid, &AAFTypeID_TapeCaseType)) - return L"AAFTypeID_TapeCaseType"; + return "AAFTypeID_TapeCaseType"; if (aafUIDCmp (auid, &AAFTypeID_ColorSitingType)) - return L"AAFTypeID_ColorSitingType"; + return "AAFTypeID_ColorSitingType"; if (aafUIDCmp (auid, &AAFTypeID_EditHintType)) - return L"AAFTypeID_EditHintType"; + return "AAFTypeID_EditHintType"; if (aafUIDCmp (auid, &AAFTypeID_FadeType)) - return L"AAFTypeID_FadeType"; + return "AAFTypeID_FadeType"; if (aafUIDCmp (auid, &AAFTypeID_LayoutType)) - return L"AAFTypeID_LayoutType"; + return "AAFTypeID_LayoutType"; if (aafUIDCmp (auid, &AAFTypeID_TCSource)) - return L"AAFTypeID_TCSource"; + return "AAFTypeID_TCSource"; if (aafUIDCmp (auid, &AAFTypeID_PulldownDirectionType)) - return L"AAFTypeID_PulldownDirectionType"; + return "AAFTypeID_PulldownDirectionType"; if (aafUIDCmp (auid, &AAFTypeID_PulldownKindType)) - return L"AAFTypeID_PulldownKindType"; + return "AAFTypeID_PulldownKindType"; if (aafUIDCmp (auid, &AAFTypeID_EdgeType)) - return L"AAFTypeID_EdgeType"; + return "AAFTypeID_EdgeType"; if (aafUIDCmp (auid, &AAFTypeID_FilmType)) - return L"AAFTypeID_FilmType"; + return "AAFTypeID_FilmType"; if (aafUIDCmp (auid, &AAFTypeID_RGBAComponentKind)) - return L"AAFTypeID_RGBAComponentKind"; + return "AAFTypeID_RGBAComponentKind"; if (aafUIDCmp (auid, &AAFTypeID_ReferenceType)) - return L"AAFTypeID_ReferenceType"; + return "AAFTypeID_ReferenceType"; if (aafUIDCmp (auid, &AAFTypeID_AlphaTransparencyType)) - return L"AAFTypeID_AlphaTransparencyType"; + return "AAFTypeID_AlphaTransparencyType"; if (aafUIDCmp (auid, &AAFTypeID_FieldNumber)) - return L"AAFTypeID_FieldNumber"; + return "AAFTypeID_FieldNumber"; if (aafUIDCmp (auid, &AAFTypeID_ElectroSpatialFormulation)) - return L"AAFTypeID_ElectroSpatialFormulation"; + return "AAFTypeID_ElectroSpatialFormulation"; if (aafUIDCmp (auid, &AAFTypeID_EmphasisType)) - return L"AAFTypeID_EmphasisType"; + return "AAFTypeID_EmphasisType"; if (aafUIDCmp (auid, &AAFTypeID_AuxBitsModeType)) - return L"AAFTypeID_AuxBitsModeType"; + return "AAFTypeID_AuxBitsModeType"; if (aafUIDCmp (auid, &AAFTypeID_ChannelStatusModeType)) - return L"AAFTypeID_ChannelStatusModeType"; + return "AAFTypeID_ChannelStatusModeType"; if (aafUIDCmp (auid, &AAFTypeID_UserDataModeType)) - return L"AAFTypeID_UserDataModeType"; + return "AAFTypeID_UserDataModeType"; if (aafUIDCmp (auid, &AAFTypeID_SignalStandardType)) - return L"AAFTypeID_SignalStandardType"; + return "AAFTypeID_SignalStandardType"; if (aafUIDCmp (auid, &AAFTypeID_ScanningDirectionType)) - return L"AAFTypeID_ScanningDirectionType"; + return "AAFTypeID_ScanningDirectionType"; if (aafUIDCmp (auid, &AAFTypeID_ContentScanningType)) - return L"AAFTypeID_ContentScanningType"; + return "AAFTypeID_ContentScanningType"; if (aafUIDCmp (auid, &AAFTypeID_TitleAlignmentType)) - return L"AAFTypeID_TitleAlignmentType"; + return "AAFTypeID_TitleAlignmentType"; if (aafUIDCmp (auid, &AAFTypeID_OperationCategoryType)) - return L"AAFTypeID_OperationCategoryType"; + return "AAFTypeID_OperationCategoryType"; if (aafUIDCmp (auid, &AAFTypeID_TransferCharacteristicType)) - return L"AAFTypeID_TransferCharacteristicType"; + return "AAFTypeID_TransferCharacteristicType"; if (aafUIDCmp (auid, &AAFTypeID_PluginCategoryType)) - return L"AAFTypeID_PluginCategoryType"; + return "AAFTypeID_PluginCategoryType"; if (aafUIDCmp (auid, &AAFTypeID_UsageType)) - return L"AAFTypeID_UsageType"; + return "AAFTypeID_UsageType"; if (aafUIDCmp (auid, &AAFTypeID_ColorPrimariesType)) - return L"AAFTypeID_ColorPrimariesType"; + return "AAFTypeID_ColorPrimariesType"; if (aafUIDCmp (auid, &AAFTypeID_CodingEquationsType)) - return L"AAFTypeID_CodingEquationsType"; + return "AAFTypeID_CodingEquationsType"; if (aafUIDCmp (auid, &AAFTypeID_Rational)) - return L"AAFTypeID_Rational"; + return "AAFTypeID_Rational"; if (aafUIDCmp (auid, &AAFTypeID_ProductVersion)) - return L"AAFTypeID_ProductVersion"; + return "AAFTypeID_ProductVersion"; if (aafUIDCmp (auid, &AAFTypeID_VersionType)) - return L"AAFTypeID_VersionType"; + return "AAFTypeID_VersionType"; if (aafUIDCmp (auid, &AAFTypeID_RGBAComponent)) - return L"AAFTypeID_RGBAComponent"; + return "AAFTypeID_RGBAComponent"; if (aafUIDCmp (auid, &AAFTypeID_DateStruct)) - return L"AAFTypeID_DateStruct"; + return "AAFTypeID_DateStruct"; if (aafUIDCmp (auid, &AAFTypeID_TimeStruct)) - return L"AAFTypeID_TimeStruct"; + return "AAFTypeID_TimeStruct"; if (aafUIDCmp (auid, &AAFTypeID_TimeStamp)) - return L"AAFTypeID_TimeStamp"; + return "AAFTypeID_TimeStamp"; if (aafUIDCmp (auid, &AAFTypeID_UInt8Array)) - return L"AAFTypeID_UInt8Array"; + return "AAFTypeID_UInt8Array"; if (aafUIDCmp (auid, &AAFTypeID_UInt8Array12)) - return L"AAFTypeID_UInt8Array12"; + return "AAFTypeID_UInt8Array12"; if (aafUIDCmp (auid, &AAFTypeID_Int32Array)) - return L"AAFTypeID_Int32Array"; + return "AAFTypeID_Int32Array"; if (aafUIDCmp (auid, &AAFTypeID_Int64Array)) - return L"AAFTypeID_Int64Array"; + return "AAFTypeID_Int64Array"; if (aafUIDCmp (auid, &AAFTypeID_StringArray)) - return L"AAFTypeID_StringArray"; + return "AAFTypeID_StringArray"; if (aafUIDCmp (auid, &AAFTypeID_AUIDArray)) - return L"AAFTypeID_AUIDArray"; + return "AAFTypeID_AUIDArray"; if (aafUIDCmp (auid, &AAFTypeID_PositionArray)) - return L"AAFTypeID_PositionArray"; + return "AAFTypeID_PositionArray"; if (aafUIDCmp (auid, &AAFTypeID_UInt8Array8)) - return L"AAFTypeID_UInt8Array8"; + return "AAFTypeID_UInt8Array8"; if (aafUIDCmp (auid, &AAFTypeID_UInt32Array)) - return L"AAFTypeID_UInt32Array"; + return "AAFTypeID_UInt32Array"; if (aafUIDCmp (auid, &AAFTypeID_ChannelStatusModeArray)) - return L"AAFTypeID_ChannelStatusModeArray"; + return "AAFTypeID_ChannelStatusModeArray"; if (aafUIDCmp (auid, &AAFTypeID_UserDataModeArray)) - return L"AAFTypeID_UserDataModeArray"; + return "AAFTypeID_UserDataModeArray"; if (aafUIDCmp (auid, &AAFTypeID_RGBALayout)) - return L"AAFTypeID_RGBALayout"; + return "AAFTypeID_RGBALayout"; if (aafUIDCmp (auid, &AAFTypeID_AUIDSet)) - return L"AAFTypeID_AUIDSet"; + return "AAFTypeID_AUIDSet"; if (aafUIDCmp (auid, &AAFTypeID_UInt32Set)) - return L"AAFTypeID_UInt32Set"; + return "AAFTypeID_UInt32Set"; if (aafUIDCmp (auid, &AAFTypeID_DataValue)) - return L"AAFTypeID_DataValue"; + return "AAFTypeID_DataValue"; if (aafUIDCmp (auid, &AAFTypeID_Stream)) - return L"AAFTypeID_Stream"; + return "AAFTypeID_Stream"; if (aafUIDCmp (auid, &AAFTypeID_Indirect)) - return L"AAFTypeID_Indirect"; + return "AAFTypeID_Indirect"; if (aafUIDCmp (auid, &AAFTypeID_Opaque)) - return L"AAFTypeID_Opaque"; + return "AAFTypeID_Opaque"; if (aafUIDCmp (auid, &AAFTypeID_ClassDefinitionWeakReference)) - return L"AAFTypeID_ClassDefinitionWeakReference"; + return "AAFTypeID_ClassDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_ContainerDefinitionWeakReference)) - return L"AAFTypeID_ContainerDefinitionWeakReference"; + return "AAFTypeID_ContainerDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_DataDefinitionWeakReference)) - return L"AAFTypeID_DataDefinitionWeakReference"; + return "AAFTypeID_DataDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_InterpolationDefinitionWeakReference)) - return L"AAFTypeID_InterpolationDefinitionWeakReference"; + return "AAFTypeID_InterpolationDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_MobWeakReference)) - return L"AAFTypeID_MobWeakReference"; + return "AAFTypeID_MobWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_OperationDefinitionWeakReference)) - return L"AAFTypeID_OperationDefinitionWeakReference"; + return "AAFTypeID_OperationDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_ParameterDefinitionWeakReference)) - return L"AAFTypeID_ParameterDefinitionWeakReference"; + return "AAFTypeID_ParameterDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_TypeDefinitionWeakReference)) - return L"AAFTypeID_TypeDefinitionWeakReference"; + return "AAFTypeID_TypeDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_PluginDefinitionWeakReference)) - return L"AAFTypeID_PluginDefinitionWeakReference"; + return "AAFTypeID_PluginDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_CodecDefinitionWeakReference)) - return L"AAFTypeID_CodecDefinitionWeakReference"; + return "AAFTypeID_CodecDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_PropertyDefinitionWeakReference)) - return L"AAFTypeID_PropertyDefinitionWeakReference"; + return "AAFTypeID_PropertyDefinitionWeakReference"; if (aafUIDCmp (auid, &AAFTypeID_ContentStorageStrongReference)) - return L"AAFTypeID_ContentStorageStrongReference"; + return "AAFTypeID_ContentStorageStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_DictionaryStrongReference)) - return L"AAFTypeID_DictionaryStrongReference"; + return "AAFTypeID_DictionaryStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_EssenceDescriptorStrongReference)) - return L"AAFTypeID_EssenceDescriptorStrongReference"; + return "AAFTypeID_EssenceDescriptorStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_NetworkLocatorStrongReference)) - return L"AAFTypeID_NetworkLocatorStrongReference"; + return "AAFTypeID_NetworkLocatorStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_OperationGroupStrongReference)) - return L"AAFTypeID_OperationGroupStrongReference"; + return "AAFTypeID_OperationGroupStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_SegmentStrongReference)) - return L"AAFTypeID_SegmentStrongReference"; + return "AAFTypeID_SegmentStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_SourceClipStrongReference)) - return L"AAFTypeID_SourceClipStrongReference"; + return "AAFTypeID_SourceClipStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_SourceReferenceStrongReference)) - return L"AAFTypeID_SourceReferenceStrongReference"; + return "AAFTypeID_SourceReferenceStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_ClassDefinitionStrongReference)) - return L"AAFTypeID_ClassDefinitionStrongReference"; + return "AAFTypeID_ClassDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_CodecDefinitionStrongReference)) - return L"AAFTypeID_CodecDefinitionStrongReference"; + return "AAFTypeID_CodecDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_ComponentStrongReference)) - return L"AAFTypeID_ComponentStrongReference"; + return "AAFTypeID_ComponentStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_ContainerDefinitionStrongReference)) - return L"AAFTypeID_ContainerDefinitionStrongReference"; + return "AAFTypeID_ContainerDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_ControlPointStrongReference)) - return L"AAFTypeID_ControlPointStrongReference"; + return "AAFTypeID_ControlPointStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_DataDefinitionStrongReference)) - return L"AAFTypeID_DataDefinitionStrongReference"; + return "AAFTypeID_DataDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_EssenceDataStrongReference)) - return L"AAFTypeID_EssenceDataStrongReference"; + return "AAFTypeID_EssenceDataStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_IdentificationStrongReference)) - return L"AAFTypeID_IdentificationStrongReference"; + return "AAFTypeID_IdentificationStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_InterpolationDefinitionStrongReference)) - return L"AAFTypeID_InterpolationDefinitionStrongReference"; + return "AAFTypeID_InterpolationDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_LocatorStrongReference)) - return L"AAFTypeID_LocatorStrongReference"; + return "AAFTypeID_LocatorStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_MobStrongReference)) - return L"AAFTypeID_MobStrongReference"; + return "AAFTypeID_MobStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_MobSlotStrongReference)) - return L"AAFTypeID_MobSlotStrongReference"; + return "AAFTypeID_MobSlotStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_OperationDefinitionStrongReference)) - return L"AAFTypeID_OperationDefinitionStrongReference"; + return "AAFTypeID_OperationDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_ParameterStrongReference)) - return L"AAFTypeID_ParameterStrongReference"; + return "AAFTypeID_ParameterStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_ParameterDefinitionStrongReference)) - return L"AAFTypeID_ParameterDefinitionStrongReference"; + return "AAFTypeID_ParameterDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_PluginDefinitionStrongReference)) - return L"AAFTypeID_PluginDefinitionStrongReference"; + return "AAFTypeID_PluginDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_PropertyDefinitionStrongReference)) - return L"AAFTypeID_PropertyDefinitionStrongReference"; + return "AAFTypeID_PropertyDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_TaggedValueStrongReference)) - return L"AAFTypeID_TaggedValueStrongReference"; + return "AAFTypeID_TaggedValueStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_TypeDefinitionStrongReference)) - return L"AAFTypeID_TypeDefinitionStrongReference"; + return "AAFTypeID_TypeDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_KLVDataStrongReference)) - return L"AAFTypeID_KLVDataStrongReference"; + return "AAFTypeID_KLVDataStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_FileDescriptorStrongReference)) - return L"AAFTypeID_FileDescriptorStrongReference"; + return "AAFTypeID_FileDescriptorStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_RIFFChunkStrongReference)) - return L"AAFTypeID_RIFFChunkStrongReference"; + return "AAFTypeID_RIFFChunkStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_DescriptiveFrameworkStrongReference)) - return L"AAFTypeID_DescriptiveFrameworkStrongReference"; + return "AAFTypeID_DescriptiveFrameworkStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_KLVDataDefinitionStrongReference)) - return L"AAFTypeID_KLVDataDefinitionStrongReference"; + return "AAFTypeID_KLVDataDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_TaggedValueDefinitionStrongReference)) - return L"AAFTypeID_TaggedValueDefinitionStrongReference"; + return "AAFTypeID_TaggedValueDefinitionStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_DescriptiveObjectStrongReference)) - return L"AAFTypeID_DescriptiveObjectStrongReference"; + return "AAFTypeID_DescriptiveObjectStrongReference"; if (aafUIDCmp (auid, &AAFTypeID_DataDefinitionWeakReferenceSet)) - return L"AAFTypeID_DataDefinitionWeakReferenceSet"; + return "AAFTypeID_DataDefinitionWeakReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_ParameterDefinitionWeakReferenceSet)) - return L"AAFTypeID_ParameterDefinitionWeakReferenceSet"; + return "AAFTypeID_ParameterDefinitionWeakReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_PluginDefinitionWeakReferenceSet)) - return L"AAFTypeID_PluginDefinitionWeakReferenceSet"; + return "AAFTypeID_PluginDefinitionWeakReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_PropertyDefinitionWeakReferenceSet)) - return L"AAFTypeID_PropertyDefinitionWeakReferenceSet"; + return "AAFTypeID_PropertyDefinitionWeakReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_OperationDefinitionWeakReferenceVector)) - return L"AAFTypeID_OperationDefinitionWeakReferenceVector"; + return "AAFTypeID_OperationDefinitionWeakReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_TypeDefinitionWeakReferenceVector)) - return L"AAFTypeID_TypeDefinitionWeakReferenceVector"; + return "AAFTypeID_TypeDefinitionWeakReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_DataDefinitionWeakReferenceVector)) - return L"AAFTypeID_DataDefinitionWeakReferenceVector"; + return "AAFTypeID_DataDefinitionWeakReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_ClassDefinitionStrongReferenceSet)) - return L"AAFTypeID_ClassDefinitionStrongReferenceSet"; + return "AAFTypeID_ClassDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_CodecDefinitionStrongReferenceSet)) - return L"AAFTypeID_CodecDefinitionStrongReferenceSet"; + return "AAFTypeID_CodecDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_ContainerDefinitionStrongReferenceSet)) - return L"AAFTypeID_ContainerDefinitionStrongReferenceSet"; + return "AAFTypeID_ContainerDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_DataDefinitionStrongReferenceSet)) - return L"AAFTypeID_DataDefinitionStrongReferenceSet"; + return "AAFTypeID_DataDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_EssenceDataStrongReferenceSet)) - return L"AAFTypeID_EssenceDataStrongReferenceSet"; + return "AAFTypeID_EssenceDataStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_InterpolationDefinitionStrongReferenceSet)) - return L"AAFTypeID_InterpolationDefinitionStrongReferenceSet"; + return "AAFTypeID_InterpolationDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_MobStrongReferenceSet)) - return L"AAFTypeID_MobStrongReferenceSet"; + return "AAFTypeID_MobStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_OperationDefinitionStrongReferenceSet)) - return L"AAFTypeID_OperationDefinitionStrongReferenceSet"; + return "AAFTypeID_OperationDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_ParameterDefinitionStrongReferenceSet)) - return L"AAFTypeID_ParameterDefinitionStrongReferenceSet"; + return "AAFTypeID_ParameterDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_PluginDefinitionStrongReferenceSet)) - return L"AAFTypeID_PluginDefinitionStrongReferenceSet"; + return "AAFTypeID_PluginDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_PropertyDefinitionStrongReferenceSet)) - return L"AAFTypeID_PropertyDefinitionStrongReferenceSet"; + return "AAFTypeID_PropertyDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_TypeDefinitionStrongReferenceSet)) - return L"AAFTypeID_TypeDefinitionStrongReferenceSet"; + return "AAFTypeID_TypeDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_KLVDataDefinitionStrongReferenceSet)) - return L"AAFTypeID_KLVDataDefinitionStrongReferenceSet"; + return "AAFTypeID_KLVDataDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_TaggedValueDefinitionStrongReferenceSet)) - return L"AAFTypeID_TaggedValueDefinitionStrongReferenceSet"; + return "AAFTypeID_TaggedValueDefinitionStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_DescriptiveObjectStrongReferenceSet)) - return L"AAFTypeID_DescriptiveObjectStrongReferenceSet"; + return "AAFTypeID_DescriptiveObjectStrongReferenceSet"; if (aafUIDCmp (auid, &AAFTypeID_ComponentStrongReferenceVector)) - return L"AAFTypeID_ComponentStrongReferenceVector"; + return "AAFTypeID_ComponentStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_ControlPointStrongReferenceVector)) - return L"AAFTypeID_ControlPointStrongReferenceVector"; + return "AAFTypeID_ControlPointStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_IdentificationStrongReferenceVector)) - return L"AAFTypeID_IdentificationStrongReferenceVector"; + return "AAFTypeID_IdentificationStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_LocatorStrongReferenceVector)) - return L"AAFTypeID_LocatorStrongReferenceVector"; + return "AAFTypeID_LocatorStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_MobSlotStrongReferenceVector)) - return L"AAFTypeID_MobSlotStrongReferenceVector"; + return "AAFTypeID_MobSlotStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_SegmentStrongReferenceVector)) - return L"AAFTypeID_SegmentStrongReferenceVector"; + return "AAFTypeID_SegmentStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_SourceReferenceStrongReferenceVector)) - return L"AAFTypeID_SourceReferenceStrongReferenceVector"; + return "AAFTypeID_SourceReferenceStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_TaggedValueStrongReferenceVector)) - return L"AAFTypeID_TaggedValueStrongReferenceVector"; + return "AAFTypeID_TaggedValueStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_KLVDataStrongReferenceVector)) - return L"AAFTypeID_KLVDataStrongReferenceVector"; + return "AAFTypeID_KLVDataStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_ParameterStrongReferenceVector)) - return L"AAFTypeID_ParameterStrongReferenceVector"; + return "AAFTypeID_ParameterStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_FileDescriptorStrongReferenceVector)) - return L"AAFTypeID_FileDescriptorStrongReferenceVector"; + return "AAFTypeID_FileDescriptorStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_RIFFChunkStrongReferenceVector)) - return L"AAFTypeID_RIFFChunkStrongReferenceVector"; + return "AAFTypeID_RIFFChunkStrongReferenceVector"; if (aafUIDCmp (auid, &AAFTypeID_DescriptiveObjectStrongReferenceVector)) - return L"AAFTypeID_DescriptiveObjectStrongReferenceVector"; + return "AAFTypeID_DescriptiveObjectStrongReferenceVector"; - return L"Unknown AAFTypeID"; + return "Unknown AAFTypeID"; } -const wchar_t* +const char* aaft_DataDefToText (AAF_Data* aafd, const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFDataDef_Picture)) - return L"AAFDataDef_Picture"; + return "AAFDataDef_Picture"; if (aafUIDCmp (auid, &AAFDataDef_LegacyPicture)) - return L"AAFDataDef_LegacyPicture"; + return "AAFDataDef_LegacyPicture"; if (aafUIDCmp (auid, &AAFDataDef_Matte)) - return L"AAFDataDef_Matte"; + return "AAFDataDef_Matte"; if (aafUIDCmp (auid, &AAFDataDef_PictureWithMatte)) - return L"AAFDataDef_PictureWithMatte"; + return "AAFDataDef_PictureWithMatte"; if (aafUIDCmp (auid, &AAFDataDef_Sound)) - return L"AAFDataDef_Sound"; + return "AAFDataDef_Sound"; if (aafUIDCmp (auid, &AAFDataDef_LegacySound)) - return L"AAFDataDef_LegacySound"; + return "AAFDataDef_LegacySound"; if (aafUIDCmp (auid, &AAFDataDef_Timecode)) - return L"AAFDataDef_Timecode"; + return "AAFDataDef_Timecode"; if (aafUIDCmp (auid, &AAFDataDef_LegacyTimecode)) - return L"AAFDataDef_LegacyTimecode"; + return "AAFDataDef_LegacyTimecode"; if (aafUIDCmp (auid, &AAFDataDef_Edgecode)) - return L"AAFDataDef_Edgecode"; + return "AAFDataDef_Edgecode"; if (aafUIDCmp (auid, &AAFDataDef_DescriptiveMetadata)) - return L"AAFDataDef_DescriptiveMetadata"; + return "AAFDataDef_DescriptiveMetadata"; if (aafUIDCmp (auid, &AAFDataDef_Auxiliary)) - return L"AAFDataDef_Auxiliary"; + return "AAFDataDef_Auxiliary"; if (aafUIDCmp (auid, &AAFDataDef_Unknown)) - return L"AAFDataDef_Unknown"; + return "AAFDataDef_Unknown"; - static wchar_t TEXTDataDef[1024]; + static char TEXTDataDef[1024]; aafObject* DataDefinitions = aaf_get_propertyValue (aafd->Dictionary, PID_Dictionary_DataDefinitions, &AAFTypeID_DataDefinitionStrongReferenceSet); aafObject* DataDefinition = NULL; - aaf_foreach_ObjectInSet (&DataDefinition, DataDefinitions, NULL) - { + while (_aaf_foreach_ObjectInSet (&DataDefinition, DataDefinitions, NULL)) { aafUID_t* DataDefIdent = aaf_get_propertyValue (DataDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); if (DataDefIdent && aafUIDCmp (DataDefIdent, auid)) { - wchar_t* name = aaf_get_propertyValue (DataDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); - swprintf (TEXTDataDef, 1024, L"%" WPRIws, name); + char* name = aaf_get_propertyValue (DataDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); + + if (!name) { + error ("Could not retrieve DataDefinition::Name"); + return NULL; + } + + int rc = snprintf (TEXTDataDef, sizeof (TEXTDataDef), "%s", name); + + assert (rc >= 0 && (size_t)rc < sizeof (TEXTDataDef)); + + // if ( rc < 0 || (size_t)rc >= 1024 ) { + // error( "snprintf() error" ); + // return NULL; + // } + free (name); return TEXTDataDef; } } - return L"Unknown AAFDataDef"; + return "Unknown AAFDataDef"; } -const wchar_t* +const char* aaft_OperationDefToText (AAF_Data* aafd, const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFOperationDef_VideoDissolve)) - return L"AAFOperationDef_VideoDissolve"; + return "AAFOperationDef_VideoDissolve"; if (aafUIDCmp (auid, &AAFOperationDef_SMPTEVideoWipe)) - return L"AAFOperationDef_SMPTEVideoWipe"; + return "AAFOperationDef_SMPTEVideoWipe"; if (aafUIDCmp (auid, &AAFOperationDef_VideoSpeedControl)) - return L"AAFOperationDef_VideoSpeedControl"; + return "AAFOperationDef_VideoSpeedControl"; if (aafUIDCmp (auid, &AAFOperationDef_VideoRepeat)) - return L"AAFOperationDef_VideoRepeat"; + return "AAFOperationDef_VideoRepeat"; if (aafUIDCmp (auid, &AAFOperationDef_Flip)) - return L"AAFOperationDef_Flip"; + return "AAFOperationDef_Flip"; if (aafUIDCmp (auid, &AAFOperationDef_Flop)) - return L"AAFOperationDef_Flop"; + return "AAFOperationDef_Flop"; if (aafUIDCmp (auid, &AAFOperationDef_FlipFlop)) - return L"AAFOperationDef_FlipFlop"; + return "AAFOperationDef_FlipFlop"; if (aafUIDCmp (auid, &AAFOperationDef_VideoPosition)) - return L"AAFOperationDef_VideoPosition"; + return "AAFOperationDef_VideoPosition"; if (aafUIDCmp (auid, &AAFOperationDef_VideoCrop)) - return L"AAFOperationDef_VideoCrop"; + return "AAFOperationDef_VideoCrop"; if (aafUIDCmp (auid, &AAFOperationDef_VideoScale)) - return L"AAFOperationDef_VideoScale"; + return "AAFOperationDef_VideoScale"; if (aafUIDCmp (auid, &AAFOperationDef_VideoRotate)) - return L"AAFOperationDef_VideoRotate"; + return "AAFOperationDef_VideoRotate"; if (aafUIDCmp (auid, &AAFOperationDef_VideoCornerPinning)) - return L"AAFOperationDef_VideoCornerPinning"; + return "AAFOperationDef_VideoCornerPinning"; if (aafUIDCmp (auid, &AAFOperationDef_VideoAlphaWithinVideoKey)) - return L"AAFOperationDef_VideoAlphaWithinVideoKey"; + return "AAFOperationDef_VideoAlphaWithinVideoKey"; if (aafUIDCmp (auid, &AAFOperationDef_VideoSeparateAlphaKey)) - return L"AAFOperationDef_VideoSeparateAlphaKey"; + return "AAFOperationDef_VideoSeparateAlphaKey"; if (aafUIDCmp (auid, &AAFOperationDef_VideoLuminanceKey)) - return L"AAFOperationDef_VideoLuminanceKey"; + return "AAFOperationDef_VideoLuminanceKey"; if (aafUIDCmp (auid, &AAFOperationDef_VideoChromaKey)) - return L"AAFOperationDef_VideoChromaKey"; + return "AAFOperationDef_VideoChromaKey"; if (aafUIDCmp (auid, &AAFOperationDef_MonoAudioGain)) - return L"AAFOperationDef_MonoAudioGain"; + return "AAFOperationDef_MonoAudioGain"; if (aafUIDCmp (auid, &AAFOperationDef_MonoAudioPan)) - return L"AAFOperationDef_MonoAudioPan"; + return "AAFOperationDef_MonoAudioPan"; if (aafUIDCmp (auid, &AAFOperationDef_MonoAudioDissolve)) - return L"AAFOperationDef_MonoAudioDissolve"; + return "AAFOperationDef_MonoAudioDissolve"; if (aafUIDCmp (auid, &AAFOperationDef_TwoParameterMonoAudioDissolve)) - return L"AAFOperationDef_TwoParameterMonoAudioDissolve"; + return "AAFOperationDef_TwoParameterMonoAudioDissolve"; if (aafUIDCmp (auid, &AAFOperationDef_VideoOpacity)) - return L"AAFOperationDef_VideoOpacity"; + return "AAFOperationDef_VideoOpacity"; if (aafUIDCmp (auid, &AAFOperationDef_VideoTitle)) - return L"AAFOperationDef_VideoTitle"; + return "AAFOperationDef_VideoTitle"; if (aafUIDCmp (auid, &AAFOperationDef_VideoColor)) - return L"AAFOperationDef_VideoColor"; + return "AAFOperationDef_VideoColor"; if (aafUIDCmp (auid, &AAFOperationDef_Unknown)) - return L"AAFOperationDef_Unknown"; + return "AAFOperationDef_Unknown"; if (aafUIDCmp (auid, &AAFOperationDef_VideoFadeToBlack)) - return L"AAFOperationDef_VideoFadeToBlack"; + return "AAFOperationDef_VideoFadeToBlack"; if (aafUIDCmp (auid, &AAFOperationDef_PictureWithMate)) - return L"AAFOperationDef_PictureWithMate"; + return "AAFOperationDef_PictureWithMate"; if (aafUIDCmp (auid, &AAFOperationDef_VideoFrameToMask)) - return L"AAFOperationDef_VideoFrameToMask"; + return "AAFOperationDef_VideoFrameToMask"; if (aafUIDCmp (auid, &AAFOperationDef_StereoAudioDissolve)) - return L"AAFOperationDef_StereoAudioDissolve"; + return "AAFOperationDef_StereoAudioDissolve"; if (aafUIDCmp (auid, &AAFOperationDef_StereoAudioGain)) - return L"AAFOperationDef_StereoAudioGain"; + return "AAFOperationDef_StereoAudioGain"; if (aafUIDCmp (auid, &AAFOperationDef_MonoAudioMixdown)) - return L"AAFOperationDef_MonoAudioMixdown"; + return "AAFOperationDef_MonoAudioMixdown"; if (aafUIDCmp (auid, &AAFOperationDef_AudioChannelCombiner)) - return L"AAFOperationDef_AudioChannelCombiner"; + return "AAFOperationDef_AudioChannelCombiner"; - static wchar_t TEXTOperationDef[1024]; + static char TEXTOperationDef[1024]; aafObject* OperationDefinitions = aaf_get_propertyValue (aafd->Dictionary, PID_Dictionary_OperationDefinitions, &AAFTypeID_OperationDefinitionStrongReferenceSet); aafObject* OperationDefinition = NULL; - aaf_foreach_ObjectInSet (&OperationDefinition, OperationDefinitions, NULL) - { + while (_aaf_foreach_ObjectInSet (&OperationDefinition, OperationDefinitions, NULL)) { aafUID_t* OpDefIdent = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); if (OpDefIdent && aafUIDCmp (OpDefIdent, auid)) { - wchar_t* name = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); - swprintf (TEXTOperationDef, 1024, L"%" WPRIws, name); + char* name = aaf_get_propertyValue (OperationDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); + + if (!name) { + error ("Could not retrieve OperationDefinition::Name"); + return NULL; + } + + int rc = snprintf (TEXTOperationDef, sizeof (TEXTOperationDef), "%s", name); + + assert (rc >= 0 && (size_t)rc < sizeof (TEXTOperationDef)); + + // if ( rc < 0 || (size_t)rc >= 1024 ) { + // fprintf( stderr, "snprintf() error" ); + // return NULL; + // } + free (name); return TEXTOperationDef; } } - return L"Unknown AAFOperationDef"; + return "Unknown AAFOperationDef"; } -const wchar_t* +const char* aaft_InterpolationToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFInterpolationDef_None)) - return L"AAFInterpolationDef_None"; + return "AAFInterpolationDef_None"; if (aafUIDCmp (auid, &AAFInterpolationDef_Linear)) - return L"AAFInterpolationDef_Linear"; + return "AAFInterpolationDef_Linear"; if (aafUIDCmp (auid, &AAFInterpolationDef_Constant)) - return L"AAFInterpolationDef_Constant"; + return "AAFInterpolationDef_Constant"; if (aafUIDCmp (auid, &AAFInterpolationDef_BSpline)) - return L"AAFInterpolationDef_BSpline"; + return "AAFInterpolationDef_BSpline"; if (aafUIDCmp (auid, &AAFInterpolationDef_Log)) - return L"AAFInterpolationDef_Log"; + return "AAFInterpolationDef_Log"; if (aafUIDCmp (auid, &AAFInterpolationDef_Power)) - return L"AAFInterpolationDef_Power"; + return "AAFInterpolationDef_Power"; - return L"Unknown AAFInterpolationDef"; + return "Unknown AAFInterpolationDef"; } -const wchar_t* +const char* aaft_ParameterToText (AAF_Data* aafd, const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFParameterDef_Level)) - return L"AAFParameterDef_Level"; + return "AAFParameterDef_Level"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEWipeNumber)) - return L"AAFParameterDef_SMPTEWipeNumber"; + return "AAFParameterDef_SMPTEWipeNumber"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEReverse)) - return L"AAFParameterDef_SMPTEReverse"; + return "AAFParameterDef_SMPTEReverse"; if (aafUIDCmp (auid, &AAFParameterDef_SpeedRatio)) - return L"AAFParameterDef_SpeedRatio"; + return "AAFParameterDef_SpeedRatio"; if (aafUIDCmp (auid, &AAFParameterDef_PositionOffsetX)) - return L"AAFParameterDef_PositionOffsetX"; + return "AAFParameterDef_PositionOffsetX"; if (aafUIDCmp (auid, &AAFParameterDef_PositionOffsetY)) - return L"AAFParameterDef_PositionOffsetY"; + return "AAFParameterDef_PositionOffsetY"; if (aafUIDCmp (auid, &AAFParameterDef_CropLeft)) - return L"AAFParameterDef_CropLeft"; + return "AAFParameterDef_CropLeft"; if (aafUIDCmp (auid, &AAFParameterDef_CropRight)) - return L"AAFParameterDef_CropRight"; + return "AAFParameterDef_CropRight"; if (aafUIDCmp (auid, &AAFParameterDef_CropTop)) - return L"AAFParameterDef_CropTop"; + return "AAFParameterDef_CropTop"; if (aafUIDCmp (auid, &AAFParameterDef_CropBottom)) - return L"AAFParameterDef_CropBottom"; + return "AAFParameterDef_CropBottom"; if (aafUIDCmp (auid, &AAFParameterDef_ScaleX)) - return L"AAFParameterDef_ScaleX"; + return "AAFParameterDef_ScaleX"; if (aafUIDCmp (auid, &AAFParameterDef_ScaleY)) - return L"AAFParameterDef_ScaleY"; + return "AAFParameterDef_ScaleY"; if (aafUIDCmp (auid, &AAFParameterDef_Rotation)) - return L"AAFParameterDef_Rotation"; + return "AAFParameterDef_Rotation"; if (aafUIDCmp (auid, &AAFParameterDef_PinTopLeftX)) - return L"AAFParameterDef_PinTopLeftX"; + return "AAFParameterDef_PinTopLeftX"; if (aafUIDCmp (auid, &AAFParameterDef_PinTopLeftY)) - return L"AAFParameterDef_PinTopLeftY"; + return "AAFParameterDef_PinTopLeftY"; if (aafUIDCmp (auid, &AAFParameterDef_PinTopRightX)) - return L"AAFParameterDef_PinTopRightX"; + return "AAFParameterDef_PinTopRightX"; if (aafUIDCmp (auid, &AAFParameterDef_PinTopRightY)) - return L"AAFParameterDef_PinTopRightY"; + return "AAFParameterDef_PinTopRightY"; if (aafUIDCmp (auid, &AAFParameterDef_PinBottomLeftX)) - return L"AAFParameterDef_PinBottomLeftX"; + return "AAFParameterDef_PinBottomLeftX"; if (aafUIDCmp (auid, &AAFParameterDef_PinBottomLeftY)) - return L"AAFParameterDef_PinBottomLeftY"; + return "AAFParameterDef_PinBottomLeftY"; if (aafUIDCmp (auid, &AAFParameterDef_PinBottomRightX)) - return L"AAFParameterDef_PinBottomRightX"; + return "AAFParameterDef_PinBottomRightX"; if (aafUIDCmp (auid, &AAFParameterDef_PinBottomRightY)) - return L"AAFParameterDef_PinBottomRightY"; + return "AAFParameterDef_PinBottomRightY"; if (aafUIDCmp (auid, &AAFParameterDef_AlphaKeyInvertAlpha)) - return L"AAFParameterDef_AlphaKeyInvertAlpha"; + return "AAFParameterDef_AlphaKeyInvertAlpha"; if (aafUIDCmp (auid, &AAFParameterDef_LumKeyLevel)) - return L"AAFParameterDef_LumKeyLevel"; + return "AAFParameterDef_LumKeyLevel"; if (aafUIDCmp (auid, &AAFParameterDef_LumKeyClip)) - return L"AAFParameterDef_LumKeyClip"; + return "AAFParameterDef_LumKeyClip"; if (aafUIDCmp (auid, &AAFParameterDef_Amplitude)) - return L"AAFParameterDef_Amplitude"; + return "AAFParameterDef_Amplitude"; if (aafUIDCmp (auid, &AAFParameterDef_Pan)) - return L"AAFParameterDef_Pan"; + return "AAFParameterDef_Pan"; if (aafUIDCmp (auid, &AAFParameterDef_OutgoingLevel)) - return L"AAFParameterDef_OutgoingLevel"; + return "AAFParameterDef_OutgoingLevel"; if (aafUIDCmp (auid, &AAFParameterDef_IncomingLevel)) - return L"AAFParameterDef_IncomingLevel"; + return "AAFParameterDef_IncomingLevel"; if (aafUIDCmp (auid, &AAFParameterDef_OpacityLevel)) - return L"AAFParameterDef_OpacityLevel"; + return "AAFParameterDef_OpacityLevel"; if (aafUIDCmp (auid, &AAFParameterDef_TitleText)) - return L"AAFParameterDef_TitleText"; + return "AAFParameterDef_TitleText"; if (aafUIDCmp (auid, &AAFParameterDef_TitleFontName)) - return L"AAFParameterDef_TitleFontName"; + return "AAFParameterDef_TitleFontName"; if (aafUIDCmp (auid, &AAFParameterDef_TitleFontSize)) - return L"AAFParameterDef_TitleFontSize"; + return "AAFParameterDef_TitleFontSize"; if (aafUIDCmp (auid, &AAFParameterDef_TitleFontColorR)) - return L"AAFParameterDef_TitleFontColorR"; + return "AAFParameterDef_TitleFontColorR"; if (aafUIDCmp (auid, &AAFParameterDef_TitleFontColorG)) - return L"AAFParameterDef_TitleFontColorG"; + return "AAFParameterDef_TitleFontColorG"; if (aafUIDCmp (auid, &AAFParameterDef_TitleFontColorB)) - return L"AAFParameterDef_TitleFontColorB"; + return "AAFParameterDef_TitleFontColorB"; if (aafUIDCmp (auid, &AAFParameterDef_TitleAlignment)) - return L"AAFParameterDef_TitleAlignment"; + return "AAFParameterDef_TitleAlignment"; if (aafUIDCmp (auid, &AAFParameterDef_TitleBold)) - return L"AAFParameterDef_TitleBold"; + return "AAFParameterDef_TitleBold"; if (aafUIDCmp (auid, &AAFParameterDef_TitleItalic)) - return L"AAFParameterDef_TitleItalic"; + return "AAFParameterDef_TitleItalic"; if (aafUIDCmp (auid, &AAFParameterDef_TitlePositionX)) - return L"AAFParameterDef_TitlePositionX"; + return "AAFParameterDef_TitlePositionX"; if (aafUIDCmp (auid, &AAFParameterDef_TitlePositionY)) - return L"AAFParameterDef_TitlePositionY"; + return "AAFParameterDef_TitlePositionY"; if (aafUIDCmp (auid, &AAFParameterDef_ColorSlopeR)) - return L"AAFParameterDef_ColorSlopeR"; + return "AAFParameterDef_ColorSlopeR"; if (aafUIDCmp (auid, &AAFParameterDef_ColorSlopeG)) - return L"AAFParameterDef_ColorSlopeG"; + return "AAFParameterDef_ColorSlopeG"; if (aafUIDCmp (auid, &AAFParameterDef_ColorSlopeB)) - return L"AAFParameterDef_ColorSlopeB"; + return "AAFParameterDef_ColorSlopeB"; if (aafUIDCmp (auid, &AAFParameterDef_ColorOffsetR)) - return L"AAFParameterDef_ColorOffsetR"; + return "AAFParameterDef_ColorOffsetR"; if (aafUIDCmp (auid, &AAFParameterDef_ColorOffsetG)) - return L"AAFParameterDef_ColorOffsetG"; + return "AAFParameterDef_ColorOffsetG"; if (aafUIDCmp (auid, &AAFParameterDef_ColorOffsetB)) - return L"AAFParameterDef_ColorOffsetB"; + return "AAFParameterDef_ColorOffsetB"; if (aafUIDCmp (auid, &AAFParameterDef_ColorPowerR)) - return L"AAFParameterDef_ColorPowerR"; + return "AAFParameterDef_ColorPowerR"; if (aafUIDCmp (auid, &AAFParameterDef_ColorPowerG)) - return L"AAFParameterDef_ColorPowerG"; + return "AAFParameterDef_ColorPowerG"; if (aafUIDCmp (auid, &AAFParameterDef_ColorPowerB)) - return L"AAFParameterDef_ColorPowerB"; + return "AAFParameterDef_ColorPowerB"; if (aafUIDCmp (auid, &AAFParameterDef_ColorSaturation)) - return L"AAFParameterDef_ColorSaturation"; + return "AAFParameterDef_ColorSaturation"; if (aafUIDCmp (auid, &AAFParameterDef_ColorCorrectionDescription)) - return L"AAFParameterDef_ColorCorrectionDescription"; + return "AAFParameterDef_ColorCorrectionDescription"; if (aafUIDCmp (auid, &AAFParameterDef_ColorInputDescription)) - return L"AAFParameterDef_ColorInputDescription"; + return "AAFParameterDef_ColorInputDescription"; if (aafUIDCmp (auid, &AAFParameterDef_ColorViewingDescription)) - return L"AAFParameterDef_ColorViewingDescription"; + return "AAFParameterDef_ColorViewingDescription"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTESoft)) - return L"AAFParameterDef_SMPTESoft"; + return "AAFParameterDef_SMPTESoft"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEBorder)) - return L"AAFParameterDef_SMPTEBorder"; + return "AAFParameterDef_SMPTEBorder"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEPosition)) - return L"AAFParameterDef_SMPTEPosition"; + return "AAFParameterDef_SMPTEPosition"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEModulator)) - return L"AAFParameterDef_SMPTEModulator"; + return "AAFParameterDef_SMPTEModulator"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEShadow)) - return L"AAFParameterDef_SMPTEShadow"; + return "AAFParameterDef_SMPTEShadow"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTETumble)) - return L"AAFParameterDef_SMPTETumble"; + return "AAFParameterDef_SMPTETumble"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTESpotlight)) - return L"AAFParameterDef_SMPTESpotlight"; + return "AAFParameterDef_SMPTESpotlight"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEReplicationH)) - return L"AAFParameterDef_SMPTEReplicationH"; + return "AAFParameterDef_SMPTEReplicationH"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTEReplicationV)) - return L"AAFParameterDef_SMPTEReplicationV"; + return "AAFParameterDef_SMPTEReplicationV"; if (aafUIDCmp (auid, &AAFParameterDef_SMPTECheckerboard)) - return L"AAFParameterDef_SMPTECheckerboard"; + return "AAFParameterDef_SMPTECheckerboard"; if (aafUIDCmp (auid, &AAFParameterDef_PhaseOffset)) - return L"AAFParameterDef_PhaseOffset"; + return "AAFParameterDef_PhaseOffset"; /* NOTE: Seen in Avid MC and PT files : PanVol_IsTrimGainEffect */ - static wchar_t TEXTParameterDef[1024]; + static char TEXTParameterDef[1024]; aafObject* ParameterDefinitions = aaf_get_propertyValue (aafd->Dictionary, PID_Dictionary_ParameterDefinitions, &AAFTypeID_ParameterDefinitionStrongReferenceSet); aafObject* ParameterDefinition = NULL; - aaf_foreach_ObjectInSet (&ParameterDefinition, ParameterDefinitions, NULL) - { + while (_aaf_foreach_ObjectInSet (&ParameterDefinition, ParameterDefinitions, NULL)) { aafUID_t* ParamDefIdent = aaf_get_propertyValue (ParameterDefinition, PID_DefinitionObject_Identification, &AAFTypeID_AUID); if (ParamDefIdent && aafUIDCmp (ParamDefIdent, auid)) { - wchar_t* name = aaf_get_propertyValue (ParameterDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); - swprintf (TEXTParameterDef, 1024, L"%" WPRIws, name); + char* name = aaf_get_propertyValue (ParameterDefinition, PID_DefinitionObject_Name, &AAFTypeID_String); + + if (!name) { + error ("Could not retrieve ParameterDefinition::Name"); + return NULL; + } + + int rc = snprintf (TEXTParameterDef, sizeof (TEXTParameterDef), "%s", name); + + assert (rc >= 0 && (size_t)rc < sizeof (TEXTParameterDef)); + + // if ( rc < 0 || (size_t)rc >= 1024 ) { + // fprintf( stderr, "snprintf() error" ); + // return NULL; + // } + free (name); return TEXTParameterDef; } } - return L"Unknown AAFParameterDef"; + return "Unknown AAFParameterDef"; } -const wchar_t* +const char* aaft_TransferCharacteristicToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFTransferCharacteristic_ITU470_PAL)) - return L"AAFTransferCharacteristic_ITU470_PAL"; + return "AAFTransferCharacteristic_ITU470_PAL"; if (aafUIDCmp (auid, &AAFTransferCharacteristic_ITU709)) - return L"AAFTransferCharacteristic_ITU709"; + return "AAFTransferCharacteristic_ITU709"; if (aafUIDCmp (auid, &AAFTransferCharacteristic_SMPTE240M)) - return L"AAFTransferCharacteristic_SMPTE240M"; + return "AAFTransferCharacteristic_SMPTE240M"; if (aafUIDCmp (auid, &AAFTransferCharacteristic_274M_296M)) - return L"AAFTransferCharacteristic_274M_296M"; + return "AAFTransferCharacteristic_274M_296M"; if (aafUIDCmp (auid, &AAFTransferCharacteristic_ITU1361)) - return L"AAFTransferCharacteristic_ITU1361"; + return "AAFTransferCharacteristic_ITU1361"; if (aafUIDCmp (auid, &AAFTransferCharacteristic_linear)) - return L"AAFTransferCharacteristic_linear"; + return "AAFTransferCharacteristic_linear"; - return L"Unknown AAFTransferCharacteristic"; + return "Unknown AAFTransferCharacteristic"; } -const wchar_t* +const char* aaft_CodingEquationsToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFCodingEquations_ITU601)) - return L"AAFCodingEquations_ITU601"; + return "AAFCodingEquations_ITU601"; if (aafUIDCmp (auid, &AAFCodingEquations_ITU709)) - return L"AAFCodingEquations_ITU709"; + return "AAFCodingEquations_ITU709"; if (aafUIDCmp (auid, &AAFCodingEquations_SMPTE240M)) - return L"AAFCodingEquations_SMPTE240M"; + return "AAFCodingEquations_SMPTE240M"; - return L"Unknown AAFCodingEquations"; + return "Unknown AAFCodingEquations"; } -const wchar_t* +const char* aaft_ColorPrimariesToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFColorPrimaries_SMPTE170M)) - return L"AAFColorPrimaries_SMPTE170M"; + return "AAFColorPrimaries_SMPTE170M"; if (aafUIDCmp (auid, &AAFColorPrimaries_ITU470_PAL)) - return L"AAFColorPrimaries_ITU470_PAL"; + return "AAFColorPrimaries_ITU470_PAL"; if (aafUIDCmp (auid, &AAFColorPrimaries_ITU709)) - return L"AAFColorPrimaries_ITU709"; + return "AAFColorPrimaries_ITU709"; - return L"Unknown AAFColorPrimaries"; + return "Unknown AAFColorPrimaries"; } -const wchar_t* +const char* aaft_UsageCodeToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AAFUID_NULL)) - return L"AAFUID_NULL"; + return "AAFUID_NULL"; if (aafUIDCmp (auid, &AAFUsage_SubClip)) - return L"AAFUsage_SubClip"; + return "AAFUsage_SubClip"; if (aafUIDCmp (auid, &AAFUsage_AdjustedClip)) - return L"AAFUsage_AdjustedClip"; + return "AAFUsage_AdjustedClip"; if (aafUIDCmp (auid, &AAFUsage_TopLevel)) - return L"AAFUsage_TopLevel"; + return "AAFUsage_TopLevel"; if (aafUIDCmp (auid, &AAFUsage_LowerLevel)) - return L"AAFUsage_LowerLevel"; + return "AAFUsage_LowerLevel"; if (aafUIDCmp (auid, &AAFUsage_Template)) - return L"AAFUsage_Template"; + return "AAFUsage_Template"; - return L"Unknown AAFUsage"; + return "Unknown AAFUsage"; } -const wchar_t* +const char* aaft_PIDToText (AAF_Data* aafd, aafPID_t pid) { switch (pid) { case PID_Root_MetaDictionary: - return L"PID_Root_MetaDictionary"; + return "PID_Root_MetaDictionary"; case PID_Root_Header: - return L"PID_Root_Header"; + return "PID_Root_Header"; case PID_InterchangeObject_ObjClass: - return L"PID_InterchangeObject_ObjClass"; + return "PID_InterchangeObject_ObjClass"; case PID_InterchangeObject_Generation: - return L"PID_InterchangeObject_Generation"; + return "PID_InterchangeObject_Generation"; case PID_Component_DataDefinition: - return L"PID_Component_DataDefinition"; + return "PID_Component_DataDefinition"; case PID_Component_Length: - return L"PID_Component_Length"; + return "PID_Component_Length"; case PID_Component_KLVData: - return L"PID_Component_KLVData"; + return "PID_Component_KLVData"; case PID_Component_UserComments: - return L"PID_Component_UserComments"; + return "PID_Component_UserComments"; case PID_Component_Attributes: - return L"PID_Component_Attributes"; + return "PID_Component_Attributes"; case PID_EdgeCode_Start: - return L"PID_EdgeCode_Start"; + return "PID_EdgeCode_Start"; case PID_EdgeCode_FilmKind: - return L"PID_EdgeCode_FilmKind"; + return "PID_EdgeCode_FilmKind"; case PID_EdgeCode_CodeFormat: - return L"PID_EdgeCode_CodeFormat"; + return "PID_EdgeCode_CodeFormat"; case PID_EdgeCode_Header: - return L"PID_EdgeCode_Header"; + return "PID_EdgeCode_Header"; case PID_EssenceGroup_Choices: - return L"PID_EssenceGroup_Choices"; + return "PID_EssenceGroup_Choices"; case PID_EssenceGroup_StillFrame: - return L"PID_EssenceGroup_StillFrame"; + return "PID_EssenceGroup_StillFrame"; case PID_Event_Position: - return L"PID_Event_Position"; + return "PID_Event_Position"; case PID_Event_Comment: - return L"PID_Event_Comment"; + return "PID_Event_Comment"; case PID_GPITrigger_ActiveState: - return L"PID_GPITrigger_ActiveState"; + return "PID_GPITrigger_ActiveState"; case PID_CommentMarker_Annotation: - return L"PID_CommentMarker_Annotation"; + return "PID_CommentMarker_Annotation"; case PID_OperationGroup_Operation: - return L"PID_OperationGroup_Operation"; + return "PID_OperationGroup_Operation"; case PID_OperationGroup_InputSegments: - return L"PID_OperationGroup_InputSegments"; + return "PID_OperationGroup_InputSegments"; case PID_OperationGroup_Parameters: - return L"PID_OperationGroup_Parameters"; + return "PID_OperationGroup_Parameters"; case PID_OperationGroup_BypassOverride: - return L"PID_OperationGroup_BypassOverride"; + return "PID_OperationGroup_BypassOverride"; case PID_OperationGroup_Rendering: - return L"PID_OperationGroup_Rendering"; + return "PID_OperationGroup_Rendering"; case PID_NestedScope_Slots: - return L"PID_NestedScope_Slots"; + return "PID_NestedScope_Slots"; case PID_Pulldown_InputSegment: - return L"PID_Pulldown_InputSegment"; + return "PID_Pulldown_InputSegment"; case PID_Pulldown_PulldownKind: - return L"PID_Pulldown_PulldownKind"; + return "PID_Pulldown_PulldownKind"; case PID_Pulldown_PulldownDirection: - return L"PID_Pulldown_PulldownDirection"; + return "PID_Pulldown_PulldownDirection"; case PID_Pulldown_PhaseFrame: - return L"PID_Pulldown_PhaseFrame"; + return "PID_Pulldown_PhaseFrame"; case PID_ScopeReference_RelativeScope: - return L"PID_ScopeReference_RelativeScope"; + return "PID_ScopeReference_RelativeScope"; case PID_ScopeReference_RelativeSlot: - return L"PID_ScopeReference_RelativeSlot"; + return "PID_ScopeReference_RelativeSlot"; case PID_Selector_Selected: - return L"PID_Selector_Selected"; + return "PID_Selector_Selected"; case PID_Selector_Alternates: - return L"PID_Selector_Alternates"; + return "PID_Selector_Alternates"; case PID_Sequence_Components: - return L"PID_Sequence_Components"; + return "PID_Sequence_Components"; case PID_SourceReference_SourceID: - return L"PID_SourceReference_SourceID"; + return "PID_SourceReference_SourceID"; case PID_SourceReference_SourceMobSlotID: - return L"PID_SourceReference_SourceMobSlotID"; + return "PID_SourceReference_SourceMobSlotID"; case PID_SourceReference_ChannelIDs: - return L"PID_SourceReference_ChannelIDs"; + return "PID_SourceReference_ChannelIDs"; case PID_SourceReference_MonoSourceSlotIDs: - return L"PID_SourceReference_MonoSourceSlotIDs"; + return "PID_SourceReference_MonoSourceSlotIDs"; case PID_SourceClip_StartTime: - return L"PID_SourceClip_StartTime"; + return "PID_SourceClip_StartTime"; case PID_SourceClip_FadeInLength: - return L"PID_SourceClip_FadeInLength"; + return "PID_SourceClip_FadeInLength"; case PID_SourceClip_FadeInType: - return L"PID_SourceClip_FadeInType"; + return "PID_SourceClip_FadeInType"; case PID_SourceClip_FadeOutLength: - return L"PID_SourceClip_FadeOutLength"; + return "PID_SourceClip_FadeOutLength"; case PID_SourceClip_FadeOutType: - return L"PID_SourceClip_FadeOutType"; + return "PID_SourceClip_FadeOutType"; case PID_HTMLClip_BeginAnchor: - return L"PID_HTMLClip_BeginAnchor"; + return "PID_HTMLClip_BeginAnchor"; case PID_HTMLClip_EndAnchor: - return L"PID_HTMLClip_EndAnchor"; + return "PID_HTMLClip_EndAnchor"; case PID_Timecode_Start: - return L"PID_Timecode_Start"; + return "PID_Timecode_Start"; case PID_Timecode_FPS: - return L"PID_Timecode_FPS"; + return "PID_Timecode_FPS"; case PID_Timecode_Drop: - return L"PID_Timecode_Drop"; + return "PID_Timecode_Drop"; case PID_TimecodeStream_SampleRate: - return L"PID_TimecodeStream_SampleRate"; + return "PID_TimecodeStream_SampleRate"; case PID_TimecodeStream_Source: - return L"PID_TimecodeStream_Source"; + return "PID_TimecodeStream_Source"; case PID_TimecodeStream_SourceType: - return L"PID_TimecodeStream_SourceType"; + return "PID_TimecodeStream_SourceType"; case PID_TimecodeStream12M_IncludeSync: - return L"PID_TimecodeStream12M_IncludeSync"; + return "PID_TimecodeStream12M_IncludeSync"; case PID_Transition_OperationGroup: - return L"PID_Transition_OperationGroup"; + return "PID_Transition_OperationGroup"; case PID_Transition_CutPoint: - return L"PID_Transition_CutPoint"; + return "PID_Transition_CutPoint"; case PID_ContentStorage_Mobs: - return L"PID_ContentStorage_Mobs"; + return "PID_ContentStorage_Mobs"; case PID_ContentStorage_EssenceData: - return L"PID_ContentStorage_EssenceData"; + return "PID_ContentStorage_EssenceData"; case PID_ControlPoint_Value: - return L"PID_ControlPoint_Value"; + return "PID_ControlPoint_Value"; case PID_ControlPoint_Time: - return L"PID_ControlPoint_Time"; + return "PID_ControlPoint_Time"; case PID_ControlPoint_EditHint: - return L"PID_ControlPoint_EditHint"; + return "PID_ControlPoint_EditHint"; case PID_DefinitionObject_Identification: - return L"PID_DefinitionObject_Identification"; + return "PID_DefinitionObject_Identification"; case PID_DefinitionObject_Name: - return L"PID_DefinitionObject_Name"; + return "PID_DefinitionObject_Name"; case PID_DefinitionObject_Description: - return L"PID_DefinitionObject_Description"; + return "PID_DefinitionObject_Description"; case PID_OperationDefinition_DataDefinition: - return L"PID_OperationDefinition_DataDefinition"; + return "PID_OperationDefinition_DataDefinition"; case PID_OperationDefinition_IsTimeWarp: - return L"PID_OperationDefinition_IsTimeWarp"; + return "PID_OperationDefinition_IsTimeWarp"; case PID_OperationDefinition_DegradeTo: - return L"PID_OperationDefinition_DegradeTo"; + return "PID_OperationDefinition_DegradeTo"; case PID_OperationDefinition_OperationCategory: - return L"PID_OperationDefinition_OperationCategory"; + return "PID_OperationDefinition_OperationCategory"; case PID_OperationDefinition_NumberInputs: - return L"PID_OperationDefinition_NumberInputs"; + return "PID_OperationDefinition_NumberInputs"; case PID_OperationDefinition_Bypass: - return L"PID_OperationDefinition_Bypass"; + return "PID_OperationDefinition_Bypass"; case PID_OperationDefinition_ParametersDefined: - return L"PID_OperationDefinition_ParametersDefined"; + return "PID_OperationDefinition_ParametersDefined"; case PID_ParameterDefinition_Type: - return L"PID_ParameterDefinition_Type"; + return "PID_ParameterDefinition_Type"; case PID_ParameterDefinition_DisplayUnits: - return L"PID_ParameterDefinition_DisplayUnits"; + return "PID_ParameterDefinition_DisplayUnits"; case PID_PluginDefinition_PluginCategory: - return L"PID_PluginDefinition_PluginCategory"; + return "PID_PluginDefinition_PluginCategory"; case PID_PluginDefinition_VersionNumber: - return L"PID_PluginDefinition_VersionNumber"; + return "PID_PluginDefinition_VersionNumber"; case PID_PluginDefinition_VersionString: - return L"PID_PluginDefinition_VersionString"; + return "PID_PluginDefinition_VersionString"; case PID_PluginDefinition_Manufacturer: - return L"PID_PluginDefinition_Manufacturer"; + return "PID_PluginDefinition_Manufacturer"; case PID_PluginDefinition_ManufacturerInfo: - return L"PID_PluginDefinition_ManufacturerInfo"; + return "PID_PluginDefinition_ManufacturerInfo"; case PID_PluginDefinition_ManufacturerID: - return L"PID_PluginDefinition_ManufacturerID"; + return "PID_PluginDefinition_ManufacturerID"; case PID_PluginDefinition_Platform: - return L"PID_PluginDefinition_Platform"; + return "PID_PluginDefinition_Platform"; case PID_PluginDefinition_MinPlatformVersion: - return L"PID_PluginDefinition_MinPlatformVersion"; + return "PID_PluginDefinition_MinPlatformVersion"; case PID_PluginDefinition_MaxPlatformVersion: - return L"PID_PluginDefinition_MaxPlatformVersion"; + return "PID_PluginDefinition_MaxPlatformVersion"; case PID_PluginDefinition_Engine: - return L"PID_PluginDefinition_Engine"; + return "PID_PluginDefinition_Engine"; case PID_PluginDefinition_MinEngineVersion: - return L"PID_PluginDefinition_MinEngineVersion"; + return "PID_PluginDefinition_MinEngineVersion"; case PID_PluginDefinition_MaxEngineVersion: - return L"PID_PluginDefinition_MaxEngineVersion"; + return "PID_PluginDefinition_MaxEngineVersion"; case PID_PluginDefinition_PluginAPI: - return L"PID_PluginDefinition_PluginAPI"; + return "PID_PluginDefinition_PluginAPI"; case PID_PluginDefinition_MinPluginAPI: - return L"PID_PluginDefinition_MinPluginAPI"; + return "PID_PluginDefinition_MinPluginAPI"; case PID_PluginDefinition_MaxPluginAPI: - return L"PID_PluginDefinition_MaxPluginAPI"; + return "PID_PluginDefinition_MaxPluginAPI"; case PID_PluginDefinition_SoftwareOnly: - return L"PID_PluginDefinition_SoftwareOnly"; + return "PID_PluginDefinition_SoftwareOnly"; case PID_PluginDefinition_Accelerator: - return L"PID_PluginDefinition_Accelerator"; + return "PID_PluginDefinition_Accelerator"; case PID_PluginDefinition_Locators: - return L"PID_PluginDefinition_Locators"; + return "PID_PluginDefinition_Locators"; case PID_PluginDefinition_Authentication: - return L"PID_PluginDefinition_Authentication"; + return "PID_PluginDefinition_Authentication"; case PID_PluginDefinition_DefinitionObject: - return L"PID_PluginDefinition_DefinitionObject"; + return "PID_PluginDefinition_DefinitionObject"; case PID_CodecDefinition_FileDescriptorClass: - return L"PID_CodecDefinition_FileDescriptorClass"; + return "PID_CodecDefinition_FileDescriptorClass"; case PID_CodecDefinition_DataDefinitions: - return L"PID_CodecDefinition_DataDefinitions"; + return "PID_CodecDefinition_DataDefinitions"; case PID_ContainerDefinition_EssenceIsIdentified: - return L"PID_ContainerDefinition_EssenceIsIdentified"; + return "PID_ContainerDefinition_EssenceIsIdentified"; case PID_Dictionary_OperationDefinitions: - return L"PID_Dictionary_OperationDefinitions"; + return "PID_Dictionary_OperationDefinitions"; case PID_Dictionary_ParameterDefinitions: - return L"PID_Dictionary_ParameterDefinitions"; + return "PID_Dictionary_ParameterDefinitions"; case PID_Dictionary_DataDefinitions: - return L"PID_Dictionary_DataDefinitions"; + return "PID_Dictionary_DataDefinitions"; case PID_Dictionary_PluginDefinitions: - return L"PID_Dictionary_PluginDefinitions"; + return "PID_Dictionary_PluginDefinitions"; case PID_Dictionary_CodecDefinitions: - return L"PID_Dictionary_CodecDefinitions"; + return "PID_Dictionary_CodecDefinitions"; case PID_Dictionary_ContainerDefinitions: - return L"PID_Dictionary_ContainerDefinitions"; + return "PID_Dictionary_ContainerDefinitions"; case PID_Dictionary_InterpolationDefinitions: - return L"PID_Dictionary_InterpolationDefinitions"; + return "PID_Dictionary_InterpolationDefinitions"; case PID_Dictionary_KLVDataDefinitions: - return L"PID_Dictionary_KLVDataDefinitions"; + return "PID_Dictionary_KLVDataDefinitions"; case PID_Dictionary_TaggedValueDefinitions: - return L"PID_Dictionary_TaggedValueDefinitions"; + return "PID_Dictionary_TaggedValueDefinitions"; case PID_EssenceData_MobID: - return L"PID_EssenceData_MobID"; + return "PID_EssenceData_MobID"; case PID_EssenceData_Data: - return L"PID_EssenceData_Data"; + return "PID_EssenceData_Data"; case PID_EssenceData_SampleIndex: - return L"PID_EssenceData_SampleIndex"; + return "PID_EssenceData_SampleIndex"; case PID_EssenceDescriptor_Locator: - return L"PID_EssenceDescriptor_Locator"; + return "PID_EssenceDescriptor_Locator"; case PID_FileDescriptor_SampleRate: - return L"PID_FileDescriptor_SampleRate"; + return "PID_FileDescriptor_SampleRate"; case PID_FileDescriptor_Length: - return L"PID_FileDescriptor_Length"; + return "PID_FileDescriptor_Length"; case PID_FileDescriptor_ContainerFormat: - return L"PID_FileDescriptor_ContainerFormat"; + return "PID_FileDescriptor_ContainerFormat"; case PID_FileDescriptor_CodecDefinition: - return L"PID_FileDescriptor_CodecDefinition"; + return "PID_FileDescriptor_CodecDefinition"; case PID_FileDescriptor_LinkedSlotID: - return L"PID_FileDescriptor_LinkedSlotID"; + return "PID_FileDescriptor_LinkedSlotID"; case PID_AIFCDescriptor_Summary: - return L"PID_AIFCDescriptor_Summary"; + return "PID_AIFCDescriptor_Summary"; case PID_DigitalImageDescriptor_Compression: - return L"PID_DigitalImageDescriptor_Compression"; + return "PID_DigitalImageDescriptor_Compression"; case PID_DigitalImageDescriptor_StoredHeight: - return L"PID_DigitalImageDescriptor_StoredHeight"; + return "PID_DigitalImageDescriptor_StoredHeight"; case PID_DigitalImageDescriptor_StoredWidth: - return L"PID_DigitalImageDescriptor_StoredWidth"; + return "PID_DigitalImageDescriptor_StoredWidth"; case PID_DigitalImageDescriptor_SampledHeight: - return L"PID_DigitalImageDescriptor_SampledHeight"; + return "PID_DigitalImageDescriptor_SampledHeight"; case PID_DigitalImageDescriptor_SampledWidth: - return L"PID_DigitalImageDescriptor_SampledWidth"; + return "PID_DigitalImageDescriptor_SampledWidth"; case PID_DigitalImageDescriptor_SampledXOffset: - return L"PID_DigitalImageDescriptor_SampledXOffset"; + return "PID_DigitalImageDescriptor_SampledXOffset"; case PID_DigitalImageDescriptor_SampledYOffset: - return L"PID_DigitalImageDescriptor_SampledYOffset"; + return "PID_DigitalImageDescriptor_SampledYOffset"; case PID_DigitalImageDescriptor_DisplayHeight: - return L"PID_DigitalImageDescriptor_DisplayHeight"; + return "PID_DigitalImageDescriptor_DisplayHeight"; case PID_DigitalImageDescriptor_DisplayWidth: - return L"PID_DigitalImageDescriptor_DisplayWidth"; + return "PID_DigitalImageDescriptor_DisplayWidth"; case PID_DigitalImageDescriptor_DisplayXOffset: - return L"PID_DigitalImageDescriptor_DisplayXOffset"; + return "PID_DigitalImageDescriptor_DisplayXOffset"; case PID_DigitalImageDescriptor_DisplayYOffset: - return L"PID_DigitalImageDescriptor_DisplayYOffset"; + return "PID_DigitalImageDescriptor_DisplayYOffset"; case PID_DigitalImageDescriptor_FrameLayout: - return L"PID_DigitalImageDescriptor_FrameLayout"; + return "PID_DigitalImageDescriptor_FrameLayout"; case PID_DigitalImageDescriptor_VideoLineMap: - return L"PID_DigitalImageDescriptor_VideoLineMap"; + return "PID_DigitalImageDescriptor_VideoLineMap"; case PID_DigitalImageDescriptor_ImageAspectRatio: - return L"PID_DigitalImageDescriptor_ImageAspectRatio"; + return "PID_DigitalImageDescriptor_ImageAspectRatio"; case PID_DigitalImageDescriptor_AlphaTransparency: - return L"PID_DigitalImageDescriptor_AlphaTransparency"; + return "PID_DigitalImageDescriptor_AlphaTransparency"; case PID_DigitalImageDescriptor_TransferCharacteristic: - return L"PID_DigitalImageDescriptor_TransferCharacteristic"; + return "PID_DigitalImageDescriptor_TransferCharacteristic"; case PID_DigitalImageDescriptor_ColorPrimaries: - return L"PID_DigitalImageDescriptor_ColorPrimaries"; + return "PID_DigitalImageDescriptor_ColorPrimaries"; case PID_DigitalImageDescriptor_CodingEquations: - return L"PID_DigitalImageDescriptor_CodingEquations"; + return "PID_DigitalImageDescriptor_CodingEquations"; case PID_DigitalImageDescriptor_ImageAlignmentFactor: - return L"PID_DigitalImageDescriptor_ImageAlignmentFactor"; + return "PID_DigitalImageDescriptor_ImageAlignmentFactor"; case PID_DigitalImageDescriptor_FieldDominance: - return L"PID_DigitalImageDescriptor_FieldDominance"; + return "PID_DigitalImageDescriptor_FieldDominance"; case PID_DigitalImageDescriptor_FieldStartOffset: - return L"PID_DigitalImageDescriptor_FieldStartOffset"; + return "PID_DigitalImageDescriptor_FieldStartOffset"; case PID_DigitalImageDescriptor_FieldEndOffset: - return L"PID_DigitalImageDescriptor_FieldEndOffset"; + return "PID_DigitalImageDescriptor_FieldEndOffset"; case PID_DigitalImageDescriptor_SignalStandard: - return L"PID_DigitalImageDescriptor_SignalStandard"; + return "PID_DigitalImageDescriptor_SignalStandard"; case PID_DigitalImageDescriptor_StoredF2Offset: - return L"PID_DigitalImageDescriptor_StoredF2Offset"; + return "PID_DigitalImageDescriptor_StoredF2Offset"; case PID_DigitalImageDescriptor_DisplayF2Offset: - return L"PID_DigitalImageDescriptor_DisplayF2Offset"; + return "PID_DigitalImageDescriptor_DisplayF2Offset"; case PID_DigitalImageDescriptor_ActiveFormatDescriptor: - return L"PID_DigitalImageDescriptor_ActiveFormatDescriptor"; + return "PID_DigitalImageDescriptor_ActiveFormatDescriptor"; case PID_CDCIDescriptor_ComponentWidth: - return L"PID_CDCIDescriptor_ComponentWidth"; + return "PID_CDCIDescriptor_ComponentWidth"; case PID_CDCIDescriptor_HorizontalSubsampling: - return L"PID_CDCIDescriptor_HorizontalSubsampling"; + return "PID_CDCIDescriptor_HorizontalSubsampling"; case PID_CDCIDescriptor_ColorSiting: - return L"PID_CDCIDescriptor_ColorSiting"; + return "PID_CDCIDescriptor_ColorSiting"; case PID_CDCIDescriptor_BlackReferenceLevel: - return L"PID_CDCIDescriptor_BlackReferenceLevel"; + return "PID_CDCIDescriptor_BlackReferenceLevel"; case PID_CDCIDescriptor_WhiteReferenceLevel: - return L"PID_CDCIDescriptor_WhiteReferenceLevel"; + return "PID_CDCIDescriptor_WhiteReferenceLevel"; case PID_CDCIDescriptor_ColorRange: - return L"PID_CDCIDescriptor_ColorRange"; + return "PID_CDCIDescriptor_ColorRange"; case PID_CDCIDescriptor_PaddingBits: - return L"PID_CDCIDescriptor_PaddingBits"; + return "PID_CDCIDescriptor_PaddingBits"; case PID_CDCIDescriptor_VerticalSubsampling: - return L"PID_CDCIDescriptor_VerticalSubsampling"; + return "PID_CDCIDescriptor_VerticalSubsampling"; case PID_CDCIDescriptor_AlphaSamplingWidth: - return L"PID_CDCIDescriptor_AlphaSamplingWidth"; + return "PID_CDCIDescriptor_AlphaSamplingWidth"; case PID_CDCIDescriptor_ReversedByteOrder: - return L"PID_CDCIDescriptor_ReversedByteOrder"; + return "PID_CDCIDescriptor_ReversedByteOrder"; case PID_RGBADescriptor_PixelLayout: - return L"PID_RGBADescriptor_PixelLayout"; + return "PID_RGBADescriptor_PixelLayout"; case PID_RGBADescriptor_Palette: - return L"PID_RGBADescriptor_Palette"; + return "PID_RGBADescriptor_Palette"; case PID_RGBADescriptor_PaletteLayout: - return L"PID_RGBADescriptor_PaletteLayout"; + return "PID_RGBADescriptor_PaletteLayout"; case PID_RGBADescriptor_ScanningDirection: - return L"PID_RGBADescriptor_ScanningDirection"; + return "PID_RGBADescriptor_ScanningDirection"; case PID_RGBADescriptor_ComponentMaxRef: - return L"PID_RGBADescriptor_ComponentMaxRef"; + return "PID_RGBADescriptor_ComponentMaxRef"; case PID_RGBADescriptor_ComponentMinRef: - return L"PID_RGBADescriptor_ComponentMinRef"; + return "PID_RGBADescriptor_ComponentMinRef"; case PID_RGBADescriptor_AlphaMaxRef: - return L"PID_RGBADescriptor_AlphaMaxRef"; + return "PID_RGBADescriptor_AlphaMaxRef"; case PID_RGBADescriptor_AlphaMinRef: - return L"PID_RGBADescriptor_AlphaMinRef"; + return "PID_RGBADescriptor_AlphaMinRef"; case PID_TIFFDescriptor_IsUniform: - return L"PID_TIFFDescriptor_IsUniform"; + return "PID_TIFFDescriptor_IsUniform"; case PID_TIFFDescriptor_IsContiguous: - return L"PID_TIFFDescriptor_IsContiguous"; + return "PID_TIFFDescriptor_IsContiguous"; case PID_TIFFDescriptor_LeadingLines: - return L"PID_TIFFDescriptor_LeadingLines"; + return "PID_TIFFDescriptor_LeadingLines"; case PID_TIFFDescriptor_TrailingLines: - return L"PID_TIFFDescriptor_TrailingLines"; + return "PID_TIFFDescriptor_TrailingLines"; case PID_TIFFDescriptor_JPEGTableID: - return L"PID_TIFFDescriptor_JPEGTableID"; + return "PID_TIFFDescriptor_JPEGTableID"; case PID_TIFFDescriptor_Summary: - return L"PID_TIFFDescriptor_Summary"; + return "PID_TIFFDescriptor_Summary"; case PID_WAVEDescriptor_Summary: - return L"PID_WAVEDescriptor_Summary"; + return "PID_WAVEDescriptor_Summary"; case PID_FilmDescriptor_FilmFormat: - return L"PID_FilmDescriptor_FilmFormat"; + return "PID_FilmDescriptor_FilmFormat"; case PID_FilmDescriptor_FrameRate: - return L"PID_FilmDescriptor_FrameRate"; + return "PID_FilmDescriptor_FrameRate"; case PID_FilmDescriptor_PerforationsPerFrame: - return L"PID_FilmDescriptor_PerforationsPerFrame"; + return "PID_FilmDescriptor_PerforationsPerFrame"; case PID_FilmDescriptor_FilmAspectRatio: - return L"PID_FilmDescriptor_FilmAspectRatio"; + return "PID_FilmDescriptor_FilmAspectRatio"; case PID_FilmDescriptor_Manufacturer: - return L"PID_FilmDescriptor_Manufacturer"; + return "PID_FilmDescriptor_Manufacturer"; case PID_FilmDescriptor_Model: - return L"PID_FilmDescriptor_Model"; + return "PID_FilmDescriptor_Model"; case PID_FilmDescriptor_FilmGaugeFormat: - return L"PID_FilmDescriptor_FilmGaugeFormat"; + return "PID_FilmDescriptor_FilmGaugeFormat"; case PID_FilmDescriptor_FilmBatchNumber: - return L"PID_FilmDescriptor_FilmBatchNumber"; + return "PID_FilmDescriptor_FilmBatchNumber"; case PID_TapeDescriptor_FormFactor: - return L"PID_TapeDescriptor_FormFactor"; + return "PID_TapeDescriptor_FormFactor"; case PID_TapeDescriptor_VideoSignal: - return L"PID_TapeDescriptor_VideoSignal"; + return "PID_TapeDescriptor_VideoSignal"; case PID_TapeDescriptor_TapeFormat: - return L"PID_TapeDescriptor_TapeFormat"; + return "PID_TapeDescriptor_TapeFormat"; case PID_TapeDescriptor_Length: - return L"PID_TapeDescriptor_Length"; + return "PID_TapeDescriptor_Length"; case PID_TapeDescriptor_ManufacturerID: - return L"PID_TapeDescriptor_ManufacturerID"; + return "PID_TapeDescriptor_ManufacturerID"; case PID_TapeDescriptor_Model: - return L"PID_TapeDescriptor_Model"; + return "PID_TapeDescriptor_Model"; case PID_TapeDescriptor_TapeBatchNumber: - return L"PID_TapeDescriptor_TapeBatchNumber"; + return "PID_TapeDescriptor_TapeBatchNumber"; case PID_TapeDescriptor_TapeStock: - return L"PID_TapeDescriptor_TapeStock"; + return "PID_TapeDescriptor_TapeStock"; case PID_Header_ByteOrder: - return L"PID_Header_ByteOrder"; + return "PID_Header_ByteOrder"; case PID_Header_LastModified: - return L"PID_Header_LastModified"; + return "PID_Header_LastModified"; case PID_Header_Content: - return L"PID_Header_Content"; + return "PID_Header_Content"; case PID_Header_Dictionary: - return L"PID_Header_Dictionary"; + return "PID_Header_Dictionary"; case PID_Header_Version: - return L"PID_Header_Version"; + return "PID_Header_Version"; case PID_Header_IdentificationList: - return L"PID_Header_IdentificationList"; + return "PID_Header_IdentificationList"; case PID_Header_ObjectModelVersion: - return L"PID_Header_ObjectModelVersion"; + return "PID_Header_ObjectModelVersion"; case PID_Header_OperationalPattern: - return L"PID_Header_OperationalPattern"; + return "PID_Header_OperationalPattern"; case PID_Header_EssenceContainers: - return L"PID_Header_EssenceContainers"; + return "PID_Header_EssenceContainers"; case PID_Header_DescriptiveSchemes: - return L"PID_Header_DescriptiveSchemes"; + return "PID_Header_DescriptiveSchemes"; case PID_Identification_CompanyName: - return L"PID_Identification_CompanyName"; + return "PID_Identification_CompanyName"; case PID_Identification_ProductName: - return L"PID_Identification_ProductName"; + return "PID_Identification_ProductName"; case PID_Identification_ProductVersion: - return L"PID_Identification_ProductVersion"; + return "PID_Identification_ProductVersion"; case PID_Identification_ProductVersionString: - return L"PID_Identification_ProductVersionString"; + return "PID_Identification_ProductVersionString"; case PID_Identification_ProductID: - return L"PID_Identification_ProductID"; + return "PID_Identification_ProductID"; case PID_Identification_Date: - return L"PID_Identification_Date"; + return "PID_Identification_Date"; case PID_Identification_ToolkitVersion: - return L"PID_Identification_ToolkitVersion"; + return "PID_Identification_ToolkitVersion"; case PID_Identification_Platform: - return L"PID_Identification_Platform"; + return "PID_Identification_Platform"; case PID_Identification_GenerationAUID: - return L"PID_Identification_GenerationAUID"; + return "PID_Identification_GenerationAUID"; case PID_NetworkLocator_URLString: - return L"PID_NetworkLocator_URLString"; + return "PID_NetworkLocator_URLString"; case PID_TextLocator_Name: - return L"PID_TextLocator_Name"; + return "PID_TextLocator_Name"; case PID_Mob_MobID: - return L"PID_Mob_MobID"; + return "PID_Mob_MobID"; case PID_Mob_Name: - return L"PID_Mob_Name"; + return "PID_Mob_Name"; case PID_Mob_Slots: - return L"PID_Mob_Slots"; + return "PID_Mob_Slots"; case PID_Mob_LastModified: - return L"PID_Mob_LastModified"; + return "PID_Mob_LastModified"; case PID_Mob_CreationTime: - return L"PID_Mob_CreationTime"; + return "PID_Mob_CreationTime"; case PID_Mob_UserComments: - return L"PID_Mob_UserComments"; + return "PID_Mob_UserComments"; case PID_Mob_KLVData: - return L"PID_Mob_KLVData"; + return "PID_Mob_KLVData"; case PID_Mob_Attributes: - return L"PID_Mob_Attributes"; + return "PID_Mob_Attributes"; case PID_Mob_UsageCode: - return L"PID_Mob_UsageCode"; + return "PID_Mob_UsageCode"; case PID_CompositionMob_DefaultFadeLength: - return L"PID_CompositionMob_DefaultFadeLength"; + return "PID_CompositionMob_DefaultFadeLength"; case PID_CompositionMob_DefFadeType: - return L"PID_CompositionMob_DefFadeType"; + return "PID_CompositionMob_DefFadeType"; case PID_CompositionMob_DefFadeEditUnit: - return L"PID_CompositionMob_DefFadeEditUnit"; + return "PID_CompositionMob_DefFadeEditUnit"; case PID_CompositionMob_Rendering: - return L"PID_CompositionMob_Rendering"; + return "PID_CompositionMob_Rendering"; case PID_SourceMob_EssenceDescription: - return L"PID_SourceMob_EssenceDescription"; + return "PID_SourceMob_EssenceDescription"; case PID_MobSlot_SlotID: - return L"PID_MobSlot_SlotID"; + return "PID_MobSlot_SlotID"; case PID_MobSlot_SlotName: - return L"PID_MobSlot_SlotName"; + return "PID_MobSlot_SlotName"; case PID_MobSlot_Segment: - return L"PID_MobSlot_Segment"; + return "PID_MobSlot_Segment"; case PID_MobSlot_PhysicalTrackNumber: - return L"PID_MobSlot_PhysicalTrackNumber"; + return "PID_MobSlot_PhysicalTrackNumber"; case PID_EventMobSlot_EditRate: - return L"PID_EventMobSlot_EditRate"; + return "PID_EventMobSlot_EditRate"; case PID_EventMobSlot_EventSlotOrigin: - return L"PID_EventMobSlot_EventSlotOrigin"; + return "PID_EventMobSlot_EventSlotOrigin"; case PID_TimelineMobSlot_EditRate: - return L"PID_TimelineMobSlot_EditRate"; + return "PID_TimelineMobSlot_EditRate"; case PID_TimelineMobSlot_Origin: - return L"PID_TimelineMobSlot_Origin"; + return "PID_TimelineMobSlot_Origin"; case PID_TimelineMobSlot_MarkIn: - return L"PID_TimelineMobSlot_MarkIn"; + return "PID_TimelineMobSlot_MarkIn"; case PID_TimelineMobSlot_MarkOut: - return L"PID_TimelineMobSlot_MarkOut"; + return "PID_TimelineMobSlot_MarkOut"; case PID_TimelineMobSlot_UserPos: - return L"PID_TimelineMobSlot_UserPos"; + return "PID_TimelineMobSlot_UserPos"; case PID_Parameter_Definition: - return L"PID_Parameter_Definition"; + return "PID_Parameter_Definition"; case PID_ConstantValue_Value: - return L"PID_ConstantValue_Value"; + return "PID_ConstantValue_Value"; case PID_VaryingValue_Interpolation: - return L"PID_VaryingValue_Interpolation"; + return "PID_VaryingValue_Interpolation"; case PID_VaryingValue_PointList: - return L"PID_VaryingValue_PointList"; + return "PID_VaryingValue_PointList"; case PID_TaggedValue_Name: - return L"PID_TaggedValue_Name"; + return "PID_TaggedValue_Name"; case PID_TaggedValue_Value: - return L"PID_TaggedValue_Value"; + return "PID_TaggedValue_Value"; case PID_KLVData_Value: - return L"PID_KLVData_Value"; + return "PID_KLVData_Value"; case PID_DescriptiveMarker_DescribedSlots: - return L"PID_DescriptiveMarker_DescribedSlots"; + return "PID_DescriptiveMarker_DescribedSlots"; case PID_DescriptiveMarker_Description: - return L"PID_DescriptiveMarker_Description"; + return "PID_DescriptiveMarker_Description"; case PID_SoundDescriptor_AudioSamplingRate: - return L"PID_SoundDescriptor_AudioSamplingRate"; + return "PID_SoundDescriptor_AudioSamplingRate"; case PID_SoundDescriptor_Locked: - return L"PID_SoundDescriptor_Locked"; + return "PID_SoundDescriptor_Locked"; case PID_SoundDescriptor_AudioRefLevel: - return L"PID_SoundDescriptor_AudioRefLevel"; + return "PID_SoundDescriptor_AudioRefLevel"; case PID_SoundDescriptor_ElectroSpatial: - return L"PID_SoundDescriptor_ElectroSpatial"; + return "PID_SoundDescriptor_ElectroSpatial"; case PID_SoundDescriptor_Channels: - return L"PID_SoundDescriptor_Channels"; + return "PID_SoundDescriptor_Channels"; case PID_SoundDescriptor_QuantizationBits: - return L"PID_SoundDescriptor_QuantizationBits"; + return "PID_SoundDescriptor_QuantizationBits"; case PID_SoundDescriptor_DialNorm: - return L"PID_SoundDescriptor_DialNorm"; + return "PID_SoundDescriptor_DialNorm"; case PID_SoundDescriptor_Compression: - return L"PID_SoundDescriptor_Compression"; + return "PID_SoundDescriptor_Compression"; case PID_DataEssenceDescriptor_DataEssenceCoding: - return L"PID_DataEssenceDescriptor_DataEssenceCoding"; + return "PID_DataEssenceDescriptor_DataEssenceCoding"; case PID_MultipleDescriptor_FileDescriptors: - return L"PID_MultipleDescriptor_FileDescriptors"; + return "PID_MultipleDescriptor_FileDescriptors"; case PID_DescriptiveClip_DescribedSlotIDs: - return L"PID_DescriptiveClip_DescribedSlotIDs"; + return "PID_DescriptiveClip_DescribedSlotIDs"; case PID_AES3PCMDescriptor_Emphasis: - return L"PID_AES3PCMDescriptor_Emphasis"; + return "PID_AES3PCMDescriptor_Emphasis"; case PID_AES3PCMDescriptor_BlockStartOffset: - return L"PID_AES3PCMDescriptor_BlockStartOffset"; + return "PID_AES3PCMDescriptor_BlockStartOffset"; case PID_AES3PCMDescriptor_AuxBitsMode: - return L"PID_AES3PCMDescriptor_AuxBitsMode"; + return "PID_AES3PCMDescriptor_AuxBitsMode"; case PID_AES3PCMDescriptor_ChannelStatusMode: - return L"PID_AES3PCMDescriptor_ChannelStatusMode"; + return "PID_AES3PCMDescriptor_ChannelStatusMode"; case PID_AES3PCMDescriptor_FixedChannelStatusData: - return L"PID_AES3PCMDescriptor_FixedChannelStatusData"; + return "PID_AES3PCMDescriptor_FixedChannelStatusData"; case PID_AES3PCMDescriptor_UserDataMode: - return L"PID_AES3PCMDescriptor_UserDataMode"; + return "PID_AES3PCMDescriptor_UserDataMode"; case PID_AES3PCMDescriptor_FixedUserData: - return L"PID_AES3PCMDescriptor_FixedUserData"; + return "PID_AES3PCMDescriptor_FixedUserData"; case PID_PCMDescriptor_BlockAlign: - return L"PID_PCMDescriptor_BlockAlign"; + return "PID_PCMDescriptor_BlockAlign"; case PID_PCMDescriptor_SequenceOffset: - return L"PID_PCMDescriptor_SequenceOffset"; + return "PID_PCMDescriptor_SequenceOffset"; case PID_PCMDescriptor_AverageBPS: - return L"PID_PCMDescriptor_AverageBPS"; + return "PID_PCMDescriptor_AverageBPS"; case PID_PCMDescriptor_ChannelAssignment: - return L"PID_PCMDescriptor_ChannelAssignment"; + return "PID_PCMDescriptor_ChannelAssignment"; case PID_PCMDescriptor_PeakEnvelopeVersion: - return L"PID_PCMDescriptor_PeakEnvelopeVersion"; + return "PID_PCMDescriptor_PeakEnvelopeVersion"; case PID_PCMDescriptor_PeakEnvelopeFormat: - return L"PID_PCMDescriptor_PeakEnvelopeFormat"; + return "PID_PCMDescriptor_PeakEnvelopeFormat"; case PID_PCMDescriptor_PointsPerPeakValue: - return L"PID_PCMDescriptor_PointsPerPeakValue"; + return "PID_PCMDescriptor_PointsPerPeakValue"; case PID_PCMDescriptor_PeakEnvelopeBlockSize: - return L"PID_PCMDescriptor_PeakEnvelopeBlockSize"; + return "PID_PCMDescriptor_PeakEnvelopeBlockSize"; case PID_PCMDescriptor_PeakChannels: - return L"PID_PCMDescriptor_PeakChannels"; + return "PID_PCMDescriptor_PeakChannels"; case PID_PCMDescriptor_PeakFrames: - return L"PID_PCMDescriptor_PeakFrames"; + return "PID_PCMDescriptor_PeakFrames"; case PID_PCMDescriptor_PeakOfPeaksPosition: - return L"PID_PCMDescriptor_PeakOfPeaksPosition"; + return "PID_PCMDescriptor_PeakOfPeaksPosition"; case PID_PCMDescriptor_PeakEnvelopeTimestamp: - return L"PID_PCMDescriptor_PeakEnvelopeTimestamp"; + return "PID_PCMDescriptor_PeakEnvelopeTimestamp"; case PID_PCMDescriptor_PeakEnvelopeData: - return L"PID_PCMDescriptor_PeakEnvelopeData"; + return "PID_PCMDescriptor_PeakEnvelopeData"; case PID_KLVDataDefinition_KLVDataType: - return L"PID_KLVDataDefinition_KLVDataType"; + return "PID_KLVDataDefinition_KLVDataType"; case PID_AuxiliaryDescriptor_MimeType: - return L"PID_AuxiliaryDescriptor_MimeType"; + return "PID_AuxiliaryDescriptor_MimeType"; case PID_AuxiliaryDescriptor_CharSet: - return L"PID_AuxiliaryDescriptor_CharSet"; + return "PID_AuxiliaryDescriptor_CharSet"; case PID_RIFFChunk_ChunkID: - return L"PID_RIFFChunk_ChunkID"; + return "PID_RIFFChunk_ChunkID"; case PID_RIFFChunk_ChunkLength: - return L"PID_RIFFChunk_ChunkLength"; + return "PID_RIFFChunk_ChunkLength"; case PID_RIFFChunk_ChunkData: - return L"PID_RIFFChunk_ChunkData"; + return "PID_RIFFChunk_ChunkData"; case PID_BWFImportDescriptor_QltyFileSecurityReport: - return L"PID_BWFImportDescriptor_QltyFileSecurityReport"; + return "PID_BWFImportDescriptor_QltyFileSecurityReport"; case PID_BWFImportDescriptor_QltyFileSecurityWave: - return L"PID_BWFImportDescriptor_QltyFileSecurityWave"; + return "PID_BWFImportDescriptor_QltyFileSecurityWave"; case PID_BWFImportDescriptor_BextCodingHistory: - return L"PID_BWFImportDescriptor_BextCodingHistory"; + return "PID_BWFImportDescriptor_BextCodingHistory"; case PID_BWFImportDescriptor_QltyBasicData: - return L"PID_BWFImportDescriptor_QltyBasicData"; + return "PID_BWFImportDescriptor_QltyBasicData"; case PID_BWFImportDescriptor_QltyStartOfModulation: - return L"PID_BWFImportDescriptor_QltyStartOfModulation"; + return "PID_BWFImportDescriptor_QltyStartOfModulation"; case PID_BWFImportDescriptor_QltyQualityEvent: - return L"PID_BWFImportDescriptor_QltyQualityEvent"; + return "PID_BWFImportDescriptor_QltyQualityEvent"; case PID_BWFImportDescriptor_QltyEndOfModulation: - return L"PID_BWFImportDescriptor_QltyEndOfModulation"; + return "PID_BWFImportDescriptor_QltyEndOfModulation"; case PID_BWFImportDescriptor_QltyQualityParameter: - return L"PID_BWFImportDescriptor_QltyQualityParameter"; + return "PID_BWFImportDescriptor_QltyQualityParameter"; case PID_BWFImportDescriptor_QltyOperatorComment: - return L"PID_BWFImportDescriptor_QltyOperatorComment"; + return "PID_BWFImportDescriptor_QltyOperatorComment"; case PID_BWFImportDescriptor_QltyCueSheet: - return L"PID_BWFImportDescriptor_QltyCueSheet"; + return "PID_BWFImportDescriptor_QltyCueSheet"; case PID_BWFImportDescriptor_UnknownBWFChunks: - return L"PID_BWFImportDescriptor_UnknownBWFChunks"; + return "PID_BWFImportDescriptor_UnknownBWFChunks"; /* the following is marked as "dynamic" in ref implementation : * AAF/ref-impl/include/ref-api/AAFTypes.h @@ -1866,68 +1976,68 @@ aaft_PIDToText (AAF_Data* aafd, aafPID_t pid) */ case PID_ClassDefinition_ParentClass: - return L"PID_ClassDefinition_ParentClass"; + return "PID_ClassDefinition_ParentClass"; case PID_ClassDefinition_Properties: - return L"PID_ClassDefinition_Properties"; + return "PID_ClassDefinition_Properties"; case PID_ClassDefinition_IsConcrete: - return L"PID_ClassDefinition_IsConcrete"; + return "PID_ClassDefinition_IsConcrete"; case PID_PropertyDefinition_Type: - return L"PID_PropertyDefinition_Type"; + return "PID_PropertyDefinition_Type"; case PID_PropertyDefinition_IsOptional: - return L"PID_PropertyDefinition_IsOptional"; + return "PID_PropertyDefinition_IsOptional"; case PID_PropertyDefinition_LocalIdentification: - return L"PID_PropertyDefinition_LocalIdentification"; + return "PID_PropertyDefinition_LocalIdentification"; case PID_PropertyDefinition_IsUniqueIdentifier: - return L"PID_PropertyDefinition_IsUniqueIdentifier"; + return "PID_PropertyDefinition_IsUniqueIdentifier"; case PID_TypeDefinitionInteger_Size: - return L"PID_TypeDefinitionInteger_Size"; + return "PID_TypeDefinitionInteger_Size"; case PID_TypeDefinitionInteger_IsSigned: - return L"PID_TypeDefinitionInteger_IsSigned"; + return "PID_TypeDefinitionInteger_IsSigned"; case PID_TypeDefinitionStrongObjectReference_ReferencedType: - return L"PID_TypeDefinitionStrongObjectReference_ReferencedType"; + return "PID_TypeDefinitionStrongObjectReference_ReferencedType"; case PID_TypeDefinitionWeakObjectReference_ReferencedType: - return L"PID_TypeDefinitionWeakObjectReference_ReferencedType"; + return "PID_TypeDefinitionWeakObjectReference_ReferencedType"; case PID_TypeDefinitionWeakObjectReference_TargetSet: - return L"PID_TypeDefinitionWeakObjectReference_TargetSet"; + return "PID_TypeDefinitionWeakObjectReference_TargetSet"; case PID_TypeDefinitionEnumeration_ElementType: - return L"PID_TypeDefinitionEnumeration_ElementType"; + return "PID_TypeDefinitionEnumeration_ElementType"; case PID_TypeDefinitionEnumeration_ElementNames: - return L"PID_TypeDefinitionEnumeration_ElementNames"; + return "PID_TypeDefinitionEnumeration_ElementNames"; case PID_TypeDefinitionEnumeration_ElementValues: - return L"PID_TypeDefinitionEnumeration_ElementValues"; + return "PID_TypeDefinitionEnumeration_ElementValues"; case PID_TypeDefinitionFixedArray_ElementType: - return L"PID_TypeDefinitionFixedArray_ElementType"; + return "PID_TypeDefinitionFixedArray_ElementType"; case PID_TypeDefinitionFixedArray_ElementCount: - return L"PID_TypeDefinitionFixedArray_ElementCount"; + return "PID_TypeDefinitionFixedArray_ElementCount"; case PID_TypeDefinitionVariableArray_ElementType: - return L"PID_TypeDefinitionVariableArray_ElementType"; + return "PID_TypeDefinitionVariableArray_ElementType"; case PID_TypeDefinitionSet_ElementType: - return L"PID_TypeDefinitionSet_ElementType"; + return "PID_TypeDefinitionSet_ElementType"; case PID_TypeDefinitionString_ElementType: - return L"PID_TypeDefinitionString_ElementType"; + return "PID_TypeDefinitionString_ElementType"; case PID_TypeDefinitionRecord_MemberTypes: - return L"PID_TypeDefinitionRecord_MemberTypes"; + return "PID_TypeDefinitionRecord_MemberTypes"; case PID_TypeDefinitionRecord_MemberNames: - return L"PID_TypeDefinitionRecord_MemberNames"; + return "PID_TypeDefinitionRecord_MemberNames"; case PID_TypeDefinitionRename_RenamedType: - return L"PID_TypeDefinitionRename_RenamedType"; + return "PID_TypeDefinitionRename_RenamedType"; case PID_TypeDefinitionExtendibleEnumeration_ElementNames: - return L"PID_TypeDefinitionExtendibleEnumeration_ElementNames"; + return "PID_TypeDefinitionExtendibleEnumeration_ElementNames"; case PID_TypeDefinitionExtendibleEnumeration_ElementValues: - return L"PID_TypeDefinitionExtendibleEnumeration_ElementValues"; + return "PID_TypeDefinitionExtendibleEnumeration_ElementValues"; case PID_MetaDefinition_Identification: - return L"PID_MetaDefinition_Identification"; + return "PID_MetaDefinition_Identification"; case PID_MetaDefinition_Name: - return L"PID_MetaDefinition_Name"; + return "PID_MetaDefinition_Name"; case PID_MetaDefinition_Description: - return L"PID_MetaDefinition_Description"; + return "PID_MetaDefinition_Description"; case PID_MetaDictionary_ClassDefinitions: - return L"PID_MetaDictionary_ClassDefinitions"; + return "PID_MetaDictionary_ClassDefinitions"; case PID_MetaDictionary_TypeDefinitions: - return L"PID_MetaDictionary_TypeDefinitions"; + return "PID_MetaDictionary_TypeDefinitions"; } - static wchar_t PIDText[1024]; + static char PIDText[1024]; aafClass* Class = NULL; @@ -1938,234 +2048,242 @@ aaft_PIDToText (AAF_Data* aafd, aafPID_t pid) foreachPropertyDefinition (PDef, Class->Properties) { if (PDef->pid == pid) { - swprintf (PIDText, 1024, L"%" WPRIs L"%" WPRIws L"%" WPRIs, - (PDef->meta) ? ANSI_COLOR_YELLOW (aafd->dbg) : "", - PDef->name, - (PDef->meta) ? ANSI_COLOR_RESET (aafd->dbg) : ""); + int rc = snprintf (PIDText, sizeof (PIDText), "%s%s%s", + (PDef->meta) ? ANSI_COLOR_MAGENTA (aafd->log) : "", + PDef->name, + (PDef->meta) ? ANSI_COLOR_RESET (aafd->log) : ""); + + assert (rc >= 0 && (size_t)rc < sizeof (PIDText)); + + // if ( rc < 0 || (size_t)rc >= 1024 ) { + // fprintf( stderr, "snprintf() error" ); + // return NULL; + // } + return PIDText; } } } - return L"Unknown PID_MetaDictionary"; + return "Unknown PID_MetaDictionary"; } -const wchar_t* +const char* aaft_ClassIDToText (AAF_Data* aafd, const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AUID_NULL)) - return L"AUID_NULL"; + return "AUID_NULL"; if (aafUIDCmp (auid, &AAFClassID_Root)) - return L"AAFClassID_Root"; + return "AAFClassID_Root"; if (aafUIDCmp (auid, &AAFClassID_InterchangeObject)) - return L"AAFClassID_InterchangeObject"; + return "AAFClassID_InterchangeObject"; if (aafUIDCmp (auid, &AAFClassID_Component)) - return L"AAFClassID_Component"; + return "AAFClassID_Component"; if (aafUIDCmp (auid, &AAFClassID_Segment)) - return L"AAFClassID_Segment"; + return "AAFClassID_Segment"; if (aafUIDCmp (auid, &AAFClassID_EdgeCode)) - return L"AAFClassID_EdgeCode"; + return "AAFClassID_EdgeCode"; if (aafUIDCmp (auid, &AAFClassID_EssenceGroup)) - return L"AAFClassID_EssenceGroup"; + return "AAFClassID_EssenceGroup"; if (aafUIDCmp (auid, &AAFClassID_Event)) - return L"AAFClassID_Event"; + return "AAFClassID_Event"; if (aafUIDCmp (auid, &AAFClassID_GPITrigger)) - return L"AAFClassID_GPITrigger"; + return "AAFClassID_GPITrigger"; if (aafUIDCmp (auid, &AAFClassID_CommentMarker)) - return L"AAFClassID_CommentMarker"; + return "AAFClassID_CommentMarker"; if (aafUIDCmp (auid, &AAFClassID_Filler)) - return L"AAFClassID_Filler"; + return "AAFClassID_Filler"; if (aafUIDCmp (auid, &AAFClassID_OperationGroup)) - return L"AAFClassID_OperationGroup"; + return "AAFClassID_OperationGroup"; if (aafUIDCmp (auid, &AAFClassID_NestedScope)) - return L"AAFClassID_NestedScope"; + return "AAFClassID_NestedScope"; if (aafUIDCmp (auid, &AAFClassID_Pulldown)) - return L"AAFClassID_Pulldown"; + return "AAFClassID_Pulldown"; if (aafUIDCmp (auid, &AAFClassID_ScopeReference)) - return L"AAFClassID_ScopeReference"; + return "AAFClassID_ScopeReference"; if (aafUIDCmp (auid, &AAFClassID_Selector)) - return L"AAFClassID_Selector"; + return "AAFClassID_Selector"; if (aafUIDCmp (auid, &AAFClassID_Sequence)) - return L"AAFClassID_Sequence"; + return "AAFClassID_Sequence"; if (aafUIDCmp (auid, &AAFClassID_SourceReference)) - return L"AAFClassID_SourceReference"; + return "AAFClassID_SourceReference"; if (aafUIDCmp (auid, &AAFClassID_SourceClip)) - return L"AAFClassID_SourceClip"; + return "AAFClassID_SourceClip"; if (aafUIDCmp (auid, &AAFClassID_TextClip)) - return L"AAFClassID_TextClip"; + return "AAFClassID_TextClip"; if (aafUIDCmp (auid, &AAFClassID_HTMLClip)) - return L"AAFClassID_HTMLClip"; + return "AAFClassID_HTMLClip"; if (aafUIDCmp (auid, &AAFClassID_Timecode)) - return L"AAFClassID_Timecode"; + return "AAFClassID_Timecode"; if (aafUIDCmp (auid, &AAFClassID_TimecodeStream)) - return L"AAFClassID_TimecodeStream"; + return "AAFClassID_TimecodeStream"; if (aafUIDCmp (auid, &AAFClassID_TimecodeStream12M)) - return L"AAFClassID_TimecodeStream12M"; + return "AAFClassID_TimecodeStream12M"; if (aafUIDCmp (auid, &AAFClassID_Transition)) - return L"AAFClassID_Transition"; + return "AAFClassID_Transition"; if (aafUIDCmp (auid, &AAFClassID_ContentStorage)) - return L"AAFClassID_ContentStorage"; + return "AAFClassID_ContentStorage"; if (aafUIDCmp (auid, &AAFClassID_ControlPoint)) - return L"AAFClassID_ControlPoint"; + return "AAFClassID_ControlPoint"; if (aafUIDCmp (auid, &AAFClassID_DefinitionObject)) - return L"AAFClassID_DefinitionObject"; + return "AAFClassID_DefinitionObject"; if (aafUIDCmp (auid, &AAFClassID_DataDefinition)) - return L"AAFClassID_DataDefinition"; + return "AAFClassID_DataDefinition"; if (aafUIDCmp (auid, &AAFClassID_OperationDefinition)) - return L"AAFClassID_OperationDefinition"; + return "AAFClassID_OperationDefinition"; if (aafUIDCmp (auid, &AAFClassID_ParameterDefinition)) - return L"AAFClassID_ParameterDefinition"; + return "AAFClassID_ParameterDefinition"; if (aafUIDCmp (auid, &AAFClassID_PluginDefinition)) - return L"AAFClassID_PluginDefinition"; + return "AAFClassID_PluginDefinition"; if (aafUIDCmp (auid, &AAFClassID_CodecDefinition)) - return L"AAFClassID_CodecDefinition"; + return "AAFClassID_CodecDefinition"; if (aafUIDCmp (auid, &AAFClassID_ContainerDefinition)) - return L"AAFClassID_ContainerDefinition"; + return "AAFClassID_ContainerDefinition"; if (aafUIDCmp (auid, &AAFClassID_InterpolationDefinition)) - return L"AAFClassID_InterpolationDefinition"; + return "AAFClassID_InterpolationDefinition"; if (aafUIDCmp (auid, &AAFClassID_Dictionary)) - return L"AAFClassID_Dictionary"; + return "AAFClassID_Dictionary"; if (aafUIDCmp (auid, &AAFClassID_EssenceData)) - return L"AAFClassID_EssenceData"; + return "AAFClassID_EssenceData"; if (aafUIDCmp (auid, &AAFClassID_EssenceDescriptor)) - return L"AAFClassID_EssenceDescriptor"; + return "AAFClassID_EssenceDescriptor"; if (aafUIDCmp (auid, &AAFClassID_FileDescriptor)) - return L"AAFClassID_FileDescriptor"; + return "AAFClassID_FileDescriptor"; if (aafUIDCmp (auid, &AAFClassID_AIFCDescriptor)) - return L"AAFClassID_AIFCDescriptor"; + return "AAFClassID_AIFCDescriptor"; if (aafUIDCmp (auid, &AAFClassID_DigitalImageDescriptor)) - return L"AAFClassID_DigitalImageDescriptor"; + return "AAFClassID_DigitalImageDescriptor"; if (aafUIDCmp (auid, &AAFClassID_CDCIDescriptor)) - return L"AAFClassID_CDCIDescriptor"; + return "AAFClassID_CDCIDescriptor"; if (aafUIDCmp (auid, &AAFClassID_RGBADescriptor)) - return L"AAFClassID_RGBADescriptor"; + return "AAFClassID_RGBADescriptor"; if (aafUIDCmp (auid, &AAFClassID_HTMLDescriptor)) - return L"AAFClassID_HTMLDescriptor"; + return "AAFClassID_HTMLDescriptor"; if (aafUIDCmp (auid, &AAFClassID_TIFFDescriptor)) - return L"AAFClassID_TIFFDescriptor"; + return "AAFClassID_TIFFDescriptor"; if (aafUIDCmp (auid, &AAFClassID_WAVEDescriptor)) - return L"AAFClassID_WAVEDescriptor"; + return "AAFClassID_WAVEDescriptor"; if (aafUIDCmp (auid, &AAFClassID_FilmDescriptor)) - return L"AAFClassID_FilmDescriptor"; + return "AAFClassID_FilmDescriptor"; if (aafUIDCmp (auid, &AAFClassID_TapeDescriptor)) - return L"AAFClassID_TapeDescriptor"; + return "AAFClassID_TapeDescriptor"; if (aafUIDCmp (auid, &AAFClassID_Header)) - return L"AAFClassID_Header"; + return "AAFClassID_Header"; if (aafUIDCmp (auid, &AAFClassID_Identification)) - return L"AAFClassID_Identification"; + return "AAFClassID_Identification"; if (aafUIDCmp (auid, &AAFClassID_Locator)) - return L"AAFClassID_Locator"; + return "AAFClassID_Locator"; if (aafUIDCmp (auid, &AAFClassID_NetworkLocator)) - return L"AAFClassID_NetworkLocator"; + return "AAFClassID_NetworkLocator"; if (aafUIDCmp (auid, &AAFClassID_TextLocator)) - return L"AAFClassID_TextLocator"; + return "AAFClassID_TextLocator"; if (aafUIDCmp (auid, &AAFClassID_Mob)) - return L"AAFClassID_Mob"; + return "AAFClassID_Mob"; if (aafUIDCmp (auid, &AAFClassID_CompositionMob)) - return L"AAFClassID_CompositionMob"; + return "AAFClassID_CompositionMob"; if (aafUIDCmp (auid, &AAFClassID_MasterMob)) - return L"AAFClassID_MasterMob"; + return "AAFClassID_MasterMob"; if (aafUIDCmp (auid, &AAFClassID_SourceMob)) - return L"AAFClassID_SourceMob"; + return "AAFClassID_SourceMob"; if (aafUIDCmp (auid, &AAFClassID_MobSlot)) - return L"AAFClassID_MobSlot"; + return "AAFClassID_MobSlot"; if (aafUIDCmp (auid, &AAFClassID_EventMobSlot)) - return L"AAFClassID_EventMobSlot"; + return "AAFClassID_EventMobSlot"; if (aafUIDCmp (auid, &AAFClassID_StaticMobSlot)) - return L"AAFClassID_StaticMobSlot"; + return "AAFClassID_StaticMobSlot"; if (aafUIDCmp (auid, &AAFClassID_TimelineMobSlot)) - return L"AAFClassID_TimelineMobSlot"; + return "AAFClassID_TimelineMobSlot"; if (aafUIDCmp (auid, &AAFClassID_Parameter)) - return L"AAFClassID_Parameter"; + return "AAFClassID_Parameter"; if (aafUIDCmp (auid, &AAFClassID_ConstantValue)) - return L"AAFClassID_ConstantValue"; + return "AAFClassID_ConstantValue"; if (aafUIDCmp (auid, &AAFClassID_VaryingValue)) - return L"AAFClassID_VaryingValue"; + return "AAFClassID_VaryingValue"; if (aafUIDCmp (auid, &AAFClassID_TaggedValue)) - return L"AAFClassID_TaggedValue"; + return "AAFClassID_TaggedValue"; if (aafUIDCmp (auid, &AAFClassID_KLVData)) - return L"AAFClassID_KLVData"; + return "AAFClassID_KLVData"; if (aafUIDCmp (auid, &AAFClassID_DescriptiveMarker)) - return L"AAFClassID_DescriptiveMarker"; + return "AAFClassID_DescriptiveMarker"; if (aafUIDCmp (auid, &AAFClassID_SoundDescriptor)) - return L"AAFClassID_SoundDescriptor"; + return "AAFClassID_SoundDescriptor"; if (aafUIDCmp (auid, &AAFClassID_DataEssenceDescriptor)) - return L"AAFClassID_DataEssenceDescriptor"; + return "AAFClassID_DataEssenceDescriptor"; if (aafUIDCmp (auid, &AAFClassID_MultipleDescriptor)) - return L"AAFClassID_MultipleDescriptor"; + return "AAFClassID_MultipleDescriptor"; if (aafUIDCmp (auid, &AAFClassID_DescriptiveClip)) - return L"AAFClassID_DescriptiveClip"; + return "AAFClassID_DescriptiveClip"; if (aafUIDCmp (auid, &AAFClassID_AES3PCMDescriptor)) - return L"AAFClassID_AES3PCMDescriptor"; + return "AAFClassID_AES3PCMDescriptor"; if (aafUIDCmp (auid, &AAFClassID_PCMDescriptor)) - return L"AAFClassID_PCMDescriptor"; + return "AAFClassID_PCMDescriptor"; if (aafUIDCmp (auid, &AAFClassID_PhysicalDescriptor)) - return L"AAFClassID_PhysicalDescriptor"; + return "AAFClassID_PhysicalDescriptor"; if (aafUIDCmp (auid, &AAFClassID_ImportDescriptor)) - return L"AAFClassID_ImportDescriptor"; + return "AAFClassID_ImportDescriptor"; if (aafUIDCmp (auid, &AAFClassID_RecordingDescriptor)) - return L"AAFClassID_RecordingDescriptor"; + return "AAFClassID_RecordingDescriptor"; if (aafUIDCmp (auid, &AAFClassID_TaggedValueDefinition)) - return L"AAFClassID_TaggedValueDefinition"; + return "AAFClassID_TaggedValueDefinition"; if (aafUIDCmp (auid, &AAFClassID_KLVDataDefinition)) - return L"AAFClassID_KLVDataDefinition"; + return "AAFClassID_KLVDataDefinition"; if (aafUIDCmp (auid, &AAFClassID_AuxiliaryDescriptor)) - return L"AAFClassID_AuxiliaryDescriptor"; + return "AAFClassID_AuxiliaryDescriptor"; if (aafUIDCmp (auid, &AAFClassID_RIFFChunk)) - return L"AAFClassID_RIFFChunk"; + return "AAFClassID_RIFFChunk"; if (aafUIDCmp (auid, &AAFClassID_BWFImportDescriptor)) - return L"AAFClassID_BWFImportDescriptor"; + return "AAFClassID_BWFImportDescriptor"; if (aafUIDCmp (auid, &AAFClassID_MPEGVideoDescriptor)) - return L"AAFClassID_MPEGVideoDescriptor"; + return "AAFClassID_MPEGVideoDescriptor"; if (aafUIDCmp (auid, &AAFClassID_ClassDefinition)) - return L"AAFClassID_ClassDefinition"; + return "AAFClassID_ClassDefinition"; if (aafUIDCmp (auid, &AAFClassID_PropertyDefinition)) - return L"AAFClassID_PropertyDefinition"; + return "AAFClassID_PropertyDefinition"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinition)) - return L"AAFClassID_TypeDefinition"; + return "AAFClassID_TypeDefinition"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionInteger)) - return L"AAFClassID_TypeDefinitionInteger"; + return "AAFClassID_TypeDefinitionInteger"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionStrongObjectReference)) - return L"AAFClassID_TypeDefinitionStrongObjectReference"; + return "AAFClassID_TypeDefinitionStrongObjectReference"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionWeakObjectReference)) - return L"AAFClassID_TypeDefinitionWeakObjectReference"; + return "AAFClassID_TypeDefinitionWeakObjectReference"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionEnumeration)) - return L"AAFClassID_TypeDefinitionEnumeration"; + return "AAFClassID_TypeDefinitionEnumeration"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionFixedArray)) - return L"AAFClassID_TypeDefinitionFixedArray"; + return "AAFClassID_TypeDefinitionFixedArray"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionVariableArray)) - return L"AAFClassID_TypeDefinitionVariableArray"; + return "AAFClassID_TypeDefinitionVariableArray"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionSet)) - return L"AAFClassID_TypeDefinitionSet"; + return "AAFClassID_TypeDefinitionSet"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionString)) - return L"AAFClassID_TypeDefinitionString"; + return "AAFClassID_TypeDefinitionString"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionStream)) - return L"AAFClassID_TypeDefinitionStream"; + return "AAFClassID_TypeDefinitionStream"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionRecord)) - return L"AAFClassID_TypeDefinitionRecord"; + return "AAFClassID_TypeDefinitionRecord"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionRename)) - return L"AAFClassID_TypeDefinitionRename"; + return "AAFClassID_TypeDefinitionRename"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionExtendibleEnumeration)) - return L"AAFClassID_TypeDefinitionExtendibleEnumeration"; + return "AAFClassID_TypeDefinitionExtendibleEnumeration"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionIndirect)) - return L"AAFClassID_TypeDefinitionIndirect"; + return "AAFClassID_TypeDefinitionIndirect"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionOpaque)) - return L"AAFClassID_TypeDefinitionOpaque"; + return "AAFClassID_TypeDefinitionOpaque"; if (aafUIDCmp (auid, &AAFClassID_TypeDefinitionCharacter)) - return L"AAFClassID_TypeDefinitionCharacter"; + return "AAFClassID_TypeDefinitionCharacter"; if (aafUIDCmp (auid, &AAFClassID_MetaDefinition)) - return L"AAFClassID_MetaDefinition"; + return "AAFClassID_MetaDefinition"; if (aafUIDCmp (auid, &AAFClassID_MetaDictionary)) - return L"AAFClassID_MetaDictionary"; + return "AAFClassID_MetaDictionary"; if (aafUIDCmp (auid, &AAFClassID_DescriptiveObject)) - return L"AAFClassID_DescriptiveObject"; + return "AAFClassID_DescriptiveObject"; if (aafUIDCmp (auid, &AAFClassID_DescriptiveFramework)) - return L"AAFClassID_DescriptiveFramework"; + return "AAFClassID_DescriptiveFramework"; - static wchar_t ClassIDText[1024]; + static char ClassIDText[1024]; ClassIDText[0] = '\0'; @@ -2174,265 +2292,338 @@ aaft_ClassIDToText (AAF_Data* aafd, const aafUID_t* auid) foreachClass (Class, aafd->Classes) { if (aafUIDCmp (Class->ID, auid)) { - swprintf (ClassIDText, 1024, L"%" WPRIs L"%" WPRIws L"%" WPRIs, - (Class->meta) ? ANSI_COLOR_YELLOW (aafd->dbg) : "", - Class->name, - (Class->meta) ? ANSI_COLOR_RESET (aafd->dbg) : ""); + int rc = snprintf (ClassIDText, sizeof (ClassIDText), "%s%s%s", + (Class->meta) ? ANSI_COLOR_MAGENTA (aafd->log) : "", + Class->name, + (Class->meta) ? ANSI_COLOR_RESET (aafd->log) : ""); + + assert (rc >= 0 && (size_t)rc < sizeof (ClassIDText)); + + // if ( rc < 0 || (size_t)rc >= 1024 ) { + // fprintf( stderr, "snprintf() error" ); + // return NULL; + // } + return ClassIDText; } } - return L"Unknown AAFClassID"; + return "Unknown AAFClassID"; } -const wchar_t* +const char* +aaft_IndirectValueToText (AAF_Data* aafd, aafIndirect_t* Indirect) +{ + static char buf[4096]; + + memset (buf, 0x00, sizeof (buf)); + + void* indirectValue = aaf_get_indirectValue (aafd, Indirect, NULL); + + if (!indirectValue) { + return NULL; + } + + int rc = 0; + + if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Boolean)) { + rc = snprintf (buf, sizeof (buf), "%c", *(uint8_t*)indirectValue); + } else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Rational)) { + rc = snprintf (buf, sizeof (buf), "%i/%i", ((aafRational_t*)indirectValue)->numerator, ((aafRational_t*)indirectValue)->denominator); + } + + else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Int8)) { + rc = snprintf (buf, sizeof (buf), "%c", *(int8_t*)indirectValue); + } else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Int16)) { + rc = snprintf (buf, sizeof (buf), "%i", *(int16_t*)indirectValue); + } else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Int32)) { + rc = snprintf (buf, sizeof (buf), "%i", *(int32_t*)indirectValue); + } else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_Int64)) { + rc = snprintf (buf, sizeof (buf), "%" PRIi64, *(int64_t*)indirectValue); + } + + else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_UInt16)) { + rc = snprintf (buf, sizeof (buf), "%u", *(uint16_t*)indirectValue); + } else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_UInt32)) { + rc = snprintf (buf, sizeof (buf), "%u", *(uint32_t*)indirectValue); + } else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_UInt64)) { + rc = snprintf (buf, sizeof (buf), "%" PRIu64, *(uint64_t*)indirectValue); + } + + else if (aafUIDCmp (&Indirect->TypeDef, &AAFTypeID_String)) { + char* str = aaf_get_indirectValue (aafd, Indirect, &AAFTypeID_String); + + if (!str) { + error ("Could not retrieve Indirect value"); + return NULL; + } + + rc = snprintf (buf, sizeof (buf), "%s", str); + + free (str); + } else { + error ("Unsupported Indirect value type ID : %s", aaft_TypeIDToText (&Indirect->TypeDef)); + return NULL; + } + + assert (rc >= 0 && (size_t)rc < sizeof (buf)); + + // if ( rc < 0 || (size_t)rc >= sizeof(buf) ) { + // fprintf( stderr, "snprintf() error" ); + // return NULL; + // } + + return buf; +} + +const char* aaft_ContainerToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AUID_NULL)) - return L"AUID_NULL"; + return "AUID_NULL"; if (aafUIDCmp (auid, &AAFContainerDef_External)) - return L"AAFContainerDef_External"; + return "AAFContainerDef_External"; if (aafUIDCmp (auid, &AAFContainerDef_OMF)) - return L"AAFContainerDef_OMF"; + return "AAFContainerDef_OMF"; if (aafUIDCmp (auid, &AAFContainerDef_AAF)) - return L"AAFContainerDef_AAF"; + return "AAFContainerDef_AAF"; if (aafUIDCmp (auid, &AAFContainerDef_AAFMSS)) - return L"AAFContainerDef_AAFMSS"; + return "AAFContainerDef_AAFMSS"; if (aafUIDCmp (auid, &AAFContainerDef_AAFKLV)) - return L"AAFContainerDef_AAFKLV"; + return "AAFContainerDef_AAFKLV"; if (aafUIDCmp (auid, &AAFContainerDef_AAFXML)) - return L"AAFContainerDef_AAFXML"; + return "AAFContainerDef_AAFXML"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_DefinedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_DefinedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_DefinedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_ExtendedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_ExtendedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_ExtendedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_PictureOnly)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_PictureOnly"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_50Mbps_PictureOnly"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_DefinedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_DefinedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_DefinedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_ExtendedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_ExtendedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_ExtendedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_PictureOnly)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_PictureOnly"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_50Mbps_PictureOnly"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_DefinedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_DefinedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_DefinedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_ExtendedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_ExtendedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_ExtendedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_PictureOnly)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_PictureOnly"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_40Mbps_PictureOnly"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_DefinedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_DefinedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_DefinedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_ExtendedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_ExtendedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_ExtendedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_PictureOnly)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_PictureOnly"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_40Mbps_PictureOnly"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_DefinedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_DefinedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_DefinedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_ExtendedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_ExtendedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_ExtendedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_PictureOnly)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_PictureOnly"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_625x50I_30Mbps_PictureOnly"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_DefinedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_DefinedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_DefinedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_ExtendedTemplate)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_ExtendedTemplate"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_ExtendedTemplate"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_PictureOnly)) - return L"AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_PictureOnly"; + return "AAFContainerDef_MXFGC_Framewrapped_SMPTE_D10_525x5994I_30Mbps_PictureOnly"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_IECDV_525x5994I_25Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_IECDV_525x5994I_25Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_IECDV_525x5994I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_IECDV_525x5994I_25Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_IECDV_525x5994I_25Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_IECDV_525x5994I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_IECDV_625x50I_25Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_IECDV_625x50I_25Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_IECDV_625x50I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_IECDV_625x50I_25Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_IECDV_625x50I_25Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_IECDV_625x50I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_IECDV_525x5994I_25Mbps_SMPTE322M)) - return L"AAFContainerDef_MXFGC_Framewrapped_IECDV_525x5994I_25Mbps_SMPTE322M"; + return "AAFContainerDef_MXFGC_Framewrapped_IECDV_525x5994I_25Mbps_SMPTE322M"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_IECDV_525x5994I_25Mbps_SMPTE322M)) - return L"AAFContainerDef_MXFGC_Clipwrapped_IECDV_525x5994I_25Mbps_SMPTE322M"; + return "AAFContainerDef_MXFGC_Clipwrapped_IECDV_525x5994I_25Mbps_SMPTE322M"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_IECDV_625x50I_25Mbps_SMPTE322M)) - return L"AAFContainerDef_MXFGC_Framewrapped_IECDV_625x50I_25Mbps_SMPTE322M"; + return "AAFContainerDef_MXFGC_Framewrapped_IECDV_625x50I_25Mbps_SMPTE322M"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_IECDV_625x50I_25Mbps_SMPTE322M)) - return L"AAFContainerDef_MXFGC_Clipwrapped_IECDV_625x50I_25Mbps_SMPTE322M"; + return "AAFContainerDef_MXFGC_Clipwrapped_IECDV_625x50I_25Mbps_SMPTE322M"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_IECDV_UndefinedSource_25Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_IECDV_UndefinedSource_25Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_IECDV_UndefinedSource_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_IECDV_UndefinedSource_25Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_IECDV_UndefinedSource_25Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_IECDV_UndefinedSource_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_525x5994I_25Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_525x5994I_25Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_525x5994I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_525x5994I_25Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_525x5994I_25Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_525x5994I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_625x50I_25Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_625x50I_25Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_625x50I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_625x50I_25Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_625x50I_25Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_625x50I_25Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_525x5994I_50Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_525x5994I_50Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_525x5994I_50Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_525x5994I_50Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_525x5994I_50Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_525x5994I_50Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_625x50I_50Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_625x50I_50Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_625x50I_50Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_625x50I_50Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_625x50I_50Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_625x50I_50Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_1080x5994I_100Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_1080x5994I_100Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_1080x5994I_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_1080x5994I_100Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_1080x5994I_100Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_1080x5994I_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_1080x50I_100Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_1080x50I_100Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_1080x50I_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_1080x50I_100Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_1080x50I_100Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_1080x50I_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_720x5994P_100Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_720x5994P_100Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_720x5994P_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_720x5994P_100Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_720x5994P_100Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_720x5994P_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_720x50P_100Mbps)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_720x50P_100Mbps"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_720x50P_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_720x50P_100Mbps)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_720x50P_100Mbps"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_720x50P_100Mbps"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_DVbased_UndefinedSource)) - return L"AAFContainerDef_MXFGC_Framewrapped_DVbased_UndefinedSource"; + return "AAFContainerDef_MXFGC_Framewrapped_DVbased_UndefinedSource"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_DVbased_UndefinedSource)) - return L"AAFContainerDef_MXFGC_Clipwrapped_DVbased_UndefinedSource"; + return "AAFContainerDef_MXFGC_Clipwrapped_DVbased_UndefinedSource"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_MPEGES_VideoStream0_SID)) - return L"AAFContainerDef_MXFGC_Framewrapped_MPEGES_VideoStream0_SID"; + return "AAFContainerDef_MXFGC_Framewrapped_MPEGES_VideoStream0_SID"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_CustomClosedGOPwrapped_MPEGES_VideoStream1_SID)) - return L"AAFContainerDef_MXFGC_CustomClosedGOPwrapped_MPEGES_VideoStream1_SID"; + return "AAFContainerDef_MXFGC_CustomClosedGOPwrapped_MPEGES_VideoStream1_SID"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_Uncompressed_525x5994I_720_422)) - return L"AAFContainerDef_MXFGC_Framewrapped_Uncompressed_525x5994I_720_422"; + return "AAFContainerDef_MXFGC_Framewrapped_Uncompressed_525x5994I_720_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_525x5994I_720_422)) - return L"AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_525x5994I_720_422"; + return "AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_525x5994I_720_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Linewrapped_Uncompressed_525x5994I_720_422)) - return L"AAFContainerDef_MXFGC_Linewrapped_Uncompressed_525x5994I_720_422"; + return "AAFContainerDef_MXFGC_Linewrapped_Uncompressed_525x5994I_720_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_Uncompressed_625x50I_720_422)) - return L"AAFContainerDef_MXFGC_Framewrapped_Uncompressed_625x50I_720_422"; + return "AAFContainerDef_MXFGC_Framewrapped_Uncompressed_625x50I_720_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_625x50I_720_422)) - return L"AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_625x50I_720_422"; + return "AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_625x50I_720_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Linewrapped_Uncompressed_625x50I_720_422)) - return L"AAFContainerDef_MXFGC_Linewrapped_Uncompressed_625x50I_720_422"; + return "AAFContainerDef_MXFGC_Linewrapped_Uncompressed_625x50I_720_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_Uncompressed_525x5994P_960_422)) - return L"AAFContainerDef_MXFGC_Framewrapped_Uncompressed_525x5994P_960_422"; + return "AAFContainerDef_MXFGC_Framewrapped_Uncompressed_525x5994P_960_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_525x5994P_960_422)) - return L"AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_525x5994P_960_422"; + return "AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_525x5994P_960_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Linewrapped_Uncompressed_525x5994P_960_422)) - return L"AAFContainerDef_MXFGC_Linewrapped_Uncompressed_525x5994P_960_422"; + return "AAFContainerDef_MXFGC_Linewrapped_Uncompressed_525x5994P_960_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_Uncompressed_625x50P_960_422)) - return L"AAFContainerDef_MXFGC_Framewrapped_Uncompressed_625x50P_960_422"; + return "AAFContainerDef_MXFGC_Framewrapped_Uncompressed_625x50P_960_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_625x50P_960_422)) - return L"AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_625x50P_960_422"; + return "AAFContainerDef_MXFGC_Clipwrapped_Uncompressed_625x50P_960_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Linewrapped_Uncompressed_625x50P_960_422)) - return L"AAFContainerDef_MXFGC_Linewrapped_Uncompressed_625x50P_960_422"; + return "AAFContainerDef_MXFGC_Linewrapped_Uncompressed_625x50P_960_422"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_Broadcast_Wave_audio_data)) - return L"AAFContainerDef_MXFGC_Framewrapped_Broadcast_Wave_audio_data"; + return "AAFContainerDef_MXFGC_Framewrapped_Broadcast_Wave_audio_data"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_Broadcast_Wave_audio_data)) - return L"AAFContainerDef_MXFGC_Clipwrapped_Broadcast_Wave_audio_data"; + return "AAFContainerDef_MXFGC_Clipwrapped_Broadcast_Wave_audio_data"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_AES3_audio_data)) - return L"AAFContainerDef_MXFGC_Framewrapped_AES3_audio_data"; + return "AAFContainerDef_MXFGC_Framewrapped_AES3_audio_data"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_AES3_audio_data)) - return L"AAFContainerDef_MXFGC_Clipwrapped_AES3_audio_data"; + return "AAFContainerDef_MXFGC_Clipwrapped_AES3_audio_data"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_Alaw_Audio)) - return L"AAFContainerDef_MXFGC_Framewrapped_Alaw_Audio"; + return "AAFContainerDef_MXFGC_Framewrapped_Alaw_Audio"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_Alaw_Audio)) - return L"AAFContainerDef_MXFGC_Clipwrapped_Alaw_Audio"; + return "AAFContainerDef_MXFGC_Clipwrapped_Alaw_Audio"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Customwrapped_Alaw_Audio)) - return L"AAFContainerDef_MXFGC_Customwrapped_Alaw_Audio"; + return "AAFContainerDef_MXFGC_Customwrapped_Alaw_Audio"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_AVCbytestream_VideoStream0_SID)) - return L"AAFContainerDef_MXFGC_Clipwrapped_AVCbytestream_VideoStream0_SID"; + return "AAFContainerDef_MXFGC_Clipwrapped_AVCbytestream_VideoStream0_SID"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_VC3)) - return L"AAFContainerDef_MXFGC_Framewrapped_VC3"; + return "AAFContainerDef_MXFGC_Framewrapped_VC3"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_VC3)) - return L"AAFContainerDef_MXFGC_Clipwrapped_VC3"; + return "AAFContainerDef_MXFGC_Clipwrapped_VC3"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Framewrapped_VC1)) - return L"AAFContainerDef_MXFGC_Framewrapped_VC1"; + return "AAFContainerDef_MXFGC_Framewrapped_VC1"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Clipwrapped_VC1)) - return L"AAFContainerDef_MXFGC_Clipwrapped_VC1"; + return "AAFContainerDef_MXFGC_Clipwrapped_VC1"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Generic_Essence_Multiple_Mappings)) - return L"AAFContainerDef_MXFGC_Generic_Essence_Multiple_Mappings"; + return "AAFContainerDef_MXFGC_Generic_Essence_Multiple_Mappings"; if (aafUIDCmp (auid, &AAFContainerDef_RIFFWAVE)) - return L"AAFContainerDef_RIFFWAVE"; + return "AAFContainerDef_RIFFWAVE"; if (aafUIDCmp (auid, &AAFContainerDef_JFIF)) - return L"AAFContainerDef_JFIF"; + return "AAFContainerDef_JFIF"; if (aafUIDCmp (auid, &AAFContainerDef_AIFFAIFC)) - return L"AAFContainerDef_AIFFAIFC"; + return "AAFContainerDef_AIFFAIFC"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_220X_1080p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_220X_1080p"; + return "AAFContainerDef_MXFGC_Avid_DNX_220X_1080p"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_145_1080p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_145_1080p"; + return "AAFContainerDef_MXFGC_Avid_DNX_145_1080p"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_220_1080p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_220_1080p"; + return "AAFContainerDef_MXFGC_Avid_DNX_220_1080p"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_36_1080p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_36_1080p"; + return "AAFContainerDef_MXFGC_Avid_DNX_36_1080p"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_220X_1080i)) - return L"AAFContainerDef_MXFGC_Avid_DNX_220X_1080i"; + return "AAFContainerDef_MXFGC_Avid_DNX_220X_1080i"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_145_1080i)) - return L"AAFContainerDef_MXFGC_Avid_DNX_145_1080i"; + return "AAFContainerDef_MXFGC_Avid_DNX_145_1080i"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_220_1080i)) - return L"AAFContainerDef_MXFGC_Avid_DNX_220_1080i"; + return "AAFContainerDef_MXFGC_Avid_DNX_220_1080i"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_145_1440_1080i)) - return L"AAFContainerDef_MXFGC_Avid_DNX_145_1440_1080i"; + return "AAFContainerDef_MXFGC_Avid_DNX_145_1440_1080i"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_220X_720p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_220X_720p"; + return "AAFContainerDef_MXFGC_Avid_DNX_220X_720p"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_220_720p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_220_720p"; + return "AAFContainerDef_MXFGC_Avid_DNX_220_720p"; if (aafUIDCmp (auid, &AAFContainerDef_MXFGC_Avid_DNX_145_720p)) - return L"AAFContainerDef_MXFGC_Avid_DNX_145_720p"; + return "AAFContainerDef_MXFGC_Avid_DNX_145_720p"; - return L"Unknown AAFContainerDef"; + return "Unknown AAFContainerDef"; } -const wchar_t* +const char* aaft_CompressionToText (const aafUID_t* auid) { if (auid == NULL) - return L"n/a"; + return "n/a"; if (aafUIDCmp (auid, &AUID_NULL)) - return L"AUID_NULL"; + return "AUID_NULL"; if (aafUIDCmp (auid, &AAFCompressionDef_AAF_CMPR_FULL_JPEG)) - return L"AAFCompressionDef_AAF_CMPR_FULL_JPEG"; + return "AAFCompressionDef_AAF_CMPR_FULL_JPEG"; if (aafUIDCmp (auid, &AAFCompressionDef_AAF_CMPR_AUNC422)) - return L"AAFCompressionDef_AAF_CMPR_AUNC422"; + return "AAFCompressionDef_AAF_CMPR_AUNC422"; if (aafUIDCmp (auid, &AAFCompressionDef_LegacyDV)) - return L"AAFCompressionDef_LegacyDV"; + return "AAFCompressionDef_LegacyDV"; if (aafUIDCmp (auid, &AAFCompressionDef_SMPTE_D10_50Mbps_625x50I)) - return L"AAFCompressionDef_SMPTE_D10_50Mbps_625x50I"; + return "AAFCompressionDef_SMPTE_D10_50Mbps_625x50I"; if (aafUIDCmp (auid, &AAFCompressionDef_SMPTE_D10_50Mbps_525x5994I)) - return L"AAFCompressionDef_SMPTE_D10_50Mbps_525x5994I"; + return "AAFCompressionDef_SMPTE_D10_50Mbps_525x5994I"; if (aafUIDCmp (auid, &AAFCompressionDef_SMPTE_D10_40Mbps_625x50I)) - return L"AAFCompressionDef_SMPTE_D10_40Mbps_625x50I"; + return "AAFCompressionDef_SMPTE_D10_40Mbps_625x50I"; if (aafUIDCmp (auid, &AAFCompressionDef_SMPTE_D10_40Mbps_525x5994I)) - return L"AAFCompressionDef_SMPTE_D10_40Mbps_525x5994I"; + return "AAFCompressionDef_SMPTE_D10_40Mbps_525x5994I"; if (aafUIDCmp (auid, &AAFCompressionDef_SMPTE_D10_30Mbps_625x50I)) - return L"AAFCompressionDef_SMPTE_D10_30Mbps_625x50I"; + return "AAFCompressionDef_SMPTE_D10_30Mbps_625x50I"; if (aafUIDCmp (auid, &AAFCompressionDef_SMPTE_D10_30Mbps_525x5994I)) - return L"AAFCompressionDef_SMPTE_D10_30Mbps_525x5994I"; + return "AAFCompressionDef_SMPTE_D10_30Mbps_525x5994I"; if (aafUIDCmp (auid, &AAFCompressionDef_IEC_DV_525_60)) - return L"AAFCompressionDef_IEC_DV_525_60"; + return "AAFCompressionDef_IEC_DV_525_60"; if (aafUIDCmp (auid, &AAFCompressionDef_IEC_DV_625_50)) - return L"AAFCompressionDef_IEC_DV_625_50"; + return "AAFCompressionDef_IEC_DV_625_50"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_25Mbps_525_60)) - return L"AAFCompressionDef_DV_Based_25Mbps_525_60"; + return "AAFCompressionDef_DV_Based_25Mbps_525_60"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_25Mbps_625_50)) - return L"AAFCompressionDef_DV_Based_25Mbps_625_50"; + return "AAFCompressionDef_DV_Based_25Mbps_625_50"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_50Mbps_525_60)) - return L"AAFCompressionDef_DV_Based_50Mbps_525_60"; + return "AAFCompressionDef_DV_Based_50Mbps_525_60"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_50Mbps_625_50)) - return L"AAFCompressionDef_DV_Based_50Mbps_625_50"; + return "AAFCompressionDef_DV_Based_50Mbps_625_50"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_100Mbps_1080x5994I)) - return L"AAFCompressionDef_DV_Based_100Mbps_1080x5994I"; + return "AAFCompressionDef_DV_Based_100Mbps_1080x5994I"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_100Mbps_1080x50I)) - return L"AAFCompressionDef_DV_Based_100Mbps_1080x50I"; + return "AAFCompressionDef_DV_Based_100Mbps_1080x50I"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_100Mbps_720x5994P)) - return L"AAFCompressionDef_DV_Based_100Mbps_720x5994P"; + return "AAFCompressionDef_DV_Based_100Mbps_720x5994P"; if (aafUIDCmp (auid, &AAFCompressionDef_DV_Based_100Mbps_720x50P)) - return L"AAFCompressionDef_DV_Based_100Mbps_720x50P"; + return "AAFCompressionDef_DV_Based_100Mbps_720x50P"; if (aafUIDCmp (auid, &AAFCompressionDef_VC3_1)) - return L"AAFCompressionDef_VC3_1"; + return "AAFCompressionDef_VC3_1"; if (aafUIDCmp (auid, &AAFCompressionDef_Avid_DNxHD_Legacy)) - return L"AAFCompressionDef_Avid_DNxHD_Legacy"; + return "AAFCompressionDef_Avid_DNxHD_Legacy"; - return L"Unknown AAFCompressionDef"; + return "Unknown AAFCompressionDef"; } diff --git a/libs/aaf/CFBDump.c b/libs/aaf/CFBDump.c index e3dfa85fa6..a342a06254 100644 --- a/libs/aaf/CFBDump.c +++ b/libs/aaf/CFBDump.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -18,11 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include #include -#include #include "aaf/CFBDump.h" #include "aaf/LibCFB.h" @@ -30,16 +28,16 @@ #include "aaf/utils.h" #define debug(...) \ - _dbg (cfbd->dbg, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (cfbd->log, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (cfbd->dbg, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_WARNING, __VA_ARGS__) + AAF_LOG (cfbd->log, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (cfbd->dbg, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_ERROR, __VA_ARGS__) + AAF_LOG (cfbd->log, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_ERROR, __VA_ARGS__) void -cfb_dump_node (CFB_Data* cfbd, cfbNode* node, int print_stream) +cfb_dump_node (CFB_Data* cfbd, cfbNode* node, int print_stream, const char* padding) { if (node == NULL) return; @@ -47,77 +45,86 @@ cfb_dump_node (CFB_Data* cfbd, cfbNode* node, int print_stream) if (node->_mse == STGTY_INVALID) return; - wchar_t nodeName[CFB_NODE_NAME_SZ]; + char* nodeName = cfb_w16toUTF8 (node->_ab, node->_cb); - cfb_w16towchar (nodeName, node->_ab, node->_cb); + struct aafLog* log = cfbd->log; - struct dbg* dbg = cfbd->dbg; - - DBG_BUFFER_WRITE (dbg, "\n"); - DBG_BUFFER_WRITE (dbg, " _ab : %ls\n", nodeName); - DBG_BUFFER_WRITE (dbg, " _cb : %u\n", node->_cb); - DBG_BUFFER_WRITE (dbg, " _mse : %s\n", + LOG_BUFFER_WRITE (log, "\n"); + LOG_BUFFER_WRITE (log, "%s_ab : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), nodeName, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_cb : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_cb, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_mse : %s%s%s\n", + padding, + ANSI_COLOR_DARKGREY (log), node->_mse == 0 ? "STGTY_INVALID" : node->_mse == 1 ? "STGTY_STORAGE" : node->_mse == 2 ? "STGTY_STREAM" : node->_mse == 3 ? "STGTY_LOCKBYTES" : node->_mse == 4 ? "STGTY_PROPERTY" : node->_mse == 5 ? "STGTY_ROOT" - : ""); + : "", + ANSI_COLOR_RESET (log)); - DBG_BUFFER_WRITE (dbg, " _bflags : %s\n", node->_bflags == 1 ? "BLACK" : "RED"); - DBG_BUFFER_WRITE (dbg, " _sidLeftSib : 0x%08x\n", node->_sidLeftSib); - DBG_BUFFER_WRITE (dbg, " _sidRightSib : 0x%08x\n", node->_sidRightSib); + LOG_BUFFER_WRITE (log, "%s_bflags : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_bflags == 1 ? "BLACK" : "RED", ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_sidLeftSib : %s0x%08x%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_sidLeftSib, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_sidRightSib : %s0x%08x%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_sidRightSib, ANSI_COLOR_RESET (log)); if (node->_mse == STGTY_STORAGE || node->_mse == STGTY_ROOT) { - DBG_BUFFER_WRITE (dbg, " _sidChild : 0x%08x\n", node->_sidChild); - DBG_BUFFER_WRITE (dbg, " _clsid : %ls\n", cfb_CLSIDToText (&(node->_clsId))); - DBG_BUFFER_WRITE (dbg, " _dwUserFlags : 0x%08x (%d)\n", node->_dwUserFlags, node->_dwUserFlags); + LOG_BUFFER_WRITE (log, "%s_sidChild : %s0x%08x%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_sidChild, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_clsid : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), cfb_CLSIDToText (&(node->_clsId)), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_dwUserFlags : %s0x%08x (%d)%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_dwUserFlags, node->_dwUserFlags, ANSI_COLOR_RESET (log)); } if (node->_mse == STGTY_INVALID) { - DBG_BUFFER_WRITE (dbg, " _time (cre) : 0x%08x%08x\n", + LOG_BUFFER_WRITE (log, "%s_time (cre) : %s0x%08x%08x%s\n", + padding, + ANSI_COLOR_DARKGREY (log), node->_time[0].dwHighDateTime, - node->_time[0].dwLowDateTime); + node->_time[0].dwLowDateTime, + ANSI_COLOR_RESET (log)); - DBG_BUFFER_WRITE (dbg, " _ (mod) : 0x%08x%08x\n", + LOG_BUFFER_WRITE (log, "%s_ (mod) : %s0x%08x%08x%s\n", + padding, + ANSI_COLOR_DARKGREY (log), node->_time[1].dwHighDateTime, - node->_time[1].dwLowDateTime); + node->_time[1].dwLowDateTime, + ANSI_COLOR_RESET (log)); } if (node->_mse == STGTY_STREAM || node->_mse == STGTY_ROOT) { - DBG_BUFFER_WRITE (dbg, " _sectStart : 0x%08x (%d)\n", node->_sectStart, node->_sectStart); - DBG_BUFFER_WRITE (dbg, " _ulSizeLow : 0x%08x (%d)\n", node->_ulSizeLow, node->_ulSizeLow); - DBG_BUFFER_WRITE (dbg, " _ulSizeHigh : 0x%08x (%d)\n", node->_ulSizeHigh, node->_ulSizeHigh); + LOG_BUFFER_WRITE (log, "%s_sectStart : %s0x%08x (%d)%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_sectStart, node->_sectStart, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_ulSizeLow : %s0x%08x (%d)%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_ulSizeLow, node->_ulSizeLow, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_ulSizeHigh : %s0x%08x (%d)%s\n", padding, ANSI_COLOR_DARKGREY (log), node->_ulSizeHigh, node->_ulSizeHigh, ANSI_COLOR_RESET (log)); } - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); if (print_stream == 1) { - cfb_dump_nodeStream (cfbd, node); + cfb_dump_nodeStream (cfbd, node, ""); } + + free (nodeName); } void -cfb_dump_nodePath (CFB_Data* cfbd, const wchar_t* path, int print_stream) +cfb_dump_nodePath (CFB_Data* cfbd, const char* path, int print_stream, const char* padding) { cfbNode* node = cfb_getNodeByPath (cfbd, path, 0); if (node == NULL) { - error ("cfb_dump_nodePath() : Could not find node at \"%ls\"\n", path); + error ("cfb_dump_nodePath() : Could not find node at \"%s\"\n", path); return; } - cfb_dump_node (cfbd, node, print_stream); + cfb_dump_node (cfbd, node, print_stream, padding); } void -cfb_dump_nodeStream (CFB_Data* cfbd, cfbNode* node) +cfb_dump_nodeStream (CFB_Data* cfbd, cfbNode* node, const char* padding) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; unsigned char* stream = NULL; uint64_t stream_sz = 0; @@ -128,22 +135,22 @@ cfb_dump_nodeStream (CFB_Data* cfbd, cfbNode* node) return; } - laaf_util_dump_hex (stream, stream_sz, &dbg->_dbg_msg, &dbg->_dbg_msg_size, dbg->_dbg_msg_pos); + laaf_util_dump_hex (stream, stream_sz, &log->_msg, &log->_msg_size, log->_msg_pos, padding); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); free (stream); } void -cfb_dump_nodePathStream (CFB_Data* cfbd, const wchar_t* path) +cfb_dump_nodePathStream (CFB_Data* cfbd, const char* path, const char* padding) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; cfbNode* node = cfb_getNodeByPath (cfbd, path, 0); if (node == NULL) { - error ("cfb_dump_nodePathStream() : Could not find node at \"%ls\"\n", path); + error ("Could not find node at \"%s\"\n", path); return; } @@ -152,204 +159,266 @@ cfb_dump_nodePathStream (CFB_Data* cfbd, const wchar_t* path) cfb_getStream (cfbd, node, &stream, &stream_sz); - laaf_util_dump_hex (stream, stream_sz, &dbg->_dbg_msg, &dbg->_dbg_msg_size, dbg->_dbg_msg_pos); + laaf_util_dump_hex (stream, stream_sz, &log->_msg, &log->_msg_size, log->_msg_pos, padding); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); free (stream); } void -cfb_dump_nodePaths (CFB_Data* cfbd, uint32_t prevPath, char* strArray[], uint32_t* str_i, cfbNode* node) +cfb_dump_nodePaths (CFB_Data* cfbd, uint32_t prevPath, char* strArray[], uint32_t* str_i, cfbNode* node, const char* padding, int firstIteration) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; + + // if ( !node ) { + if (firstIteration) { + /* initial function call */ + node = &cfbd->nodes[0]; + + if (!node) { + return; + } - if (node == NULL) { - /* the begining of the first function call. */ - node = &cfbd->nodes[0]; strArray = calloc (cfbd->nodes_cnt, sizeof (char*)); + + if (!strArray) { + error ("Out of memory"); + return; + } } uint32_t thisPath = (*str_i); - wchar_t nodeName[CFB_NODE_NAME_SZ]; - cfb_w16towchar (nodeName, node->_ab, node->_cb); + /* TODO snprintf_realloc() ? */ + char* nodeName = cfb_w16toUTF8 (node->_ab, node->_cb); - int pathlen = snprintf (NULL, 0, "%s/%ls", strArray[prevPath], nodeName); + laaf_util_snprintf_realloc (&strArray[thisPath], 0, 0, "%s/%s", strArray[prevPath], nodeName); - if (pathlen < 0) { - // TODO error - return; - } - - pathlen++; - - strArray[thisPath] = malloc (pathlen); - - snprintf (strArray[thisPath], pathlen, "%s/%ls", strArray[prevPath], nodeName); + free (nodeName); (*str_i)++; if ((int32_t)node->_sidChild > 0) - cfb_dump_nodePaths (cfbd, thisPath, strArray, str_i, &cfbd->nodes[node->_sidChild]); + cfb_dump_nodePaths (cfbd, thisPath, strArray, str_i, &cfbd->nodes[node->_sidChild], padding, 0); if ((int32_t)node->_sidLeftSib > 0) - cfb_dump_nodePaths (cfbd, prevPath, strArray, str_i, &cfbd->nodes[node->_sidLeftSib]); + cfb_dump_nodePaths (cfbd, prevPath, strArray, str_i, &cfbd->nodes[node->_sidLeftSib], padding, 0); if ((int32_t)node->_sidRightSib > 0) - cfb_dump_nodePaths (cfbd, prevPath, strArray, str_i, &cfbd->nodes[node->_sidRightSib]); + cfb_dump_nodePaths (cfbd, prevPath, strArray, str_i, &cfbd->nodes[node->_sidRightSib], padding, 0); /* the end of the first function call, recursion is over. */ - if (node == &cfbd->nodes[0]) { - /* commented out because output is proper this way... why did we call qsort() in the first place ?! */ + // if ( node == &cfbd->nodes[0] ) { + if (firstIteration) { + /* commented out because output seems proper this way... why did we call qsort() in the first place ?! */ // qsort( strArray, *str_i, sizeof(char*), compareStrings ); for (uint32_t i = 0; i < cfbd->nodes_cnt && strArray[i] != NULL; i++) { - DBG_BUFFER_WRITE (dbg, "%05i : %s\n", i, strArray[i]); + LOG_BUFFER_WRITE (log, "%s%0*i : %s%s%s\n", + padding, + (cfbd->nodes_cnt > 1000000) ? 7 : (cfbd->nodes_cnt > 100000) ? 6 + : (cfbd->nodes_cnt > 10000) ? 5 + : (cfbd->nodes_cnt > 1000) ? 4 + : (cfbd->nodes_cnt > 100) ? 3 + : (cfbd->nodes_cnt > 10) ? 2 + : 1, + i, + ANSI_COLOR_DARKGREY (log), + strArray[i], + ANSI_COLOR_RESET (log)); free (strArray[i]); } free (strArray); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } } void -cfb_dump_header (CFB_Data* cfbd) +cfb_dump_header (CFB_Data* cfbd, const char* padding) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; cfbHeader* cfbh = cfbd->hdr; - DBG_BUFFER_WRITE (dbg, "_abSig : 0x%08" PRIx64 "\n", cfbh->_abSig); - DBG_BUFFER_WRITE (dbg, "_clsId : %ls\n", cfb_CLSIDToText (&(cfbh->_clsid))); - DBG_BUFFER_WRITE (dbg, " version : %u.%u ( 0x%04x 0x%04x )\n", + LOG_BUFFER_WRITE (log, "%s_abSig : %s0x%08" PRIx64 "%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_abSig, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_clsId : %s%s%s\n", padding, ANSI_COLOR_DARKGREY (log), cfb_CLSIDToText (&(cfbh->_clsid)), ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_version : %s%u.%u ( 0x%04x 0x%04x )%s\n", + padding, + ANSI_COLOR_DARKGREY (log), cfbh->_uMinorVersion, cfbh->_uDllVersion, - cfbh->_uMinorVersion, cfbh->_uDllVersion); - DBG_BUFFER_WRITE (dbg, "_uByteOrder : %s ( 0x%04x )\n", + cfbh->_uMinorVersion, cfbh->_uDllVersion, + ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_uByteOrder : %s%s ( 0x%04x )%s\n", + padding, + ANSI_COLOR_DARKGREY (log), cfbh->_uByteOrder == 0xFFFE ? "little-endian" : cfbh->_uByteOrder == 0xFEFF ? "big-endian" : "?", - cfbh->_uByteOrder); - DBG_BUFFER_WRITE (dbg, "_uSectorShift : %u (%u bytes sectors)\n", + cfbh->_uByteOrder, + ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_uSectorShift : %s%u (%u bytes sectors)%s\n", + padding, + ANSI_COLOR_DARKGREY (log), cfbh->_uSectorShift, - 1 << cfbh->_uSectorShift); - DBG_BUFFER_WRITE (dbg, "_uMiniSectorShift : %u (%u bytes mini-sectors)\n", + 1 << cfbh->_uSectorShift, + ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_uMiniSectorShift : %s%u (%u bytes mini-sectors)%s\n", + padding, + ANSI_COLOR_DARKGREY (log), cfbh->_uMiniSectorShift, - 1 << cfbh->_uMiniSectorShift); - DBG_BUFFER_WRITE (dbg, "_usReserved0 : 0x%02x\n", cfbh->_usReserved); - DBG_BUFFER_WRITE (dbg, "_ulReserved1 : 0x%04x\n", cfbh->_ulReserved1); - DBG_BUFFER_WRITE (dbg, "_csectDir : %u\n", cfbh->_csectDir); - DBG_BUFFER_WRITE (dbg, "_csectFat : %u\n", cfbh->_csectFat); - DBG_BUFFER_WRITE (dbg, "_sectDirStart : %u\n", cfbh->_sectDirStart); - DBG_BUFFER_WRITE (dbg, "_signature : %u\n", cfbh->_signature); - DBG_BUFFER_WRITE (dbg, "_ulMiniSectorCutoff : %u\n", cfbh->_ulMiniSectorCutoff); - DBG_BUFFER_WRITE (dbg, "_sectMiniFatStart : %u\n", cfbh->_sectMiniFatStart); - DBG_BUFFER_WRITE (dbg, "_csectMiniFat : %u\n", cfbh->_csectMiniFat); - DBG_BUFFER_WRITE (dbg, "_sectDifStart : %u\n", cfbh->_sectDifStart); - DBG_BUFFER_WRITE (dbg, "_csectDif : %u\n", cfbh->_csectDif); + 1 << cfbh->_uMiniSectorShift, + ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_usReserved0 : %s0x%02x%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_usReserved, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_ulReserved1 : %s0x%04x%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_ulReserved1, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_csectDir : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_csectDir, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_csectFat : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_csectFat, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_sectDirStart : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_sectDirStart, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_signature : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_signature, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_ulMiniSectorCutoff : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_ulMiniSectorCutoff, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_sectMiniFatStart : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_sectMiniFatStart, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_csectMiniFat : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_csectMiniFat, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_sectDifStart : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_sectDifStart, ANSI_COLOR_RESET (log)); + LOG_BUFFER_WRITE (log, "%s_csectDif : %s%u%s\n", padding, ANSI_COLOR_DARKGREY (log), cfbh->_csectDif, ANSI_COLOR_RESET (log)); - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -cfb_dump_FAT (CFB_Data* cfbd) +cfb_dump_FAT (CFB_Data* cfbd, const char* padding) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; - DBG_BUFFER_WRITE (dbg, "_CFB_FAT_______________________________________________________________________________________\n\n"); + LOG_BUFFER_WRITE (log, "_CFB_FAT_______________________________________________________________________________________\n\n"); uint32_t i = 0; for (i = 0; i < cfbd->fat_sz; i++) { - DBG_BUFFER_WRITE (dbg, " SECT[%u] : 0x%08x %s\n", + LOG_BUFFER_WRITE (log, "%sSECT[%s%0*u%s] : %s0x%08x %s%s\n", + padding, + ANSI_COLOR_DARKGREY (log), + (cfbd->fat_sz > 1000000) ? 7 : (cfbd->fat_sz > 100000) ? 6 + : (cfbd->fat_sz > 10000) ? 5 + : (cfbd->fat_sz > 1000) ? 4 + : (cfbd->fat_sz > 100) ? 3 + : (cfbd->fat_sz > 10) ? 2 + : 1, i, + ANSI_COLOR_RESET (log), + + ANSI_COLOR_DARKGREY (log), cfbd->fat[i], (cfbd->fat[i] == CFB_MAX_REG_SECT) ? "(CFB_MAX_REG_SECT)" : (cfbd->fat[i] == CFB_DIFAT_SECT) ? "(CFB_DIFAT_SECT)" : (cfbd->fat[i] == CFB_FAT_SECT) ? "(CFB_FAT_SECT)" : (cfbd->fat[i] == CFB_END_OF_CHAIN) ? "(CFB_END_OF_CHAIN)" : (cfbd->fat[i] == CFB_FREE_SECT) ? "(CFB_FREE_SECT)" - : ""); + : "", + ANSI_COLOR_RESET (log)); } - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); - DBG_BUFFER_WRITE (dbg, " End of FAT.\n\n"); + LOG_BUFFER_WRITE (log, "%sEnd of FAT.\n\n", padding); - DBG_BUFFER_WRITE (dbg, " Total FAT entries : %u\n", cfbd->fat_sz); - DBG_BUFFER_WRITE (dbg, " Count of FAT sector : %u\n", cfbd->hdr->_csectFat); + LOG_BUFFER_WRITE (log, "%sTotal FAT entries : %u\n", padding, cfbd->fat_sz); + LOG_BUFFER_WRITE (log, "%sCount of FAT sector : %u\n", padding, cfbd->hdr->_csectFat); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -cfb_dump_MiniFAT (CFB_Data* cfbd) +cfb_dump_MiniFAT (CFB_Data* cfbd, const char* padding) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; - DBG_BUFFER_WRITE (dbg, "_CFB_MiniFAT___________________________________________________________________________________\n\n"); + LOG_BUFFER_WRITE (log, "_CFB_MiniFAT___________________________________________________________________________________\n\n"); uint32_t i = 0; for (i = 0; i < cfbd->miniFat_sz; i++) { - DBG_BUFFER_WRITE (dbg, " SECT[%u] : 0x%08x %s\n", + LOG_BUFFER_WRITE (log, "%sSECT[%s%0*u%s] : %s0x%08x %s%s\n", + padding, + ANSI_COLOR_DARKGREY (log), + (cfbd->miniFat_sz > 1000000) ? 7 : (cfbd->miniFat_sz > 100000) ? 6 + : (cfbd->miniFat_sz > 10000) ? 5 + : (cfbd->miniFat_sz > 1000) ? 4 + : (cfbd->miniFat_sz > 100) ? 3 + : (cfbd->miniFat_sz > 10) ? 2 + : 1, i, + ANSI_COLOR_RESET (log), + + ANSI_COLOR_DARKGREY (log), cfbd->miniFat[i], (cfbd->miniFat[i] == CFB_MAX_REG_SECT) ? "(CFB_MAX_REG_SECT)" : (cfbd->miniFat[i] == CFB_DIFAT_SECT) ? "(CFB_DIFAT_SECT)" : (cfbd->miniFat[i] == CFB_FAT_SECT) ? "(CFB_FAT_SECT)" : (cfbd->miniFat[i] == CFB_END_OF_CHAIN) ? "(CFB_END_OF_CHAIN)" : (cfbd->miniFat[i] == CFB_FREE_SECT) ? "(CFB_FREE_SECT)" - : ""); + : "", + ANSI_COLOR_RESET (log)); } - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); - DBG_BUFFER_WRITE (dbg, " End of MiniFAT.\n\n"); + LOG_BUFFER_WRITE (log, "%sEnd of MiniFAT.\n\n", padding); - DBG_BUFFER_WRITE (dbg, " Total MiniFAT entries : %u\n", cfbd->miniFat_sz); - DBG_BUFFER_WRITE (dbg, " First MiniFAT sector ID : %u\n", cfbd->hdr->_sectMiniFatStart); - DBG_BUFFER_WRITE (dbg, " Count of MiniFAT sector : %u\n", cfbd->hdr->_csectMiniFat); + LOG_BUFFER_WRITE (log, "%sTotal MiniFAT entries : %u\n", padding, cfbd->miniFat_sz); + LOG_BUFFER_WRITE (log, "%sFirst MiniFAT sector ID : %u\n", padding, cfbd->hdr->_sectMiniFatStart); + LOG_BUFFER_WRITE (log, "%sCount of MiniFAT sector : %u\n", padding, cfbd->hdr->_csectMiniFat); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } void -cfb_dump_DiFAT (CFB_Data* cfbd) +cfb_dump_DiFAT (CFB_Data* cfbd, const char* padding) { - struct dbg* dbg = cfbd->dbg; + struct aafLog* log = cfbd->log; - DBG_BUFFER_WRITE (dbg, "_CFB_DiFAT_____________________________________________________________________________________\n\n"); + LOG_BUFFER_WRITE (log, "_CFB_DiFAT_____________________________________________________________________________________\n\n"); uint32_t i = 0; for (i = 0; i < cfbd->DiFAT_sz; i++) { - DBG_BUFFER_WRITE (dbg, " SECT[%u] : 0x%08x %s\n", + LOG_BUFFER_WRITE (log, "%sSECT[%s%0*u%s] : %s0x%08x %s%s\n", + padding, + ANSI_COLOR_DARKGREY (log), + (cfbd->miniFat_sz > 1000000) ? 7 : (cfbd->miniFat_sz > 100000) ? 6 + : (cfbd->miniFat_sz > 10000) ? 5 + : (cfbd->miniFat_sz > 1000) ? 4 + : (cfbd->miniFat_sz > 100) ? 3 + : (cfbd->miniFat_sz > 10) ? 2 + : 1, i, + ANSI_COLOR_RESET (log), + + ANSI_COLOR_DARKGREY (log), cfbd->DiFAT[i], (cfbd->DiFAT[i] == CFB_MAX_REG_SECT) ? "(CFB_MAX_REG_SECT)" : (cfbd->DiFAT[i] == CFB_DIFAT_SECT) ? "(CFB_DIFAT_SECT)" : (cfbd->DiFAT[i] == CFB_FAT_SECT) ? "(CFB_FAT_SECT)" : (cfbd->DiFAT[i] == CFB_END_OF_CHAIN) ? "(CFB_END_OF_CHAIN)" : (cfbd->DiFAT[i] == CFB_FREE_SECT) ? "(CFB_FREE_SECT)" - : ""); + : "", + ANSI_COLOR_RESET (log)); } - DBG_BUFFER_WRITE (dbg, "\n"); + LOG_BUFFER_WRITE (log, "\n"); - DBG_BUFFER_WRITE (dbg, " End of DiFAT.\n\n"); + LOG_BUFFER_WRITE (log, "%sEnd of DiFAT.\n\n", padding); - DBG_BUFFER_WRITE (dbg, " Total DiFAT entries : %u\n", cfbd->DiFAT_sz); - DBG_BUFFER_WRITE (dbg, " First DiFAT sector ID : %u\n", cfbd->hdr->_sectDifStart); - DBG_BUFFER_WRITE (dbg, " Count of DiFAT sector : Header + %u\n", cfbd->hdr->_csectDif); + LOG_BUFFER_WRITE (log, "%sTotal DiFAT entries : %u\n", padding, cfbd->DiFAT_sz); + LOG_BUFFER_WRITE (log, "%sFirst DiFAT sector ID : %u\n", padding, cfbd->hdr->_sectDifStart); + LOG_BUFFER_WRITE (log, "%sCount of DiFAT sector : Header + %u\n", padding, cfbd->hdr->_csectDif); - DBG_BUFFER_WRITE (dbg, "\n\n"); + LOG_BUFFER_WRITE (log, "\n\n"); - dbg->debug_callback (dbg, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, dbg->_dbg_msg, dbg->user); + log->debug_callback (log, (void*)cfbd, DEBUG_SRC_ID_DUMP, 0, "", "", 0, log->_msg, log->user); } diff --git a/libs/aaf/LibCFB.c b/libs/aaf/LibCFB.c index bea80a4f1b..ec68344adc 100644 --- a/libs/aaf/LibCFB.c +++ b/libs/aaf/LibCFB.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -53,7 +53,7 @@ * * Once the file is loaded, you can access the nodes with the functions * cfb_getNodeByPath() and cfb_getChildNode(), and access a node's stream with the - * functions cfb_getStream() or cfb_foreachSectorInStream(). The former is prefered + * functions cfb_getStream() or CFB_foreachSectorInStream(). The former is prefered * for small-size streams, since it allocates the entire stream to memory, while the * later loops through each sector that composes a stream, better for the big ones. * @@ -77,7 +77,7 @@ * // Loop through each sector that composes the "properties" stream * cfbSectorID_t sectorID = 0; * - * cfb_foreachSectorInStream( cfbd, properties, &stream, &stream_sz, §orID ) + * CFB_foreachSectorInStream( cfbd, properties, &stream, &stream_sz, §orID ) * { * // do stuff.. * } @@ -93,26 +93,26 @@ */ #include -#include #include // ceil() #include #include #include #include +#include "aaf/CFBDump.h" #include "aaf/LibCFB.h" -#include "aaf/debug.h" +#include "aaf/log.h" #include "aaf/utils.h" #define debug(...) \ - _dbg (cfbd->dbg, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (cfbd->log, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (cfbd->dbg, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_WARNING, __VA_ARGS__) + AAF_LOG (cfbd->log, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (cfbd->dbg, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_ERROR, __VA_ARGS__) + AAF_LOG (cfbd->log, cfbd, DEBUG_SRC_ID_LIB_CFB, VERB_ERROR, __VA_ARGS__) static int cfb_getFileSize (CFB_Data* cfbd); @@ -121,7 +121,7 @@ static int cfb_openFile (CFB_Data* cfbd); static uint64_t -cfb_readFile (CFB_Data* cfbd, unsigned char* buf, uint64_t offset, uint64_t len); +cfb_readFile (CFB_Data* cfbd, unsigned char* buf, size_t offset, size_t len); static void cfb_closeFile (CFB_Data* cfbd); @@ -150,10 +150,10 @@ getNodeCount (CFB_Data* cfbd); static cfbSID_t cfb_getIDByNode (CFB_Data* cfbd, cfbNode* node); -const wchar_t* +const char* cfb_CLSIDToText (const cfbCLSID_t* clsid) { - static wchar_t str[96]; + static char str[96]; if (clsid == NULL) { str[0] = 'n'; @@ -161,18 +161,23 @@ cfb_CLSIDToText (const cfbCLSID_t* clsid) str[2] = 'a'; str[3] = '\0'; } else { - swprintf (str, sizeof (str), L"{ 0x%08x 0x%04x 0x%04x { 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x } }", - clsid->Data1, - clsid->Data2, - clsid->Data3, - clsid->Data4[0], - clsid->Data4[1], - clsid->Data4[2], - clsid->Data4[3], - clsid->Data4[4], - clsid->Data4[5], - clsid->Data4[6], - clsid->Data4[7]); + int rc = snprintf (str, sizeof (str), "{ 0x%08x 0x%04x 0x%04x { 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x } }", + clsid->Data1, + clsid->Data2, + clsid->Data3, + clsid->Data4[0], + clsid->Data4[1], + clsid->Data4[2], + clsid->Data4[3], + clsid->Data4[4], + clsid->Data4[5], + clsid->Data4[6], + clsid->Data4[7]); + + if (rc < 0 || (size_t)rc >= sizeof (str)) { + // TODO error + return NULL; + } } return str; @@ -185,16 +190,15 @@ cfb_CLSIDToText (const cfbCLSID_t* clsid) */ CFB_Data* -cfb_alloc (struct dbg* dbg) +cfb_alloc (struct aafLog* log) { - CFB_Data* cfbd = calloc (sizeof (CFB_Data), sizeof (unsigned char)); + CFB_Data* cfbd = calloc (1, sizeof (CFB_Data)); - if (cfbd == NULL) { - error ("%s.", strerror (errno)); + if (!cfbd) { return NULL; } - cfbd->dbg = dbg; + cfbd->log = log; return cfbd; } @@ -214,30 +218,23 @@ cfb_release (CFB_Data** cfbd) cfb_closeFile (*cfbd); - if ((*cfbd)->DiFAT != NULL) { - free ((*cfbd)->DiFAT); - (*cfbd)->DiFAT = NULL; - } + free ((*cfbd)->file); + (*cfbd)->file = NULL; - if ((*cfbd)->fat != NULL) { - free ((*cfbd)->fat); - (*cfbd)->fat = NULL; - } + free ((*cfbd)->DiFAT); + (*cfbd)->DiFAT = NULL; - if ((*cfbd)->miniFat != NULL) { - free ((*cfbd)->miniFat); - (*cfbd)->miniFat = NULL; - } + free ((*cfbd)->fat); + (*cfbd)->fat = NULL; - if ((*cfbd)->nodes != NULL) { - free ((*cfbd)->nodes); - (*cfbd)->nodes = NULL; - } + free ((*cfbd)->miniFat); + (*cfbd)->miniFat = NULL; - if ((*cfbd)->hdr != NULL) { - free ((*cfbd)->hdr); - (*cfbd)->hdr = NULL; - } + free ((*cfbd)->nodes); + (*cfbd)->nodes = NULL; + + free ((*cfbd)->hdr); + (*cfbd)->hdr = NULL; free (*cfbd); *cfbd = NULL; @@ -260,7 +257,9 @@ int cfb_load_file (CFB_Data** cfbd_p, const char* file) { CFB_Data* cfbd = *cfbd_p; - snprintf (cfbd->file, sizeof (((CFB_Data){ 0 }).file), "%s", file); + + // laaf_util_snprintf_realloc( &cfbd->file, NULL, 0, "%s", file ); + cfbd->file = laaf_util_absolute_path (file); if (cfb_openFile (cfbd) < 0) { cfb_release (cfbd_p); @@ -307,6 +306,11 @@ cfb_load_file (CFB_Data** cfbd_p, const char* file) return -1; } + // debug( "FAT size: %u", cfbd->fat_sz ); + // debug( "DiFAT size: %u", cfbd->DiFAT_sz ); + // debug( "MiniFAT size: %u", cfbd->miniFat_sz ); + // debug( "MiniFAT sector (%u) per FAT setor (%u): %u", (1 << cfbd->hdr->_uMiniSectorShift), (1 << cfbd->hdr->_uSectorShift), (1 << cfbd->hdr->_uSectorShift) / (1 << cfbd->hdr->_uMiniSectorShift) ); + return 0; } @@ -323,11 +327,13 @@ cfb_new_file (CFB_Data* cfbd, const char* file, int sectSize) cfbHeader* hdr = malloc (sizeof (cfbHeader)); - if (cfbd->hdr == NULL) { - error ("%s.", strerror (errno)); + if (!hdr) { + error ("Out of memory"); return -1; } + cfbd->hdr = hdr; + hdr->_abSig = 0xe11ab1a1e011cfd0; /* @@ -404,23 +410,36 @@ cfb_is_valid (CFB_Data* cfbd) static int cfb_getFileSize (CFB_Data* cfbd) { +#ifdef _WIN32 + if (_fseeki64 (cfbd->fp, 0L, SEEK_END) < 0) { + error ("fseek() failed : %s.", strerror (errno)); + return -1; + } + + __int64 filesz = _ftelli64 (cfbd->fp); + +#else if (fseek (cfbd->fp, 0L, SEEK_END) < 0) { error ("fseek() failed : %s.", strerror (errno)); return -1; } - cfbd->file_sz = ftell (cfbd->fp); + long filesz = ftell (cfbd->fp); - if ((long)cfbd->file_sz < 0) { +#endif + + if (filesz < 0) { error ("ftell() failed : %s.", strerror (errno)); return -1; } - if (cfbd->file_sz == 0) { + if (filesz == 0) { error ("File is empty (0 byte)."); return -1; } + cfbd->file_sz = (size_t)filesz; + return 0; } @@ -434,9 +453,28 @@ cfb_getFileSize (CFB_Data* cfbd) static int cfb_openFile (CFB_Data* cfbd) { - cfbd->fp = fopen (cfbd->file, "rb"); + if (!cfbd->file) { + return -1; + } - if (cfbd->fp == NULL) { +#ifdef _WIN32 + + wchar_t* wfile = laaf_util_windows_utf8toutf16 (cfbd->file); + + if (!wfile) { + error ("Unable to convert filepath to wide string : %s", cfbd->file); + return -1; + } + + cfbd->fp = _wfopen (wfile, L"rb"); + + free (wfile); + +#else + cfbd->fp = fopen (cfbd->file, "rb"); +#endif + + if (!cfbd->fp) { error ("%s.", strerror (errno)); return -1; } @@ -456,26 +494,42 @@ cfb_openFile (CFB_Data* cfbd) */ static uint64_t -cfb_readFile (CFB_Data* cfbd, unsigned char* buf, uint64_t offset, uint64_t len) +cfb_readFile (CFB_Data* cfbd, unsigned char* buf, size_t offset, size_t reqlen) { FILE* fp = cfbd->fp; - if (len + offset > cfbd->file_sz) { - error ("Requested data goes %" PRIu64 " bytes beyond the EOF : offset %" PRIu64 " | length %" PRIu64 "", (len + offset) - cfbd->file_sz, offset, len); + // debug( "Requesting file read @ offset %"PRIu64" of length %"PRIu64, offset, reqlen ); + + if (offset >= LONG_MAX) { + error ("Requested data offset is bigger than LONG_MAX"); return 0; } - int rc = fseek (fp, offset, SEEK_SET); + if (reqlen + offset > cfbd->file_sz) { + error ("Requested data goes %" PRIu64 " bytes beyond the EOF : offset %" PRIu64 " | length %" PRIu64 "", (reqlen + offset) - cfbd->file_sz, offset, reqlen); + return 0; + } + + int rc = fseek (fp, (long)offset, SEEK_SET); if (rc < 0) { error ("%s.", strerror (errno)); return 0; } - uint64_t byteRead = fread (buf, sizeof (unsigned char), len, fp); + size_t byteRead = fread (buf, sizeof (unsigned char), reqlen, fp); - if (byteRead < len) { - warning ("Could only retrieve %" PRIu64 " bytes out of %" PRIu64 " requested.", byteRead, len); + if (feof (fp)) { + if (byteRead < reqlen) { + error ("Incomplete fread() of CFB due to EOF : %" PRIu64 " bytes read out of %" PRIu64 " requested", byteRead, reqlen); + } + debug ("fread() : EOF reached in CFB file"); + } else if (ferror (fp)) { + if (byteRead < reqlen) { + error ("Incomplete fread() of CFB due to error : %" PRIu64 " bytes read out of %" PRIu64 " requested", byteRead, reqlen); + } else { + error ("fread() error of CFB : %" PRIu64 " bytes read out of %" PRIu64 " requested", byteRead, reqlen); + } } return byteRead; @@ -528,10 +582,10 @@ cfb_getSector (CFB_Data* cfbd, cfbSectorID_t id) uint64_t sectorSize = (1 << cfbd->hdr->_uSectorShift); uint64_t fileOffset = (id + 1) << cfbd->hdr->_uSectorShift; - unsigned char* buf = calloc (sectorSize, sizeof (unsigned char)); + unsigned char* buf = calloc (1, sectorSize); - if (buf == NULL) { - error ("%s.", strerror (errno)); + if (!buf) { + error ("Out of memory"); return NULL; } @@ -540,6 +594,8 @@ cfb_getSector (CFB_Data* cfbd, cfbSectorID_t id) return NULL; } + // laaf_util_dump_hex( buf, (1<hdr->_uSectorShift), &cfbd->log->_msg, &cfbd->log->_msg_size, cfbd->log->_msg_pos, "" ); + return buf; } @@ -568,13 +624,13 @@ cfb_getMiniSector (CFB_Data* cfbd, cfbSectorID_t id) return NULL; } - int MiniSectorSize = 1 << cfbd->hdr->_uMiniSectorShift; - int SectorSize = 1 << cfbd->hdr->_uSectorShift; + uint32_t SectorSize = 1 << cfbd->hdr->_uSectorShift; + uint32_t MiniSectorSize = 1 << cfbd->hdr->_uMiniSectorShift; - unsigned char* buf = calloc (MiniSectorSize, sizeof (unsigned char)); + unsigned char* buf = calloc (1, MiniSectorSize); - if (buf == NULL) { - error ("%s.", strerror (errno)); + if (!buf) { + error ("Out of memory"); return NULL; } @@ -583,11 +639,30 @@ cfb_getMiniSector (CFB_Data* cfbd, cfbSectorID_t id) uint64_t offset = 0; uint32_t i = 0; - /* Fat Divisor: allow to guess the number of mini-stream sectors per standard sector */ + // debug( "Requesting fatID: %u (%u)", fatId, id ); + + /* Fat Divisor: allow to guess the number of mini-stream sectors per standard FAT sector */ unsigned int fatDiv = SectorSize / MiniSectorSize; /* move forward in the FAT's mini-stream chain to retrieve the sector we want. */ + for (i = 0; i < id / fatDiv; i++) { + if (cfbd->fat[fatId] == 0) { + error ("Next FAT index (%i/%i) is null.", i, (id / fatDiv)); + goto err; + } + + if (cfbd->fat[fatId] >= CFB_MAX_REG_SID) { + error ("Next FAT index (%i/%i) is invalid: %u (%08x)", i, (id / fatDiv), cfbd->fat[fatId], cfbd->fat[fatId]); + goto err; + } + + if (cfbd->fat[fatId] >= cfbd->fat_sz) { + error ("Next FAT index (%i/%i) is bigger than FAT size (%u): %u (%08x)", i, (id / fatDiv), cfbd->fat_sz, cfbd->fat[fatId], cfbd->fat[fatId]); + goto err; + } + + // debug( "sectorCount: %i / %u fatId: %u", i, id/fatDiv, cfbd->fat[fatId] ); fatId = cfbd->fat[fatId]; } @@ -595,10 +670,16 @@ cfb_getMiniSector (CFB_Data* cfbd, cfbSectorID_t id) offset += ((id % fatDiv) << cfbd->hdr->_uMiniSectorShift); if (cfb_readFile (cfbd, buf, offset, MiniSectorSize) == 0) { - free (buf); - return NULL; + goto err; } + goto end; + +err: + free (buf); + buf = NULL; + +end: return buf; } @@ -615,23 +696,20 @@ cfb_getMiniSector (CFB_Data* cfbd, cfbSectorID_t id) uint64_t cfb_getStream (CFB_Data* cfbd, cfbNode* node, unsigned char** stream, uint64_t* stream_sz) { - // if ( node == NULL || node->_mse == STGTY_ROOT ) - // return; + if (node == NULL) { + return 0; + } - // Should not happen.. or could it ? - // if ( node->_ulSizeLow < 1 ) - // return; - - uint64_t stream_len = cfb_getNodeStreamLen (cfbd, node); //node->_ulSizeLow; + uint64_t stream_len = CFB_getNodeStreamLen (cfbd, node); if (stream_len == 0) { return 0; } - *stream = calloc (stream_len, sizeof (unsigned char)); + *stream = calloc (1, stream_len); - if (*stream == NULL) { - error ("%s.", strerror (errno)); + if (!(*stream)) { + error ("Out of memory"); return 0; } @@ -642,7 +720,7 @@ cfb_getStream (CFB_Data* cfbd, cfbNode* node, unsigned char** stream, uint64_t* if (stream_len < cfbd->hdr->_ulMiniSectorCutoff) { /* mini-stream */ - cfb_foreachMiniSectorInChain (cfbd, buf, id) + CFB_foreachMiniSectorInChain (cfbd, buf, id) { if (!buf) { free (*stream); @@ -659,7 +737,7 @@ cfb_getStream (CFB_Data* cfbd, cfbNode* node, unsigned char** stream, uint64_t* offset += (1 << cfbd->hdr->_uMiniSectorShift); } } else { - cfb_foreachSectorInChain (cfbd, buf, id) + CFB_foreachSectorInChain (cfbd, buf, id) { cpy_sz = ((stream_len - offset) < (uint64_t) (1 << cfbd->hdr->_uSectorShift)) ? (stream_len - offset) : (uint64_t) (1 << cfbd->hdr->_uSectorShift); @@ -681,7 +759,7 @@ cfb_getStream (CFB_Data* cfbd, cfbNode* node, unsigned char** stream, uint64_t* * Loops through all the sectors that compose a stream * and retrieve their content. * - * This function should be called through the macro cfb_foreachSectorInStream(). + * This function should be called through the macro CFB_foreachSectorInStream(). * * @param cfbd Pointer to the CFB_Data structure. * @param node Pointer to the Node that hold the stream. @@ -704,20 +782,14 @@ cfb__foreachSectorInStream (CFB_Data* cfbd, cfbNode* node, unsigned char** buf, if (*sectID >= CFB_MAX_REG_SID) return 0; - /* is this possible ? */ - // if ( node->_ulSizeLow < 1 ) - // return 0; - /* free the previously allocated buf, if any */ - if (*buf != NULL) { - free (*buf); - *buf = NULL; - } + free (*buf); + *buf = NULL; /* if *nodeID == 0, then it is the first function call */ *sectID = (*sectID == 0) ? node->_sectStart : *sectID; - size_t stream_sz = cfb_getNodeStreamLen (cfbd, node); + size_t stream_sz = CFB_getNodeStreamLen (cfbd, node); if (stream_sz < cfbd->hdr->_ulMiniSectorCutoff) { /* Mini-Stream */ @@ -731,12 +803,6 @@ cfb__foreachSectorInStream (CFB_Data* cfbd, cfbNode* node, unsigned char** buf, *sectID = cfbd->fat[*sectID]; } - // trim data length to match the EXACT stream size - - // if ( *sectID >= CFB_MAX_REG_SECT ) - // *bytesRead = ( stream_sz % *bytesRead ); - // *bytesRead = ( stream_sz % *bytesRead ); - return 1; } @@ -753,26 +819,36 @@ cfb__foreachSectorInStream (CFB_Data* cfbd, cfbNode* node, unsigned char** buf, static int cfb_retrieveFileHeader (CFB_Data* cfbd) { - cfbd->hdr = calloc (sizeof (cfbHeader), sizeof (unsigned char)); + cfbd->hdr = calloc (1, sizeof (cfbHeader)); - if (cfbd->hdr == NULL) { - error ("%s.", strerror (errno)); + if (!cfbd->hdr) { + error ("Out of memory"); return -1; } if (cfb_readFile (cfbd, (unsigned char*)cfbd->hdr, 0, sizeof (cfbHeader)) == 0) { - free (cfbd->hdr); - cfbd->hdr = NULL; - return -1; + goto err; + } + + if (cfbd->hdr->_uSectorShift != 9 && + cfbd->hdr->_uSectorShift != 12) { + goto err; } return 0; + +err: + free (cfbd->hdr); + cfbd->hdr = NULL; + + return -1; } static int cfb_retrieveDiFAT (CFB_Data* cfbd) { cfbSectorID_t* DiFAT = NULL; + unsigned char* buf = NULL; /* * Check DiFAT properties in header. @@ -782,13 +858,18 @@ cfb_retrieveDiFAT (CFB_Data* cfbd) cfbSectorID_t csectDif = 0; if (cfbd->hdr->_csectFat > 109) { - csectDif = ceil ((float)((cfbd->hdr->_csectFat - 109) * 4) / (1 << cfbd->hdr->_uSectorShift)); + double csectDifdouble = ceil ((float)((cfbd->hdr->_csectFat - 109) * 4) / (1 << cfbd->hdr->_uSectorShift)); + + if (csectDifdouble >= UINT_MAX || csectDifdouble < 0) { + warning ("Calculated csectDif is negative or bigger than UINT_MAX"); + // return -1; + } + + csectDif = (cfbSectorID_t)csectDifdouble; } if (csectDif != cfbd->hdr->_csectDif) { - warning ("cfbd->hdr->_csectDif value seems wrong (%u)", cfbd->hdr->_csectDif); - // warning( "cfbd->hdr->_csectDif value seems wrong (%u). Correcting from cfbd->hdr->_csectFat.", cfbd->hdr->_csectDif ); - // cfbd->hdr->_csectDif = csectDif; + warning ("cfbd->hdr->_csectDif value (%u) does not match calculated csectDif (%u)", cfbd->hdr->_csectDif, csectDif); } if (csectDif == 0 && cfbd->hdr->_sectDifStart != CFB_END_OF_CHAIN) { @@ -798,14 +879,20 @@ cfb_retrieveDiFAT (CFB_Data* cfbd) /* * DiFAT size is the number of FAT sector entries in the DiFAT chain. + * _uSectorShift is guaranted to be 9 or 12, so DiFAT_sz will never override UINT_MAX */ - uint32_t DiFAT_sz = (cfbd->hdr->_csectDif) * (((1 << cfbd->hdr->_uSectorShift) / sizeof (cfbSectorID_t)) - 1) + 109; + size_t DiFAT_sz = cfbd->hdr->_csectDif * (((1 << cfbd->hdr->_uSectorShift) / sizeof (cfbSectorID_t)) - 1) + 109; + + if (DiFAT_sz >= UINT_MAX) { + error ("DiFAT size is bigger than UINT_MAX : %lu", DiFAT_sz); + return -1; + } DiFAT = calloc (DiFAT_sz, sizeof (cfbSectorID_t)); - if (DiFAT == NULL) { - error ("%s.", strerror (errno)); + if (!DiFAT) { + error ("Out of memory"); return -1; } @@ -816,22 +903,24 @@ cfb_retrieveDiFAT (CFB_Data* cfbd) memcpy (DiFAT, cfbd->hdr->_sectFat, 109 * sizeof (cfbSectorID_t)); - unsigned char* buf = NULL; - cfbSectorID_t id = 0; //cfbd->hdr->_sectDifStart; - uint64_t offset = 109 * sizeof (cfbSectorID_t); + cfbSectorID_t id = 0; + uint64_t offset = 109 * sizeof (cfbSectorID_t); uint64_t cnt = 0; - cfb_foreachSectorInDiFATChain (cfbd, buf, id) + /* _uSectorShift is guaranted to be 9 or 12, so sectorSize will never be negative */ + uint32_t sectorSize = (1U << cfbd->hdr->_uSectorShift) - 4U; + + CFB_foreachSectorInDiFATChain (cfbd, buf, id) { if (buf == NULL) { error ("Error retrieving sector %u (0x%08x) out of the DiFAT chain.", id, id); - return -1; + goto err; } - memcpy ((unsigned char*)DiFAT + offset, buf, (1 << cfbd->hdr->_uSectorShift) - 4); + memcpy ((unsigned char*)DiFAT + offset, buf, sectorSize); - offset += (1 << cfbd->hdr->_uSectorShift) - 4; + offset += sectorSize; cnt++; /* @@ -845,6 +934,7 @@ cfb_retrieveDiFAT (CFB_Data* cfbd) } free (buf); + buf = NULL; /* * Standard says DIFAT should end with a CFB_END_OF_CHAIN index, @@ -855,9 +945,15 @@ cfb_retrieveDiFAT (CFB_Data* cfbd) warning ("Incorrect end of DiFAT Chain 0x%08x (%d)", id, id); cfbd->DiFAT = DiFAT; - cfbd->DiFAT_sz = DiFAT_sz; + cfbd->DiFAT_sz = (uint32_t)DiFAT_sz; return 0; + +err: + free (DiFAT); + free (buf); + + return -1; } /** @@ -872,12 +968,12 @@ static int cfb_retrieveFAT (CFB_Data* cfbd) { cfbSectorID_t* FAT = NULL; - uint64_t FAT_sz = (((cfbd->hdr->_csectFat) * (1 << cfbd->hdr->_uSectorShift))) / sizeof (cfbSectorID_t); + uint32_t FAT_sz = (((cfbd->hdr->_csectFat) * (1 << cfbd->hdr->_uSectorShift))) / sizeof (cfbSectorID_t); FAT = calloc (FAT_sz, sizeof (cfbSectorID_t)); - if (FAT == NULL) { - error ("%s.", strerror (errno)); + if (!FAT) { + error ("Out of memory"); return -1; } @@ -888,11 +984,13 @@ cfb_retrieveFAT (CFB_Data* cfbd) cfbSectorID_t id = 0; uint64_t offset = 0; - cfb_foreachFATSectorIDInDiFAT (cfbd, id) + CFB_foreachFATSectorIDInDiFAT (cfbd, id) { if (cfbd->DiFAT[id] == CFB_FREE_SECT) continue; + // debug( "cfbd->DiFAT[id]: %u", cfbd->DiFAT[id] ); + /* observed in fairlight's AAFs.. */ if (cfbd->DiFAT[id] == 0x00000000 && id > 0) { warning ("Got a NULL FAT index in the DiFAT @ %u, should be CFB_FREE_SECT.", id); @@ -901,6 +999,8 @@ cfb_retrieveFAT (CFB_Data* cfbd) buf = cfb_getSector (cfbd, cfbd->DiFAT[id]); + // laaf_util_dump_hex( buf, (1<hdr->_uSectorShift), &cfbd->log->_msg, &cfbd->log->_msg_size, cfbd->log->_msg_pos, "" ); + if (buf == NULL) { error ("Error retrieving FAT sector %u (0x%08x).", id, id); return -1; @@ -926,12 +1026,12 @@ cfb_retrieveFAT (CFB_Data* cfbd) static int cfb_retrieveMiniFAT (CFB_Data* cfbd) { - uint64_t miniFat_sz = cfbd->hdr->_csectMiniFat * (1 << cfbd->hdr->_uSectorShift) / sizeof (cfbSectorID_t); + uint32_t miniFat_sz = cfbd->hdr->_csectMiniFat * (1 << cfbd->hdr->_uSectorShift) / sizeof (cfbSectorID_t); cfbSectorID_t* miniFat = calloc (miniFat_sz, sizeof (cfbSectorID_t)); - if (miniFat == NULL) { - error ("%s.", strerror (errno)); + if (!miniFat) { + error ("Out of memory"); return -1; } @@ -939,7 +1039,7 @@ cfb_retrieveMiniFAT (CFB_Data* cfbd) cfbSectorID_t id = cfbd->hdr->_sectMiniFatStart; uint64_t offset = 0; - cfb_foreachSectorInChain (cfbd, buf, id) + CFB_foreachSectorInChain (cfbd, buf, id) { if (buf == NULL) { error ("Error retrieving MiniFAT sector %u (0x%08x).", id, id); @@ -986,8 +1086,8 @@ cfb_retrieveNodes (CFB_Data* cfbd) cfbNode* node = calloc (cfbd->nodes_cnt, sizeof (cfbNode)); - if (node == NULL) { - error ("%s.", strerror (errno)); + if (!node) { + error ("Out of memory"); return -1; } @@ -997,7 +1097,7 @@ cfb_retrieveNodes (CFB_Data* cfbd) if (cfbd->hdr->_uSectorShift == 9) { /* 512 bytes sectors */ - cfb_foreachSectorInChain (cfbd, buf, id) + CFB_foreachSectorInChain (cfbd, buf, id) { if (buf == NULL) { error ("Error retrieving Directory sector %u (0x%08x).", id, id); @@ -1013,7 +1113,7 @@ cfb_retrieveNodes (CFB_Data* cfbd) } } else if (cfbd->hdr->_uSectorShift == 12) { /* 4096 bytes sectors */ - cfb_foreachSectorInChain (cfbd, buf, id) + CFB_foreachSectorInChain (cfbd, buf, id) { if (buf == NULL) { error ("Error retrieving Directory sector %u (0x%08x).", id, id); @@ -1059,10 +1159,12 @@ cfb_retrieveNodes (CFB_Data* cfbd) /* handle non-standard sector size, that is different than 512B or 4kB */ /* TODO has not been tested yet, should not even exist anyway */ - warning ("Parsing non-standard sector size !!! (%u bytes)", (1 << cfbd->hdr->_uSectorShift)) - uint32_t nodesPerSect = (1 << cfbd->hdr->_uMiniSectorShift) / sizeof (cfbNode); + warning ("Parsing non-standard sector size !!! (%u bytes)", (1 << cfbd->hdr->_uSectorShift)); - cfb_foreachSectorInChain (cfbd, buf, id) + /* _uSectorShift is guaranted to be 9 or 12, so nodesPerSect will never override UINT_MAX */ + uint32_t nodesPerSect = (1U << cfbd->hdr->_uMiniSectorShift) / sizeof (cfbNode); + + CFB_foreachSectorInChain (cfbd, buf, id) { if (buf == NULL) { error ("Error retrieving Directory sector %u (0x%08x).", id, id); @@ -1083,42 +1185,25 @@ cfb_retrieveNodes (CFB_Data* cfbd) } /** - * Converts 16-bits MS/CFB wchar_t to system wchar_t. + * Converts UTF-16 to UTF-8. * - * @param buf Pointer to wchar_t output buffer. If NULL, then function will allocate a new buffer. - * @param w16buf Pointer to a 16-bits MS/CFB "wchar_t" array. - * @param w16blen Size of the w16buf array in bytes, including the NULL. If it is set to - * CFB_W16TOWCHAR_STRLEN, then function will parse w16buf up to NULL to retrieve w16buf byte size + * @param w16buf Pointer to a NULL terminated uint16_t UTF-16 array. + * @param w16blen Size of the w16buf array in bytes * - * @return Pointer to buf,\n + * @return New allocated buffer with UTF-8 string\n * NULL on failure. */ -wchar_t* -cfb_w16towchar (wchar_t* buf, uint16_t* w16buf, size_t w16blen) +char* +cfb_w16toUTF8 (const uint16_t* w16buf, size_t w16blen) { - if (w16buf == NULL) + (void)w16blen; + + if (!w16buf) { return NULL; - - if (w16blen == CFB_W16TOWCHAR_STRLEN) { - w16blen = 0; - while (w16buf[w16blen >> 1] != 0x0000) { - w16blen += sizeof (uint16_t); - } - w16blen += sizeof (uint16_t); /* NULL termination */ } - if (buf == NULL) { - buf = malloc (w16blen * sizeof (wchar_t)); - if (buf == NULL) - return NULL; - } - - for (size_t i = 0; i < w16blen >> 1; i++) { - buf[i] = ((uint16_t*)w16buf)[i]; - } - - return buf; + return laaf_util_utf16Toutf8 (w16buf); } /** @@ -1134,7 +1219,7 @@ cfb_w16towchar (wchar_t* buf, uint16_t* w16buf, size_t w16blen) */ cfbNode* -cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) +cfb_getNodeByPath (CFB_Data* cfbd, const char* path, cfbSID_t id) { /* * begining of the first function call. @@ -1149,20 +1234,27 @@ cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) * work either with or without "/Root Entry" */ - if (wcsncmp (path, L"/Root Entry", 11) != 0) { + if (strncmp (path, "/Root Entry", 11) != 0) { id = cfbd->nodes[0]._sidChild; } } - uint32_t l = 0; - /* * retrieves the first node's name from path */ - for (l = 0; l < wcslen (path); l++) - if (l > 0 && path[l] == '/') + uint32_t nameLen = 0; + + for (nameLen = 0; nameLen < strlen (path); nameLen++) { + if (nameLen == UINT_MAX) { + error ("Name length is bigger than UINT_MAX"); + return NULL; + } + + if (nameLen > 0 && path[nameLen] == '/') { break; + } + } /* * removes any leading '/' @@ -1170,10 +1262,17 @@ cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) if (path[0] == '/') { path++; - l--; + nameLen--; } - wchar_t ab[CFB_NODE_NAME_SZ]; + size_t nameUTF16Len = (nameLen + 1) << 1; + + if (nameUTF16Len >= INT_MAX) { + error ("Name length is bigger than INT_MAX"); + return NULL; + } + + char* ab = NULL; while (1) { if (id >= cfbd->nodes_cnt) { @@ -1181,16 +1280,17 @@ cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) return NULL; } - // laaf_util_dump_hex( cfbd->nodes[id]->_ab, cfbd->nodes[id]->_cb ); + ab = cfb_w16toUTF8 (cfbd->nodes[id]._ab, cfbd->nodes[id]._cb); - cfb_w16towchar (ab, cfbd->nodes[id]._ab, cfbd->nodes[id]._cb); + int rc = 0; - int32_t rc = 0; + if (strlen (ab) == nameLen) + rc = strncmp (path, ab, nameLen); + else { + rc = (int)nameUTF16Len - cfbd->nodes[id]._cb; + } - if (wcslen (ab) == l) - rc = wcsncmp (path, ab, l); - else - rc = l - wcslen (ab); + free (ab); /* * Some node in the path was found. @@ -1201,7 +1301,7 @@ cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) * get full path length minus any terminating '/' */ - uint32_t pathLen = wcslen (path); + size_t pathLen = strlen (path); if (path[pathLen - 1] == '/') pathLen--; @@ -1212,10 +1312,10 @@ cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) * to next node in the path. */ - if (pathLen == l) + if (pathLen == nameLen) return &cfbd->nodes[id]; else - return cfb_getNodeByPath (cfbd, path + l, cfbd->nodes[id]._sidChild); + return cfb_getNodeByPath (cfbd, path + nameLen, cfbd->nodes[id]._sidChild); } else if (rc > 0) id = cfbd->nodes[id]._sidRightSib; else if (rc < 0) @@ -1239,16 +1339,23 @@ cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* path, cfbSID_t id) */ cfbNode* -cfb_getChildNode (CFB_Data* cfbd, const wchar_t* name, cfbNode* startNode) +cfb_getChildNode (CFB_Data* cfbd, const char* name, cfbNode* startNode) { - int32_t rc = 0; + int rc = 0; - /** @TODO : cfb_getIDByNode should be quiker (macro ?) */ cfbSID_t id = cfb_getIDByNode (cfbd, &cfbd->nodes[startNode->_sidChild]); - uint32_t nameUTF16Len = ((wcslen (name) + 1) << 1); + if (id == UINT_MAX) { + error ("Could not retrieve id by node"); + return NULL; + } - wchar_t nodename[CFB_NODE_NAME_SZ]; + size_t nameUTF16Len = ((strlen (name) + 1) << 1); + + if (nameUTF16Len >= INT_MAX) { + error ("Name length is bigger than INT_MAX"); + return NULL; + } while (1) { if (id >= cfbd->nodes_cnt) { @@ -1256,13 +1363,15 @@ cfb_getChildNode (CFB_Data* cfbd, const wchar_t* name, cfbNode* startNode) return NULL; } - cfb_w16towchar (nodename, cfbd->nodes[id]._ab, cfbd->nodes[id]._cb); + char* nodename = cfb_w16toUTF8 (cfbd->nodes[id]._ab, cfbd->nodes[id]._cb); if (cfbd->nodes[id]._cb == nameUTF16Len) - rc = wcscmp (name, nodename); - else - rc = nameUTF16Len - cfbd->nodes[id]._cb; + rc = strcmp (name, nodename); + else { + rc = (int)nameUTF16Len - cfbd->nodes[id]._cb; + } + free (nodename); /* * Node found */ @@ -1310,7 +1419,7 @@ cfb_getIDByNode (CFB_Data* cfbd, cfbNode* node) } } - return -1; + return UINT_MAX; } /** @@ -1324,7 +1433,7 @@ cfb_getIDByNode (CFB_Data* cfbd, cfbNode* node) static cfbSID_t getNodeCount (CFB_Data* cfbd) { - uint64_t cnt = (1 << cfbd->hdr->_uSectorShift); + uint32_t cnt = (1 << cfbd->hdr->_uSectorShift); cfbSectorID_t id = cfbd->hdr->_sectDirStart; while (id < CFB_MAX_REG_SID) { diff --git a/libs/aaf/MediaComposer.c b/libs/aaf/MediaComposer.c new file mode 100644 index 0000000000..50695b7dbf --- /dev/null +++ b/libs/aaf/MediaComposer.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024 Adrien Gesta-Fline + * + * This file is part of libAAF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "aaf/AAFDefs/AAFPropertyIDs.h" +#include "aaf/AAFDefs/AAFTypeDefUIDs.h" +#include "aaf/AAFIParser.h" +#include "aaf/AAFToText.h" + +#include "aaf/libaaf.h" +#include "aaf/log.h" + +#define debug(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + +#define warning(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + +#define error(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) + +int +mediaComposer_AAF (struct AAF_Iface* aafi) +{ + int probe = 0; + + if (aafi->aafd->Identification.CompanyName && strncmp (aafi->aafd->Identification.CompanyName, "Avid Technology, Inc.", strlen ("Avid Technology, Inc.")) == 0) { + probe++; + } + + if (aafi->aafd->Identification.ProductName && strncmp (aafi->aafd->Identification.ProductName, "Avid Media Composer", strlen ("Avid Media Composer")) == 0) { + probe++; + } + + if (probe == 2) { + return 1; + } + + return 0; +} diff --git a/libs/aaf/ProTools.c b/libs/aaf/ProTools.c index df1227c538..88ef808bf9 100644 --- a/libs/aaf/ProTools.c +++ b/libs/aaf/ProTools.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -23,81 +23,70 @@ #include "aaf/AAFIface.h" #include "aaf/ProTools.h" -#define PROTOOLS_CLIP_NAME_FADE_EN_LEN 5 // +1 -#define PROTOOLS_CLIP_NAME_FADE_DE_LEN 5 // +1 -#define PROTOOLS_CLIP_NAME_FADE_JA_LEN 5 // +1 -#define PROTOOLS_CLIP_NAME_FADE_FR_LEN 6 // +1 -#define PROTOOLS_CLIP_NAME_FADE_ES_LEN 8 // +1 -#define PROTOOLS_CLIP_NAME_FADE_ZH_CN_LEN 3 // +1 -#define PROTOOLS_CLIP_NAME_FADE_ZH_TW_LEN 3 // +1 -#define PROTOOLS_CLIP_NAME_FADE_KO_LEN 3 // +1 - -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_EN_LEN 20 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_DE_LEN 24 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ES_LEN 32 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_FR_LEN 33 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_JA_LEN 8 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_CN_LEN 6 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_TW_LEN 6 // +1 -#define PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_KO_LEN 11 // +1 - /* English : "Fade " (Same as JA and DE) */ -static const wchar_t PROTOOLS_CLIP_NAME_FADE_EN[] = L"\x0046\x0061\x0064\x0065\x0020\x0000"; -/* German : "Fade " (Same as JA and EN) */ -// static const wchar_t PROTOOLS_CLIP_NAME_FADE_DE[] = L"\x0046\x0061\x0064\x0065\x0020\x0000"; -/* Japanese : "Fade " (Same as EN and DE) */ -// static const wchar_t PROTOOLS_CLIP_NAME_FADE_JA[] = L"\x0046\x0061\x0064\x0065\x0020\x0000"; +static const char PROTOOLS_CLIP_NAME_FADE_EN[] = "\x46\x61\x64\x65\x20"; /* French : "Fondu " */ -static const wchar_t PROTOOLS_CLIP_NAME_FADE_FR[] = L"\x0046\x006f\x006e\x0064\x0075\x0020\x0000"; +static const char PROTOOLS_CLIP_NAME_FADE_FR[] = "\x46\x6f\x6e\x64\x75\x20"; /* Spanish : "Fundido" */ -static const wchar_t PROTOOLS_CLIP_NAME_FADE_ES[] = L"\x0046\x0075\x006e\x0064\x0069\x0064\x006f\x0020\x0000"; -/* Chinese (S) : "淡变 " */ -static const wchar_t PROTOOLS_CLIP_NAME_FADE_ZH_CN[] = L"\x6de1\x53d8\x0020\x0000"; -/* Chinese (T) : "淡變 " */ -static const wchar_t PROTOOLS_CLIP_NAME_FADE_ZH_TW[] = L"\x6de1\x8b8a\x0020\x0000"; +static const char PROTOOLS_CLIP_NAME_FADE_ES[] = "\x46\x75\x6e\x64\x69\x64\x6f\x20"; /* Korean : "페이드" */ -static const wchar_t PROTOOLS_CLIP_NAME_FADE_KO[] = L"\xd398\xc774\xb4dc\x0000"; +static const char PROTOOLS_CLIP_NAME_FADE_KO[] = "\xed\x8e\x98\xec\x9d\xb4\xeb\x93\x9c"; +/* Chinese (S) : "淡变 " */ +static const char PROTOOLS_CLIP_NAME_FADE_ZH_CN[] = "\xe6\xb7\xa1\xe5\x8f\x98\x20"; +/* Chinese (T) : "淡變 " */ +static const char PROTOOLS_CLIP_NAME_FADE_ZH_TW[] = "\xe6\xb7\xa1\xe8\xae\x8a\x20"; /* English : "Sample accurate edit" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_EN[] = L"\x0053\x0061\x006d\x0070\x006c\x0065\x0020\x0061\x0063\x0063\x0075\x0072\x0061\x0074\x0065\x0020\x0065\x0064\x0069\x0074\x0000"; +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_EN[] = "\x53\x61\x6d\x70\x6c\x65\x20\x61\x63\x63\x75\x72\x61\x74\x65\x20\x65\x64\x69\x74"; /* German : "Samplegenaue Bearbeitung" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_DE[] = L"\x0053\x0061\x006d\x0070\x006c\x0065\x0067\x0065\x006e\x0061\x0075\x0065\x0020\x0042\x0065\x0061\x0072\x0062\x0065\x0069\x0074\x0075\x006e\x0067\x0000"; +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_DE[] = "\x53\x61\x6d\x70\x6c\x65\x67\x65\x6e\x61\x75\x65\x20\x42\x65\x61\x72\x62\x65\x69\x74\x75\x6e\x67"; /* Spanish : "Edición con precisión de muestra" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ES[] = L"\x0045\x0064\x0069\x0063\x0069\x00f3\x006e\x0020\x0063\x006f\x006e\x0020\x0070\x0072\x0065\x0063\x0069\x0073\x0069\x00f3\x006e\x0020\x0064\x0065\x0020\x006d\x0075\x0065\x0073\x0074\x0072\x0061\x0000"; +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ES[] = "\x45\x64\x69\x63\x69\xc3\xb3\x6e\x20\x63\x6f\x6e\x20\x70\x72\x65\x63\x69\x73\x69\xc3\xb3\x6e\x20\x64\x65\x20\x6d\x75\x65\x73\x74\x72\x61"; /* French : "Modification à l'échantillon près" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_FR[] = L"\x004d\x006f\x0064\x0069\x0066\x0069\x0063\x0061\x0074\x0069\x006f\x006e\x0020\x00e0\x0020\x006c\x0027\x00e9\x0063\x0068\x0061\x006e\x0074\x0069\x006c\x006c\x006f\x006e\x0020\x0070\x0072\x00e8\x0073\x0000"; +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_FR[] = "\x4d\x6f\x64\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\xc3\xa0\x20\x6c\x27\xc3\xa9\x63\x68\x61\x6e\x74\x69\x6c\x6c\x6f\x6e\x20\x70\x72\xc3\xa8\x73"; /* Japanese : "サンプル精度編集" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_JA[] = L"\x30b5\x30f3\x30d7\x30eb\x7cbe\x5ea6\x7de8\x96c6\x0000"; -/* Chinese (S) : "精确采样编辑" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_CN[] = L"\x7cbe\x786e\x91c7\x6837\x7f16\x8f91\x0000"; -/* Chinese (T) : "精確取樣編輯" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_TW[] = L"\x7cbe\x78ba\x53d6\x6a23\x7de8\x8f2f\x0000"; +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_JA[] = "\xe3\x82\xb5\xe3\x83\xb3\xe3\x83\x97\xe3\x83\xab\xe7\xb2\xbe\xe5\xba\xa6\xe7\xb7\xa8\xe9\x9b\x86"; /* Korean : "샘플 단위 정밀 편집" */ -static const wchar_t PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_KO[] = L"\xc0d8\xd50c\x0020\xb2e8\xc704\x0020\xc815\xbc00\x0020\xd3b8\xc9d1\x0000"; +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_KO[] = "\xec\x83\x98\xed\x94\x8c\x20\xeb\x8b\xa8\xec\x9c\x84\x20\xec\xa0\x95\xeb\xb0\x80\x20\xed\x8e\xb8\xec\xa7\x91"; +/* Chinese (S) : "精确采样编辑" */ +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_CN[] = "\xe7\xb2\xbe\xe7\xa1\xae\xe9\x87\x87\xe6\xa0\xb7\xe7\xbc\x96\xe8\xbe\x91"; +/* Chinese (T) : "精確取樣編輯" */ +static const char PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_TW[] = "\xe7\xb2\xbe\xe7\xa2\xba\xe5\x8f\x96\xe6\xa8\xa3\xe7\xb7\xa8\xe8\xbc\xaf"; + +#define debug(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + +#define warning(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + +#define error(...) \ + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) static int -is_rendered_fade (const wchar_t* clipName); +is_rendered_fade (const char* clipName); static int -is_sample_accurate_edit (const wchar_t* clipName); +is_sample_accurate_edit (const char* clipName); static int -replace_clipfade_with_fade (AAF_Iface* aafi, aafiTimelineItem* Item); +remove_sampleAccurateEditClip (AAF_Iface* aafi, aafiAudioTrack* audioTrack, aafiTimelineItem* saeItem); +static int +replace_clipFade (AAF_Iface* aafi, aafiAudioTrack* audioTrack, aafiTimelineItem* fadeItem); int protools_AAF (struct AAF_Iface* aafi) { int probe = 0; - /* TODO: CompanyName is "Digidesign, Inc." in ProTools 10.3.10.613 AAF, but what about since ? */ + /* NOTE: CompanyName is "Digidesign, Inc." at least since ProTools 10.3.10.613, and still today */ - // if ( aafi->aafd->Identification.CompanyName && wcscmp( aafi->aafd->Identification.CompanyName, L"Digidesign, Inc." ) == 0 ) { - // probe++; - // } - - if (aafi->aafd->Identification.ProductName && wcscmp (aafi->aafd->Identification.ProductName, L"ProTools") == 0) { + if (aafi->aafd->Identification.CompanyName && strcmp (aafi->aafd->Identification.CompanyName, "Digidesign, Inc.") == 0) { probe++; } - if (probe == 1) { + if (aafi->aafd->Identification.ProductName && strcmp (aafi->aafd->Identification.ProductName, "ProTools") == 0) { + probe++; + } + + if (probe == 2) { return 1; } @@ -105,131 +94,291 @@ protools_AAF (struct AAF_Iface* aafi) } static int -is_rendered_fade (const wchar_t* clipName) +is_rendered_fade (const char* clipName) { - return (memcmp (clipName, PROTOOLS_CLIP_NAME_FADE_EN, PROTOOLS_CLIP_NAME_FADE_EN_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_FADE_ES, PROTOOLS_CLIP_NAME_FADE_ES_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_FADE_FR, PROTOOLS_CLIP_NAME_FADE_FR_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_FADE_ZH_CN, PROTOOLS_CLIP_NAME_FADE_ZH_CN_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_FADE_ZH_TW, PROTOOLS_CLIP_NAME_FADE_ZH_TW_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_FADE_KO, PROTOOLS_CLIP_NAME_FADE_KO_LEN) == 0); + return (strcmp (clipName, PROTOOLS_CLIP_NAME_FADE_EN) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_FADE_ES) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_FADE_FR) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_FADE_ZH_CN) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_FADE_ZH_TW) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_FADE_KO) == 0); } static int -is_sample_accurate_edit (const wchar_t* clipName) +is_sample_accurate_edit (const char* clipName) { - return (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_EN, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_EN_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_DE, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_DE_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ES, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ES_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_FR, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_FR_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_JA, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_JA_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_CN, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_CN_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_TW, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_TW_LEN) == 0) || - (memcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_KO, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_KO_LEN) == 0); + return (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_EN) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_DE) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ES) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_FR) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_JA) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_CN) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_ZH_TW) == 0) || + (strcmp (clipName, PROTOOLS_CLIP_NAME_SAMPLE_ACCURATE_EDIT_KO) == 0); } static int -replace_clipfade_with_fade (AAF_Iface* aafi, aafiTimelineItem* Item) +remove_sampleAccurateEditClip (AAF_Iface* aafi, aafiAudioTrack* audioTrack, aafiTimelineItem* saeItem) { - if (Item->type != AAFI_AUDIO_CLIP) { - return -1; - } + /* + * Note: In this function, we assume we need to expand a clip to remove an + * attached sample accurate edit. TODO: Ensure it's always possible with ProTools + */ - aafiAudioClip* audioClip = (aafiAudioClip*)Item->data; + aafiAudioClip* saeClip = saeItem->data; - aafPosition_t currentpos = audioClip->pos; - aafPosition_t currentlen = audioClip->len; + if (saeItem->prev) { + if (saeItem->prev->type == AAFI_AUDIO_CLIP) { + aafiAudioClip* leftClip = saeItem->prev->data; - aafiTimelineItem* transItem = calloc (sizeof (aafiTimelineItem) + sizeof (aafiTransition), sizeof (char)); + if (saeClip->pos == (leftClip->pos + leftClip->len)) { + aafPosition_t essenceLength = aafi_convertUnit (leftClip->essencePointerList->essenceFile->length, leftClip->essencePointerList->essenceFile->samplerateRational, leftClip->track->edit_rate); - memset (transItem, 0x00, sizeof (aafiTimelineItem) + sizeof (aafiTransition)); + if ((essenceLength - leftClip->essence_offset - leftClip->len) >= saeClip->len) { + debug ("Removing SAE \"%s\" : left clip \"%s\" goes from length %" PRIi64 " to %" PRIi64, + saeClip->essencePointerList->essenceFile->unique_name, + leftClip->essencePointerList->essenceFile->unique_name, + leftClip->len, + leftClip->len + saeClip->len); - transItem->type = AAFI_TRANS; - transItem->next = NULL; - transItem->prev = NULL; + leftClip->len += saeClip->len; - transItem->data = calloc (sizeof (aafiTransition), sizeof (char)); + aafi_removeTimelineItem (aafi, saeItem); - aafiTransition* trans = transItem->data; - - trans->len = audioClip->len; - trans->flags = AAFI_INTERPOL_NONE; - - // debug( "%ls", audioClip->Essence->unique_file_name ); - - aafiAudioClip* prevClip = NULL; - aafiAudioClip* nextClip = NULL; - - if (Item->prev != NULL) { - if (Item->prev->type == AAFI_AUDIO_CLIP) { - prevClip = (aafiAudioClip*)Item->prev->data; - - // debug( "PREVIOUS POS %lu", prevClip->pos + prevClip->len ); - // debug( "CURENT POS %lu", currentpos ); - - if (prevClip->pos + prevClip->len < currentpos - 1) { - prevClip = NULL; + audioTrack->clipCount--; + return 1; + } + // else { + // warning( L"Can't remove SAE \"%s\" : left clip \"%s\" has not enough right handle : %lu but %lu is required", + // saeClip->essencePointerList->essenceFile->unique_name, + // leftClip->essencePointerList->essenceFile->unique_name, + // (essenceLength - leftClip->essence_offset - leftClip->len), + // saeClip->len ); + // } } } } - if (Item->next != NULL) { - if (Item->next->type == AAFI_AUDIO_CLIP) { - nextClip = (aafiAudioClip*)Item->next->data; + if (saeItem->next) { + if (saeItem->next->type == AAFI_AUDIO_CLIP) { + aafiAudioClip* rightClip = saeItem->next->data; - if (is_sample_accurate_edit (nextClip->essencePointerList->essence->file_name)) { - if (Item->next->next != NULL) { - nextClip = (aafiAudioClip*)Item->next->next->data; + if ((saeClip->pos + saeClip->len) == rightClip->pos) { + if (rightClip->essence_offset >= saeClip->len) { + debug ("Removing SAE \"%s\" : right clip \"%s\" goes from length: %" PRIi64 " to %" PRIi64 ", pos: %" PRIi64 " to %" PRIi64 ", source offset: %" PRIi64 " to %" PRIi64, + saeClip->essencePointerList->essenceFile->unique_name, + rightClip->essencePointerList->essenceFile->unique_name, + rightClip->len, + rightClip->len + saeClip->len, + rightClip->pos, + rightClip->pos - saeClip->len, + rightClip->essence_offset, + rightClip->essence_offset - saeClip->len); - // debug( "NEXT POS %lu", nextClip->pos ); - // debug( "CURENT POS %lu", currentpos + currentlen ); + rightClip->pos -= saeClip->len; + rightClip->len += saeClip->len; + rightClip->essence_offset -= saeClip->len; - if (nextClip->pos != currentpos + currentlen + 1) { + aafi_removeTimelineItem (aafi, saeItem); + + audioTrack->clipCount--; + return 1; + } + // else { + // warning( L"Can't remove SAE \"%s\" : right clip \"%s\" has not enough left handle : %lu but %lu is required", + // saeClip->essencePointerList->essenceFile->unique_name, + // rightClip->essencePointerList->essenceFile->unique_name, + // rightClip->essence_offset, + // saeClip->len ); + // } + } + } + } + + return 0; +} + +static int +replace_clipFade (AAF_Iface* aafi, aafiAudioTrack* audioTrack, aafiTimelineItem* fadeItem) +{ + aafiAudioClip* fadeClip = fadeItem->data; + + aafiTimelineItem* prevItem1 = fadeItem->prev; + aafiTimelineItem* prevItem2 = (prevItem1 && prevItem1->prev) ? prevItem1->prev : NULL; + + aafiTimelineItem* nextItem1 = fadeItem->next; + aafiTimelineItem* nextItem2 = (nextItem1 && nextItem1->next) ? nextItem1->next : NULL; + + aafiAudioClip* prevClip = NULL; + aafiAudioClip* nextClip = NULL; + + if (prevItem1 && prevItem1->type == AAFI_AUDIO_CLIP) { + prevClip = prevItem1->data; + + if (fadeClip->pos == (prevClip->pos + prevClip->len)) { + /* a previous clip is touching this fadeClip on the left */ + + if (is_sample_accurate_edit (prevClip->essencePointerList->essenceFile->name)) { + remove_sampleAccurateEditClip (aafi, audioTrack, prevItem1); + + if (prevItem2 && prevItem2->type == AAFI_AUDIO_CLIP) { + aafiAudioClip* prevClip2 = prevItem2->data; + + if (fadeClip->pos == (prevClip2->pos + prevClip2->len)) { + prevClip = prevClip2; + debug ("Got a clip \"%s\" preceding fadeClip \"%s\"", + prevClip->essencePointerList->essenceFile->unique_name, + fadeClip->essencePointerList->essenceFile->unique_name); + } else { + prevClip = NULL; + } + } else { + prevClip = NULL; + } + } else { + debug ("Got a clip \"%s\" preceding fadeClip \"%s\"", + prevClip->essencePointerList->essenceFile->unique_name, + fadeClip->essencePointerList->essenceFile->unique_name); + } + } else { + prevClip = NULL; + } + } + + if (nextItem1 && nextItem1->type == AAFI_AUDIO_CLIP) { + nextClip = nextItem1->data; + + if ((fadeClip->pos + fadeClip->len) == nextClip->pos) { + /* a following clip is touching this fadeClip on the right */ + + if (is_sample_accurate_edit (nextClip->essencePointerList->essenceFile->name)) { + remove_sampleAccurateEditClip (aafi, audioTrack, nextItem1); + + if (nextItem2 && nextItem2->type == AAFI_AUDIO_CLIP) { + aafiAudioClip* nextClip2 = nextItem2->data; + + if ((fadeClip->pos + fadeClip->len) == nextClip2->pos) { + nextClip = nextClip2; + debug ("Got a clip \"%s\" following fadeClip \"%s\"", + nextClip->essencePointerList->essenceFile->unique_name, + fadeClip->essencePointerList->essenceFile->unique_name); + } else { nextClip = NULL; } } else { nextClip = NULL; } } else { - // nextClip = (aafiAudioClip*)Item->next->data; - - // debug( "NEXT POS %lu", nextClip->pos ); - // debug( "CURENT POS %lu", currentpos + currentlen ); - - if (nextClip->pos != currentpos + currentlen) { - nextClip = NULL; - } + debug ("Got a clip \"%s\" following fadeClip \"%s\"", + nextClip->essencePointerList->essenceFile->unique_name, + fadeClip->essencePointerList->essenceFile->unique_name); } + } else { + nextClip = NULL; } } + if (!prevClip && !nextClip) { + debug ("FadeClip \"%s\" is not surrounding by any touching clip", + fadeClip->essencePointerList->essenceFile->unique_name); + return 0; + } + + /* + * Ensures we have enough handle in surrounding clips to expand by fade length + */ + + if (prevClip) { + aafPosition_t essenceLength = aafi_convertUnit (prevClip->essencePointerList->essenceFile->length, prevClip->essencePointerList->essenceFile->samplerateRational, prevClip->track->edit_rate); + + if ((essenceLength - prevClip->essence_offset - prevClip->len) < fadeClip->len) { + warning ("Previous clip \"%s\" has not enough handle to build a fade in place of \"%s\"", + prevClip->essencePointerList->essenceFile->unique_name, + fadeClip->essencePointerList->essenceFile->unique_name); + return -1; + } + } + + if (nextClip) { + if (nextClip->essence_offset < fadeClip->len) { + warning ("Next clip \"%s\" has not enough handle to build a fade in place of \"%s\"", + nextClip->essencePointerList->essenceFile->unique_name, + fadeClip->essencePointerList->essenceFile->unique_name); + return -1; + } + } + + debug ("Replacing fadeClip \"%s\" with a %s transition of length %" PRIi64, + fadeClip->essencePointerList->essenceFile->unique_name, + (prevClip && nextClip) ? "X-Fade" : (nextClip) ? "FadeIn" + : "FadeOut", + fadeClip->len); + + /* + * changes existing aafiTimelineItem from aafiAudioClip into aafiTransition + */ + + aafPosition_t fadeClipLength = fadeClip->len; + + fadeItem->type = AAFI_TRANS; + + aafi_freeAudioClip (fadeItem->data); + + fadeItem->data = calloc (1, sizeof (aafiTransition)); + + if (!fadeItem->data) { + error ("Out of memory"); + aafi_removeTimelineItem (aafi, fadeItem); + audioTrack->clipCount--; + return 1; /* important ! */ + } + + aafiTransition* trans = fadeItem->data; + + trans->len = fadeClipLength; + trans->flags = AAFI_INTERPOL_LINEAR; + trans->time_a = calloc (2, sizeof (aafRational_t)); trans->value_a = calloc (2, sizeof (aafRational_t)); - trans->time_a[0].numerator = 0; - trans->time_a[0].denominator = 0; - trans->time_a[1].numerator = 1; - trans->time_a[1].denominator = 1; + if (!trans->time_a || !trans->value_a) { + error ("Out of memory"); + aafi_removeTimelineItem (aafi, fadeItem); + audioTrack->clipCount--; + return 1; /* important ! */ + } if (prevClip && nextClip) { - // debug( ":: XFADE" ); + prevClip->len += fadeClipLength; + + nextClip->pos -= fadeClipLength; + nextClip->len += fadeClipLength; + nextClip->essence_offset -= fadeClipLength; + trans->flags |= AAFI_TRANS_XFADE; + trans->cut_pt = fadeClipLength / 2; trans->value_a[0].numerator = 0; trans->value_a[0].denominator = 0; trans->value_a[1].numerator = 1; trans->value_a[1].denominator = 1; } else if (prevClip) { - // debug( ":: FADE OUT" ); + prevClip->len += fadeClipLength; + trans->flags |= AAFI_TRANS_FADE_OUT; + trans->cut_pt = fadeClipLength; trans->value_a[0].numerator = 1; trans->value_a[0].denominator = 1; trans->value_a[1].numerator = 0; trans->value_a[1].denominator = 0; } else if (nextClip) { - // debug( ":: FADE IN" ); + nextClip->pos -= fadeClipLength; + nextClip->len += fadeClipLength; + nextClip->essence_offset -= fadeClipLength; + trans->flags |= AAFI_TRANS_FADE_IN; + trans->cut_pt = 0; trans->value_a[0].numerator = 0; trans->value_a[0].denominator = 0; @@ -237,43 +386,23 @@ replace_clipfade_with_fade (AAF_Iface* aafi, aafiTimelineItem* Item) trans->value_a[1].denominator = 1; } - if (Item->prev) { - Item->prev->next = transItem; - transItem->prev = Item->prev; - } else { - aafiAudioTrack* audioTrack = NULL; + audioTrack->clipCount--; - foreach_audioTrack (audioTrack, aafi) - { - if (audioTrack->Items == Item) { - audioTrack->Items = transItem; - } - } - - transItem->prev = NULL; - } - - if (Item->next) { - Item->next->prev = transItem; - } - - transItem->next = Item->next; - - aafi_freeTimelineItem (&Item); - - return 0; + return 1; } int -protools_post_processing (AAF_Iface* aafi /*, enum protools_options flags*/) +protools_post_processing (AAF_Iface* aafi) { aafiAudioTrack* audioTrack = NULL; - foreach_audioTrack (audioTrack, aafi) + AAFI_foreachAudioTrack (aafi, audioTrack) { - aafiTimelineItem* audioItem = audioTrack->Items; + aafiTimelineItem* audioItem = audioTrack->timelineItems; while (audioItem != NULL) { + aafiTimelineItem* audioItemNext = audioItem->next; + if (audioItem->type != AAFI_AUDIO_CLIP) { audioItem = audioItem->next; continue; @@ -281,21 +410,23 @@ protools_post_processing (AAF_Iface* aafi /*, enum protools_options flags*/) aafiAudioClip* audioClip = (aafiAudioClip*)audioItem->data; - wchar_t* clipName = audioClip->essencePointerList->essence->file_name; + char* clipName = audioClip->essencePointerList->essenceFile->name; - if ((aafi->ctx.options.protools & PROTOOLS_REPLACE_CLIP_FADES) && is_rendered_fade (clipName)) { - replace_clipfade_with_fade (aafi, audioItem); - - audioItem = audioTrack->Items; - continue; - } else if ((aafi->ctx.options.protools & PROTOOLS_REMOVE_SAMPLE_ACCURATE_EDIT) && is_sample_accurate_edit (clipName)) { - aafi_removeTimelineItem (aafi, audioItem); - - audioItem = audioTrack->Items; - continue; + if ((aafi->ctx.options.protools & AAFI_PROTOOLS_OPT_REPLACE_CLIP_FADES) && + is_rendered_fade (clipName)) { + if (replace_clipFade (aafi, audioTrack, audioItem) > 0) { + audioItem = audioTrack->timelineItems; + continue; + } + } else if ((aafi->ctx.options.protools & AAFI_PROTOOLS_OPT_REMOVE_SAMPLE_ACCURATE_EDIT) && + is_sample_accurate_edit (clipName)) { + if (remove_sampleAccurateEditClip (aafi, audioTrack, audioItem)) { + audioItem = audioTrack->timelineItems; + continue; + } } - audioItem = audioItem->next; + audioItem = audioItemNext; } } diff --git a/libs/aaf/RIFFParser.c b/libs/aaf/RIFFParser.c index 40abff154c..09e74c49cd 100644 --- a/libs/aaf/RIFFParser.c +++ b/libs/aaf/RIFFParser.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Adrien Gesta-Fline + * Copyright (C) 2023-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -18,7 +18,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include #include @@ -27,13 +26,13 @@ #include "aaf/RIFFParser.h" #define debug(...) \ - _dbg (dbg, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (log, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (dbg, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (log, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (dbg, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) + AAF_LOG (log, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) #define BE2LE32(val) \ (((val >> 24) & 0xff) | ((val << 8) & 0xff0000) | ((val >> 8) & 0xff00) | ((val << 24) & 0xff000000)) @@ -45,10 +44,10 @@ static uint32_t beExtended2leUint32 (const unsigned char numx[10]); int -riff_writeWavFileHeader (FILE* fp, struct wavFmtChunk* wavFmt, struct wavBextChunk* wavBext, uint32_t audioDataSize, struct dbg* dbg) +laaf_riff_writeWavFileHeader (FILE* fp, struct wavFmtChunk* wavFmt, struct wavBextChunk* wavBext, uint32_t audioDataSize, struct aafLog* log) { - (void)dbg; - uint32_t filesize = (4 /* WAVE */) + sizeof (struct wavFmtChunk) + ((wavBext) ? sizeof (struct wavBextChunk) : 0) + (8 /*data chunk header*/) + audioDataSize; + (void)log; + size_t filesize = (4 /* WAVE */) + sizeof (struct wavFmtChunk) + ((wavBext) ? sizeof (struct wavBextChunk) : 0) + (8 /*data chunk header*/) + audioDataSize; size_t writtenBytes = fwrite ("RIFF", sizeof (unsigned char), 4, fp); @@ -75,7 +74,7 @@ riff_writeWavFileHeader (FILE* fp, struct wavFmtChunk* wavFmt, struct wavBextChu wavFmt->cksz = sizeof (struct wavFmtChunk) - sizeof (struct riffChunk); wavFmt->format_tag = 1; /* PCM */ wavFmt->avg_bytes_per_sec = wavFmt->samples_per_sec * wavFmt->channels * wavFmt->bits_per_sample / 8; - wavFmt->block_align = wavFmt->channels * wavFmt->bits_per_sample / 8; + wavFmt->block_align = wavFmt->channels * (wavFmt->bits_per_sample >> 3); writtenBytes = fwrite ((unsigned char*)wavFmt, sizeof (unsigned char), sizeof (struct wavFmtChunk), fp); @@ -114,7 +113,7 @@ riff_writeWavFileHeader (FILE* fp, struct wavFmtChunk* wavFmt, struct wavBextChu } int -riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS flags, size_t (*readerCallback) (unsigned char*, size_t, size_t, void*, void*, void*), void* user1, void* user2, void* user3, struct dbg* dbg) +laaf_riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS flags, size_t (*readerCallback) (unsigned char*, size_t, size_t, void*, void*, void*), void* user1, void* user2, void* user3, struct aafLog* log) { struct riffChunk chunk; struct riffHeaderChunk riff; @@ -123,7 +122,8 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS size_t bytesRead = readerCallback ((unsigned char*)&riff, 0, sizeof (riff), user1, user2, user3); - if (bytesRead < sizeof (riff)) { + if (bytesRead == RIFF_READER_ERROR || + bytesRead < sizeof (riff)) { error ("Could not read file header"); return -1; } @@ -153,12 +153,14 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS } size_t filesize = riff.cksz + sizeof (chunk); + size_t pos_sz = 0; size_t pos = sizeof (struct riffHeaderChunk); while (pos < filesize) { bytesRead = readerCallback ((unsigned char*)&chunk, pos, sizeof (chunk), user1, user2, user3); - if (bytesRead < sizeof (chunk)) { + if (bytesRead == RIFF_READER_ERROR || + bytesRead < sizeof (chunk)) { error ("Could not read chunk \"%.4s\" @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, pos, bytesRead); break; } @@ -179,7 +181,8 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS bytesRead = readerCallback ((unsigned char*)&wavFmtChunk, pos, sizeof (wavFmtChunk), user1, user2, user3); - if (bytesRead < sizeof (wavFmtChunk)) { + if (bytesRead == RIFF_READER_ERROR || + bytesRead < sizeof (riff)) { error ("Could not read chunk \"%.4s\" content @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, pos, bytesRead); break; } @@ -199,6 +202,8 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS RIFFAudioFile->sampleCount = chunk.cksz / RIFFAudioFile->channels / (RIFFAudioFile->sampleSize / 8); } + RIFFAudioFile->pcm_audio_start_offset = (pos + sizeof (struct riffChunk)); + if (flags & RIFF_PARSE_AAF_SUMMARY) { return 0; } @@ -213,7 +218,8 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS bytesRead = readerCallback ((unsigned char*)&aiffCOMMChunk, pos, sizeof (aiffCOMMChunk), user1, user2, user3); - if (bytesRead < sizeof (aiffCOMMChunk)) { + if (bytesRead == RIFF_READER_ERROR || + bytesRead < sizeof (riff)) { error ("Could not read chunk \"%.4s\" content @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, pos, bytesRead); break; } @@ -241,7 +247,8 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS debug ("Sample count retrieved from COMM chunk (%" PRIu64 ") does not match SSND chunk (%" PRIu64 ")", RIFFAudioFile->sampleCount, sampleCount); } - RIFFAudioFile->sampleCount = sampleCount; + RIFFAudioFile->sampleCount = sampleCount; + RIFFAudioFile->pcm_audio_start_offset = pos + sizeof (struct aiffSSNDChunk); if (flags & RIFF_PARSE_AAF_SUMMARY) { return 0; @@ -249,7 +256,14 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS } } - pos += chunk.cksz + sizeof (chunk); + pos_sz = chunk.cksz + sizeof (chunk); + + if (pos_sz >= SIZE_MAX) { + error ("Parser position is bigger than RIFF_SIZE limits"); + break; + } + + pos += pos_sz; } return 0; @@ -293,7 +307,7 @@ beExtended2leUint32 (const unsigned char numx[10]) } else { /* Otherwise it's denormal. It cannot be represented as double. Translate as singed zero. */ memcpy (&result, d, 8); - return result; + return (uint32_t)result; } } else { /* Normal number. */ @@ -301,7 +315,7 @@ beExtended2leUint32 (const unsigned char numx[10]) if (exponent <= -52) { /*< Too small to represent. Translate as (signed) zero. */ memcpy (&result, d, 8); - return result; + return (uint32_t)result; } else if (exponent < 0) { /* Denormal, exponent bits are already zero here. */ } else if (exponent >= 0x7FF) { /*< Too large to represent. Translate as infinite. */ @@ -309,11 +323,11 @@ beExtended2leUint32 (const unsigned char numx[10]) d[6] = 0xF0; memset (d, 0x00, 6); memcpy (&result, d, 8); - return result; + return (uint32_t)result; } else { /* Representable number */ d[7] |= (exponent & 0x7F0) >> 4; - d[6] |= (exponent & 0xF) << 4; + d[6] |= (unsigned char)((exponent & 0xF) << 4); } } diff --git a/libs/aaf/Resolve.c b/libs/aaf/Resolve.c index a11e67559c..43162c71bc 100644 --- a/libs/aaf/Resolve.c +++ b/libs/aaf/Resolve.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Adrien Gesta-Fline + * Copyright (C) 2023-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -26,28 +26,28 @@ #include "aaf/AAFIParser.h" #include "aaf/AAFToText.h" -#include "aaf/debug.h" #include "aaf/libaaf.h" +#include "aaf/log.h" #define debug(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (aafi->dbg, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) + AAF_LOG (aafi->log, aafi, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) int resolve_AAF (struct AAF_Iface* aafi) { int probe = 0; - if (aafi->aafd->Identification.CompanyName && wcsncmp (aafi->aafd->Identification.CompanyName, L"Blackmagic Design", wcslen (L"Blackmagic Design")) == 0) { + if (aafi->aafd->Identification.CompanyName && strncmp (aafi->aafd->Identification.CompanyName, "Blackmagic Design", strlen ("Blackmagic Design")) == 0) { probe++; } - if (aafi->aafd->Identification.ProductName && wcsncmp (aafi->aafd->Identification.ProductName, L"DaVinci Resolve", wcslen (L"DaVinci Resolve")) == 0) { + if (aafi->aafd->Identification.ProductName && strncmp (aafi->aafd->Identification.ProductName, "DaVinci Resolve", strlen ("DaVinci Resolve")) == 0) { probe++; } @@ -57,166 +57,3 @@ resolve_AAF (struct AAF_Iface* aafi) return 0; } - -int -resolve_parse_aafObject_Selector (struct AAF_Iface* aafi, aafObject* Selector, td* __ptd) -{ - /* - * Resolve 18.5 - * - * The Selector Object was only seen used to describe a disabled clip : - * - Selected property Object is an empty Filler - * - Alternate keeps track of the original clip. - * -03411││ ├──◻ AAFClassID_Selector -01926││ Selected --> │ └──◻ AAFClassID_Filler -02359││ Alternate -> │ └──◻ AAFClassID_OperationGroup (OpIdent: AAFOperationDef_MonoAudioGain) -03822││ │ ├──◻ AAFClassID_VaryingValue -02877││ │ └──◻ AAFClassID_SourceClip -02882││ │ └──◻ AAFClassID_MasterMob (UsageCode: n/a) : speech-sample.mp3 - disabled -04460││ │ └──◻ AAFClassID_TimelineMobSlot -03089││ │ └──◻ AAFClassID_SourceClip -04167││ │ └──◻ AAFClassID_SourceMob (UsageCode: n/a) : speech-sample.mp3 - disabled -01249││ │ └──◻ AAFClassID_PCMDescriptor -01455││ │ └──◻ AAFClassID_NetworkLocator : file:///C:/Users/user/Desktop/libAAF/test/res/speech-sample.mp3 - */ - - struct trace_dump __td; - __td_set (__td, __ptd, 0); - - aafObject* Selected = aaf_get_propertyValue (Selector, PID_Selector_Selected, &AAFTypeID_SegmentStrongReference); - - if (Selected == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, Selector, &__td, "Missing PID_Selector_Selected"); - return -1; - } - - aafObject* Alternates = aaf_get_propertyValue (Selector, PID_Selector_Alternates, &AAFTypeID_SegmentStrongReferenceVector); - - if (Alternates == NULL) { /* opt */ - DUMP_OBJ_WARNING (aafi, Selector, &__td, "Missing PID_Selector_Alternates"); - return -1; - } - - void* ComponentAttributeList = aaf_get_propertyValue (Selector, aaf_get_PropertyIDByName (aafi->aafd, L"ComponentAttributeList"), &AAFUID_NULL); - - if (ComponentAttributeList == NULL) { - DUMP_OBJ_ERROR (aafi, Selector, &__td, "Missing AAFClassID_Selector::ComponentAttributeList"); - return -1; - } - - DUMP_OBJ (aafi, Selector, &__td); - - // aaf_dump_ObjectProperties( aafi->aafd, Selector ); - // aaf_dump_ObjectProperties( aafi->aafd, ComponentAttributeList ); - - int ismuted = 0; - aafObject* ComponentAttribute = NULL; - - aaf_foreach_ObjectInSet (&ComponentAttribute, ComponentAttributeList, NULL) - { - /* TODO implement retrieve_TaggedValue() */ - - wchar_t* name = aaf_get_propertyValue (ComponentAttribute, PID_TaggedValue_Name, &AAFTypeID_String); - - if (name == NULL) { /* req */ - DUMP_OBJ_ERROR (aafi, ComponentAttribute, &__td, "Missing PID_TaggedValue_Name"); - continue; - } - - aafIndirect_t* Indirect = aaf_get_propertyValue (ComponentAttribute, PID_TaggedValue_Value, &AAFTypeID_Indirect); - - if (Indirect == NULL) { - DUMP_OBJ_ERROR (aafi, ComponentAttribute, &__td, "Missing PID_TaggedValue_Value"); - free (name); - continue; - } - - int32_t* value = aaf_get_indirectValue (aafi->aafd, Indirect, &AAFTypeID_Int32); - - if (value == NULL) { - DUMP_OBJ_ERROR (aafi, ComponentAttribute, &__td, "Could not retrieve Indirect value for PID_TaggedValue_Value"); - free (name); - continue; - } - - // debug( "Tagged | Name: %ls Value : %u", name, *value ); - - if (aafi->ctx.options.resolve & RESOLVE_INCLUDE_DISABLED_CLIPS) { - if (wcsncmp (name, L"_DISABLE_CLIP_FLAG", wcslen (L"_DISABLE_CLIP_FLAG")) == 0 && *value == 1) { - ismuted = 1; - aafi->ctx.current_clip_is_muted = 1; - - aafObject* Alternate = NULL; - - int i = 0; - aaf_foreach_ObjectInSet (&Alternate, Alternates, NULL) - { - if (i == 0) { /* there should be only one Segment in set, but still. Let's be carefull */ - aafi_parse_Segment (aafi, Alternate, &__td); - } else { - DUMP_OBJ_ERROR (aafi, Alternate, &__td, "Multiple Alternates in Davinci Resolve selector"); - } - i++; - } - } - } - - free (name); - } - - /* aafi->ctx.current_clip_is_muted was already reset at this point */ - if (ismuted == 0) { - return aafi_parse_Segment (aafi, Selected, &__td); - } - - return 0; -} - -int -resolve_parse_aafObject_DescriptiveMarker (struct AAF_Iface* aafi, aafObject* DescriptiveMarker, td* __ptd) -{ - /* - * Resolve 18.5 - */ - - struct trace_dump __td; - __td_set (__td, __ptd, 1); - - aafPosition_t* start = aaf_get_propertyValue (DescriptiveMarker, PID_Event_Position, &AAFTypeID_PositionType); - - if (start == NULL) { /* req (TODO: conditional) */ - DUMP_OBJ_ERROR (aafi, DescriptiveMarker, &__td, "Missing PID_Event_Position"); - return -1; - } - - aafPosition_t* length = aaf_get_propertyValue (DescriptiveMarker, PID_Component_Length, &AAFTypeID_PositionType); - - wchar_t* comment = aaf_get_propertyValue (DescriptiveMarker, PID_Event_Comment, &AAFTypeID_String); - - wchar_t* name = aaf_get_propertyValue (DescriptiveMarker, aaf_get_PropertyIDByName (aafi->aafd, L"CommentMarkerUser"), &AAFTypeID_String); - - uint16_t* RGBColor = NULL; - - aafProperty* RGBColorProp = aaf_get_property (DescriptiveMarker, aaf_get_PropertyIDByName (aafi->aafd, L"CommentMarkerColor")); - - if (RGBColorProp) { - if (RGBColorProp->len != sizeof (uint16_t) * 3) { - error ("CommentMarkerColor has wrong size of %u", RGBColorProp->len); - } else { - RGBColor = RGBColorProp->val; - - /* big endian to little endian */ - - RGBColor[0] = (RGBColor[0] >> 8) | (RGBColor[0] << 8); - RGBColor[1] = (RGBColor[1] >> 8) | (RGBColor[1] << 8); - RGBColor[2] = (RGBColor[2] >> 8) | (RGBColor[2] << 8); - } - } - - aafi_newMarker (aafi, aafi->ctx.current_markers_edit_rate, *start, ((length) ? *length : 0), name, comment, &RGBColor); - - DUMP_OBJ (aafi, DescriptiveMarker, &__td); - - return 0; -} diff --git a/libs/aaf/URIParser.c b/libs/aaf/URIParser.c index 37420e38d1..198d566d09 100644 --- a/libs/aaf/URIParser.c +++ b/libs/aaf/URIParser.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Adrien Gesta-Fline + * Copyright (C) 2023-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -18,6 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include #include @@ -31,15 +32,16 @@ typedef SSIZE_T ssize_t; #endif #include "aaf/URIParser.h" +#include "aaf/utils.h" #define debug(...) \ - _dbg (dbg, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) + AAF_LOG (log, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_DEBUG, __VA_ARGS__) #define warning(...) \ - _dbg (dbg, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) + AAF_LOG (log, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_WARNING, __VA_ARGS__) #define error(...) \ - _dbg (dbg, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) + AAF_LOG (log, NULL, DEBUG_SRC_ID_AAF_IFACE, VERB_ERROR, __VA_ARGS__) #define IS_LOWALPHA(c) \ ((c >= 'a') && (c <= 'z')) @@ -89,52 +91,45 @@ typedef SSIZE_T ssize_t; (uri->scheme_t != URI_SCHEME_T_FILE && \ !(uri->opts & URI_OPT_IGNORE_FRAGMENT)) -#define URI_SET_STR(str, start, end) \ - \ - str = malloc (sizeof (char) * ((end - start) + 1)); \ - \ - if (NULL == str) { \ - error ("URI allocation failed"); \ - goto err; \ - } \ - \ - snprintf (str, (end - start) + 1, "%s", start); +#define URI_SET_STR(str, start, end) \ + \ + str = malloc (sizeof (char) * (uint32_t) ((end - start) + 1)); \ + \ + if (!str) { \ + error ("Out of memory"); \ + goto err; \ + } \ + \ + snprintf (str, (uint32_t) (end - start) + 1, "%s", start); + +static char* +uriDecodeString (char* src, char* dst); +static int +uriIsIPv4 (const char* s, size_t size, char** err); +static int +uriIsIPv6 (const char* s, size_t size, char** err); static int -_uri_parse_scheme (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_scheme (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static int -_uri_parse_authority (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_authority (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static int -_uri_parse_userinfo (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_userinfo (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static int -_uri_parse_hostname (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_hostname (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static int -_uri_parse_path (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_path (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static int -_uri_parse_query (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_query (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static int -_uri_parse_fragment (struct uri* uri, const char** pos, const char* end, struct dbg* dbg); +_uri_parse_fragment (struct uri* uri, const char** pos, const char* end, struct aafLog* log); static void _uri_scheme2schemeType (struct uri* uri); -static int -_laaf_util_snprintf_realloc (char** str, size_t* size, size_t offset, const char* format, ...); -#ifdef BUILD_URI_TEST // gcc -g -W -Wall ./URIParser.c -D BUILD_URI_TEST -static int -_uri_cmp (const struct uri* a, const struct uri* b); -static void -_uri_dump_diff (struct uri* a, struct uri* b, int totalDifferencies); -static int -_uri_test (const char* uristr, enum uri_option optflags, struct uri expectedRes, int line); -#endif // BUILD_URI_TEST - -char* +static char* uriDecodeString (char* src, char* dst) { - int inpos = 0; - int outpos = 0; - if (src == NULL) { return NULL; } @@ -143,47 +138,39 @@ uriDecodeString (char* src, char* dst) dst = src; } - while (src[inpos]) { - if (src[inpos] == '%' && IS_HEX (src[inpos + 1]) && IS_HEX (src[inpos + 2])) { - int c = 0; + char* end = src + strlen (src); - char hex1 = src[inpos + 1]; + while (*src) { + if (*src == '%' && src + 2 < end && IS_HEX (*(src + 1)) && IS_HEX (*(src + 2))) { + char d1 = *(src + 1); + char d2 = *(src + 2); - if ((hex1 >= '0') && (hex1 <= '9')) - c = (hex1 - '0'); - else if ((hex1 >= 'a') && (hex1 <= 'f')) - c = (hex1 - 'a') + 10; - else if ((hex1 >= 'A') && (hex1 <= 'F')) - c = (hex1 - 'A') + 10; + int digit = 0; - char hex2 = src[inpos + 2]; + digit = (d1 >= 'A' ? ((d1 & 0xdf) - 'A') + 10 : (d1 - '0')); + digit <<= 4; + digit += (d2 >= 'A' ? ((d2 & 0xdf) - 'A') + 10 : (d2 - '0')); - if ((hex2 >= '0') && (hex2 <= '9')) - c = c * 16 + (hex2 - '0'); - else if ((hex2 >= 'a') && (hex2 <= 'f')) - c = c * 16 + (hex2 - 'a') + 10; - else if ((hex2 >= 'A') && (hex2 <= 'F')) - c = c * 16 + (hex2 - 'A') + 10; + assert (digit > CHAR_MIN && digit < UCHAR_MAX); - dst[outpos] = (char)c; - inpos += 3; + *dst = (char)digit; + + src += 3; + dst++; } else { - dst[outpos] = src[inpos]; - inpos++; + *dst = *src; + src++; + dst++; } - - outpos++; } - if (inpos > outpos) { - dst[outpos] = 0x00; - } + *dst = 0x00; return dst; } static int -_uri_parse_scheme (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_scheme (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { const char* p = *pos; @@ -216,7 +203,12 @@ _uri_parse_scheme (struct uri* uri, const char** pos, const char* end, struct db char* pp = uri->scheme; while (*pp) { - *pp = tolower (*pp); + int charint = tolower (*pp); + + assert (charint > CHAR_MIN && charint < CHAR_MAX); + + *pp = (char)charint; + pp++; } @@ -231,7 +223,7 @@ err: } static int -_uri_parse_authority (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_authority (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { /* * RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax @@ -298,7 +290,7 @@ err: } static int -_uri_parse_userinfo (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_userinfo (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { int hasUserinfo = 0; int userinfoIllegalCharacters = 0; @@ -373,7 +365,7 @@ err: } static int -_uri_parse_hostname (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_hostname (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { const char* p = *pos; @@ -422,7 +414,7 @@ _uri_parse_hostname (struct uri* uri, const char** pos, const char* end, struct p++; } - // debug( " >>> %.*s", (int)(p-*pos), p ); + // debug( L" >>> %.*s", (int)(p-*pos), p ); URI_SET_STR (uri->host, *pos, p); } @@ -430,7 +422,7 @@ _uri_parse_hostname (struct uri* uri, const char** pos, const char* end, struct // if ( !(uri->flags & URI_T_HOST_IPV6 || uri->flags & URI_T_HOST_EMPTY) ) { if (!(uri->flags & URI_T_HOST_IPV6) && uri->host != NULL && *uri->host != 0x00) { if (uriIsIPv4 (uri->host, strlen (uri->host), NULL)) { - uri->flags &= ~URI_T_HOST_MASK; + uri->flags &= ~(unsigned)URI_T_HOST_MASK; uri->flags |= URI_T_HOST_IPV4; if (strcmp (uri->host, "127.0.0.1") == 0) { uri->flags |= URI_T_LOCALHOST; @@ -479,7 +471,7 @@ err: } static int -_uri_parse_path (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_path (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { int winDrive = 0; @@ -507,7 +499,7 @@ _uri_parse_path (struct uri* uri, const char** pos, const char* end, struct dbg* p++; } - // debug( " >>> (%i) %.*s", (int)(p-*pos), (int)(p-*pos), p ); + // debug( L" >>> (%i) %.*s", (int)(p-*pos), (int)(p-*pos), p ); URI_SET_STR (uri->path, *pos, p); @@ -534,7 +526,7 @@ err: } static int -_uri_parse_query (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_query (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { const char* p = *pos; @@ -561,7 +553,7 @@ err: } static int -_uri_parse_fragment (struct uri* uri, const char** pos, const char* end, struct dbg* dbg) +_uri_parse_fragment (struct uri* uri, const char** pos, const char* end, struct aafLog* log) { /* * https://datatracker.ietf.org/doc/html/draft-yevstifeyev-ftp-uri-scheme#section-3.2.4.2 @@ -602,7 +594,7 @@ err: } struct uri* -uriParse (const char* uristr, enum uri_option optflags, struct dbg* dbg) +laaf_uri_parse (const char* uristr, enum uri_option optflags, struct aafLog* log) { if (uristr == NULL) { return NULL; @@ -610,7 +602,8 @@ uriParse (const char* uristr, enum uri_option optflags, struct dbg* dbg) struct uri* uri = calloc (1, sizeof (struct uri)); - if (uri == NULL) { + if (!uri) { + error ("Out of memory"); return NULL; } @@ -626,27 +619,27 @@ uriParse (const char* uristr, enum uri_option optflags, struct dbg* dbg) const char* pos = uristr; const char* end = pos + urilen; - _uri_parse_scheme (uri, &pos, end, dbg); + _uri_parse_scheme (uri, &pos, end, log); - if (_uri_parse_authority (uri, &pos, end, dbg)) { - _uri_parse_userinfo (uri, &pos, end, dbg); - _uri_parse_hostname (uri, &pos, end, dbg); + if (_uri_parse_authority (uri, &pos, end, log)) { + _uri_parse_userinfo (uri, &pos, end, log); + _uri_parse_hostname (uri, &pos, end, log); } - _uri_parse_path (uri, &pos, end, dbg); + _uri_parse_path (uri, &pos, end, log); if (SCHEME_ALLOW_QUERY (uri)) { - _uri_parse_query (uri, &pos, end, dbg); + _uri_parse_query (uri, &pos, end, log); } if (SCHEME_ALLOW_FRAGMENT (uri)) { - _uri_parse_fragment (uri, &pos, end, dbg); + _uri_parse_fragment (uri, &pos, end, log); } goto end; err: - uriFree (uri); + laaf_uri_free (uri); uri = NULL; end: @@ -655,51 +648,34 @@ end: } void -uriFree (struct uri* uri) +laaf_uri_free (struct uri* uri) { - if (uri == NULL) { + if (!uri) { return; } - if (NULL != uri->scheme) { - free (uri->scheme); - } - if (NULL != uri->userinfo) { - free (uri->userinfo); - } - if (NULL != uri->authority) { - free (uri->authority); - } - if (NULL != uri->user) { - free (uri->user); - } - if (NULL != uri->pass) { - free (uri->pass); - } - if (NULL != uri->host) { - free (uri->host); - } - if (NULL != uri->path) { - free (uri->path); - } - if (NULL != uri->query) { - free (uri->query); - } - if (NULL != uri->fragment) { - free (uri->fragment); - } + + free (uri->scheme); + free (uri->userinfo); + free (uri->authority); + free (uri->user); + free (uri->pass); + free (uri->host); + free (uri->path); + free (uri->query); + free (uri->fragment); free (uri); } -int -uriIsIPv4 (const char* s, int size, char** err) +static int +uriIsIPv4 (const char* s, size_t size, char** err) { int octets = 0; const char* currentOctetStart = s; char prev = 0; - for (int i = 0; i <= size; i++) { + for (size_t i = 0; i <= size; i++) { if (prev == 0) { if (IS_DIGIT (*(s + i))) { currentOctetStart = (s + i); @@ -709,7 +685,7 @@ uriIsIPv4 (const char* s, int size, char** err) if (*(s + i) == '.') { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : can't start with a single '.'"); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : can't start with a single '.'"); } return 0; } @@ -724,7 +700,7 @@ uriIsIPv4 (const char* s, int size, char** err) if (*(s + i) == '.') { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : can't have successive '.'"); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : can't have successive '.'"); } return 0; } @@ -740,14 +716,14 @@ uriIsIPv4 (const char* s, int size, char** err) int octet = atoi (currentOctetStart); if (octet > 255) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : octet %i is too high : %.*s", (octets), (int)((s + i) - currentOctetStart), currentOctetStart); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : octet %i is too high : %.*s", (octets), (int)((s + i) - currentOctetStart), currentOctetStart); } return 0; } if (i + 1 == size) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : can't end with a single '.'"); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : can't end with a single '.'"); } return 0; } @@ -763,20 +739,20 @@ uriIsIPv4 (const char* s, int size, char** err) } if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : illegal char '%c' (0x%02x)", *(s + i), *(s + i)); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : illegal char '%c' (0x%02x)", *(s + i), *(s + i)); } return 0; } if (octets > 4) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : too many octets"); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : too many octets"); } return 0; } if (octets < 4) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : not enough octets"); + laaf_util_snprintf_realloc (err, NULL, 0, "IPV4 parser error : not enough octets"); } return 0; } @@ -784,8 +760,8 @@ uriIsIPv4 (const char* s, int size, char** err) return 1; } -int -uriIsIPv6 (const char* s, int size, char** err) +static int +uriIsIPv6 (const char* s, size_t size, char** err) { int segmentCount = 0; int emptySegmentCount = 0; @@ -798,7 +774,7 @@ uriIsIPv6 (const char* s, int size, char** err) char prev = 0; - for (int i = 0; i <= size; i++) { + for (size_t i = 0; i <= size; i++) { if (prev == 0) { if (IS_HEX (*(s + i))) { segmentCount++; @@ -826,7 +802,7 @@ uriIsIPv6 (const char* s, int size, char** err) if (*(s + i) == ':') { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "can't start with a single ':'"); + laaf_util_snprintf_realloc (err, NULL, 0, "can't start with a single ':'"); } return 0; } @@ -852,11 +828,11 @@ uriIsIPv6 (const char* s, int size, char** err) int octet = atoi (curSegmentStart); if (octet > 255) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "ipv4 portion octet %i is too high : %.*s", (ipv4portion), curSegmentLength, curSegmentStart); + laaf_util_snprintf_realloc (err, NULL, 0, "ipv4 portion octet %i is too high : %.*s", (ipv4portion), curSegmentLength, curSegmentStart); } return 0; } - // debug( "%i", octet ); + // debug( L"%i", octet ); prev = 'p'; ipv4portion++; continue; @@ -865,7 +841,7 @@ uriIsIPv6 (const char* s, int size, char** err) if (i == size || *(s + i) == ':') { if (curSegmentLength > 4) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "segment %i is too long : %.*s", (segmentCount - 1), curSegmentLength, curSegmentStart); + laaf_util_snprintf_realloc (err, NULL, 0, "segment %i is too long : %.*s", (segmentCount - 1), curSegmentLength, curSegmentStart); } return 0; } @@ -879,7 +855,7 @@ uriIsIPv6 (const char* s, int size, char** err) i++; } else if (i + 1 == size) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "can't end with a single ':'"); + laaf_util_snprintf_realloc (err, NULL, 0, "can't end with a single ':'"); } return 0; } else { @@ -910,7 +886,7 @@ uriIsIPv6 (const char* s, int size, char** err) if (*(s + i) == ':') { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "can't have more than two successive ':'"); + laaf_util_snprintf_realloc (err, NULL, 0, "can't have more than two successive ':'"); } return 0; } @@ -925,14 +901,14 @@ uriIsIPv6 (const char* s, int size, char** err) if (*(s + i) == '.') { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "can't have successive '.'"); + laaf_util_snprintf_realloc (err, NULL, 0, "can't have successive '.'"); } return 0; } } if (prev == 'd') { - if (IS_DIGIT (*(s + i))) { + if (IS_DIGIT (*(s + i)) && *(s + i + 1) != '\0' && i + 1 != size) { prev = 'd'; continue; } @@ -941,16 +917,16 @@ uriIsIPv6 (const char* s, int size, char** err) int octet = atoi (curSegmentStart); if (octet > 255) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "ipv4 portion octet %i is too high : %.*s", (ipv4portion), curSegmentLength, curSegmentStart); + laaf_util_snprintf_realloc (err, NULL, 0, "ipv4 portion octet %i is too high : %.*s", (ipv4portion), curSegmentLength, curSegmentStart); } return 0; } - // debug( "%i", octet ); + // debug( L"%i", octet ); if (i + 1 == size) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "can't end with a single '.'"); + laaf_util_snprintf_realloc (err, NULL, 0, "can't end with a single '.'"); } return 0; } @@ -966,43 +942,43 @@ uriIsIPv6 (const char* s, int size, char** err) } if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "illegal char '%c' (0x%02x)", *(s + i), *(s + i)); + laaf_util_snprintf_realloc (err, NULL, 0, "illegal char '%c' (0x%02x)", *(s + i), *(s + i)); } return 0; } - // debug( "segments : %i", segmentCount ); - // debug( "empty segments : %i", emptySegmentCount ); - // debug( "ipv4portion : %i", ipv4portion ); + // debug( L"segments : %i", segmentCount ); + // debug( L"empty segments : %i", emptySegmentCount ); + // debug( L"ipv4portion : %i", ipv4portion ); if (ipv4portion > 4) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "too many octets in ipv4 portion"); + laaf_util_snprintf_realloc (err, NULL, 0, "too many octets in ipv4 portion : %i", ipv4portion); } return 0; } if (ipv4portion > 0 && ipv4portion < 4) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "not enough octets in ipv4 portion"); + laaf_util_snprintf_realloc (err, NULL, 0, "not enough octets in ipv4 portion : %i", ipv4portion); } return 0; } if (emptySegmentCount + (segmentCount / 2) + ipv4portion > 8) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "too many segments"); + laaf_util_snprintf_realloc (err, NULL, 0, "too many segments"); } return 0; } if (emptySegmentCount == 0 && (((ipv4portion / 2) + segmentCount) < 8)) { if (err) { - _laaf_util_snprintf_realloc (err, NULL, 0, "not enough segments"); + laaf_util_snprintf_realloc (err, NULL, 0, "not enough segments"); } return 0; } - // debug( "LOCALHOST >>>>>>> %i", loopback ); + // debug( L"LOCALHOST >>>>>>> %i", loopback ); /* * 1: valid ipv6 address @@ -1059,261 +1035,3 @@ _uri_scheme2schemeType (struct uri* uri) uri->scheme_t = URI_SCHEME_T_UNKNOWN; } } - -static int -_laaf_util_snprintf_realloc (char** str, size_t* size, size_t offset, const char* format, ...) -{ - size_t tmpsize = 0; - - if (!size) { - size = &tmpsize; - } - - int retval, needed; - va_list ap; - - va_start (ap, format); - - while (0 <= (retval = vsnprintf ((*str) + offset, (*size) - offset, format, ap)) && (int64_t) ((*size) - offset) < (needed = retval + 1)) { - va_end (ap); - - *size *= 2; - - if ((int64_t) ((*size) - offset) < needed) - *size = needed; - - char* p = realloc (*str, *size); - - if (p) { - *str = p; - } else { - free (*str); - *str = NULL; - *size = 0; - return -1; - } - - va_start (ap, format); - } - - va_end (ap); - - return retval; -} - -#ifdef BUILD_URI_TEST - -static int -_uri_cmp (const struct uri* a, const struct uri* b) -{ - int differenciesCount = 0; - - if (a == NULL || b == NULL) { - return -1; - } - - // if ( (strcmp((a->scheme) ? a->scheme : "", (b->scheme) ? b->scheme : "") != 0 ) ) { - // differenciesCount++; - // } - if ((strcmp ((a->userinfo) ? a->userinfo : "", (b->userinfo) ? b->userinfo : "") != 0)) { - differenciesCount++; - } - if ((strcmp ((a->user) ? a->user : "", (b->user) ? b->user : "") != 0)) { - differenciesCount++; - } - if ((strcmp ((a->pass) ? a->pass : "", (b->pass) ? b->pass : "") != 0)) { - differenciesCount++; - } - if ((strcmp ((a->host) ? a->host : "", (b->host) ? b->host : "") != 0)) { - differenciesCount++; - } - if ((strcmp ((a->path) ? a->path : "", (b->path) ? b->path : "") != 0)) { - differenciesCount++; - } - if ((strcmp ((a->query) ? a->query : "", (b->query) ? b->query : "") != 0)) { - differenciesCount++; - } - if ((strcmp ((a->fragment) ? a->fragment : "", (b->fragment) ? b->fragment : "") != 0)) { - differenciesCount++; - } - if (a->port != b->port) { - differenciesCount++; - } - if (a->scheme_t != b->scheme_t) { - differenciesCount++; - } - if (a->flags != b->flags) { - differenciesCount++; - } - - return differenciesCount; -} - -static void -_uri_dump_diff (struct uri* a, struct uri* b, int totalDifferencies) -{ - int differenciesCount = 0; - - if (a == NULL || b == NULL) { - return; - } - - // if ( (strcmp((a->scheme) ? a->scheme : "", (b->scheme) ? b->scheme : "") != 0 ) ) { - // printf(" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .scheme : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->scheme, b->scheme ); - // } - if ((strcmp ((a->userinfo) ? a->userinfo : "", (b->userinfo) ? b->userinfo : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .userinfo : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->userinfo, b->userinfo); - } - if ((strcmp ((a->user) ? a->user : "", (b->user) ? b->user : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .user : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->user, b->user); - } - if ((strcmp ((a->pass) ? a->pass : "", (b->pass) ? b->pass : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .pass : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->pass, b->pass); - } - if ((strcmp ((a->host) ? a->host : "", (b->host) ? b->host : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .host : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->host, b->host); - } - if ((strcmp ((a->path) ? a->path : "", (b->path) ? b->path : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .path : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->path, b->path); - } - if ((strcmp ((a->query) ? a->query : "", (b->query) ? b->query : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .query : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->query, b->query); - } - if ((strcmp ((a->fragment) ? a->fragment : "", (b->fragment) ? b->fragment : "") != 0)) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .fragment : \"%s\" (expected: \"%s\")\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->fragment, b->fragment); - } - - if (a->port != b->port) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .port : %i (expected: %i)\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->port, b->port); - } - if (a->scheme_t != b->scheme_t) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .scheme_t : %i (expected: %i)\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->scheme_t, b->scheme_t); - } - if (a->flags != b->flags) { - printf (" \x1b[38;5;242m\u2502\x1b[0m \x1b[38;5;124m%s .flags : %i (expected: %i)\n", (++differenciesCount < totalDifferencies) ? "\u251c\u2500\u2500\u25fb" : "\u2514\u2500\u2500\u25fb", a->flags, b->flags); - } -} - -static int -_uri_test (const char* uristr, enum uri_option optflags, struct uri expectedRes, int line) -{ - struct uri* uri = uriParse (uristr, optflags); - - int differenciesCount = 0; - - if ((differenciesCount = _uri_cmp (uri, &expectedRes)) == 0) { - printf ("\x1b[38;5;242m"); // dark gray - printf ("%05i", line); - printf ("\x1b[0m"); - - printf ("\x1b[38;5;242m %s \x1b[0m", "\u2502"); - - printf ("\x1b[38;5;120m"); // green - printf ("[ok] "); - printf ("\x1b[0m"); - - printf ("\x1b[38;5;242m"); // dark gray - printf ("%s", uristr); - printf ("\x1b[0m"); - - printf ("\n"); - } else { - printf ("\x1b[38;5;124m"); // red - printf ("%05i", line); - printf ("\x1b[0m"); - - printf ("\x1b[38;5;242m %s \x1b[0m", "\u2502"); - - printf ("\x1b[38;5;124m"); // red - printf ("[er] "); - printf ("\x1b[0m"); - - printf ("\x1b[38;5;242m"); // dark gray - printf ("%s", uristr); - printf ("\x1b[0m"); - - printf ("\n"); - - printf ("\x1b[38;5;124m"); // red - _uri_dump_diff (uri, &expectedRes, differenciesCount); - printf ("\x1b[0m"); - - printf (" \x1b[38;5;242m\u2502\x1b[0m\n"); - } - - uriFree (uri); - - return differenciesCount; -} - -int -main (void) -{ - int rc = 0; - - // rc += _uri_test( "", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_UNKNOWN, .host = NULL, .port = 0, .path = NULL, .query = NULL, .fragment = NULL }, __LINE__ ); - rc += _uri_test ("https://www.server.com", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = NULL, .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://user:pass@www.server.com", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .userinfo = "user:pass", .user = "user", .pass = "pass", .host = "www.server.com", .port = 0, .path = NULL, .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("HTTPS://www.server.com", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = NULL, .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("hTtPs://www.server.com", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = NULL, .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com:8080", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 8080, .path = NULL, .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com:8080?foo=bar", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 8080, .path = NULL, .query = "foo=bar", .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com:8080#anchor", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 8080, .path = NULL, .query = NULL, .fragment = "anchor", .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com/", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com/?foo=bar", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/", .query = "foo=bar", .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com/////?foo=bar", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/", .query = "foo=bar", .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com///////", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com?foo=bar", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = NULL, .query = "foo=bar", .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com#anchor", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = NULL, .query = NULL, .fragment = "anchor", .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com/path/to/file.html?foo=bar&foo2=bar2#anchor", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/path/to/file.html", .query = "foo=bar&foo2=bar2", .fragment = "anchor", .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com:80/", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 80, .path = "/", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com:/", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com:", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - - rc += _uri_test ("https://[8:3:1:2:1234:5678::]:8080/ipv6", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "8:3:1:2:1234:5678::", .port = 8080, .path = "/ipv6", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 }, __LINE__); - rc += _uri_test ("https://[2001:db8:0:85a3::ac1f:8001]:8080/ipv6", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "2001:db8:0:85a3::ac1f:8001", .port = 8080, .path = "/ipv6", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 }, __LINE__); - rc += _uri_test ("https://user:pass@[2001:db8:3333:4444:5555:6666:1.2.3.4]:8080/ipv6", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .userinfo = "user:pass", .user = "user", .pass = "pass", .host = "2001:db8:3333:4444:5555:6666:1.2.3.4", .port = 8080, .path = "/ipv6", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 }, __LINE__); - rc += _uri_test ("https://192.168.0.1:8080/ipv4", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "192.168.0.1", .port = 8080, .path = "/ipv4", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV4 }, __LINE__); - rc += _uri_test ("https://127.0.0.1:8080/ipv4loopback", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "127.0.0.1", .port = 8080, .path = "/ipv4loopback", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV4 | URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("https://localhost:8080/loopback", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "localhost", .port = 8080, .path = "/loopback", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("https://[0:0:0:0:0:0:0:1]:8080/ipv6loopback", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "0:0:0:0:0:0:0:1", .port = 8080, .path = "/ipv6loopback", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 | URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("https://[::0:0:0:1]:8080/ipv6loopback", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "::0:0:0:1", .port = 8080, .path = "/ipv6loopback", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 | URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("https://[::0:0000:0:001]:8080/ipv6loopback", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "::0:0000:0:001", .port = 8080, .path = "/ipv6loopback", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 | URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("https://[::1]:8080/ipv6loopback", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "::1", .port = 8080, .path = "/ipv6loopback", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV6 | URI_T_LOCALHOST }, __LINE__); - - rc += _uri_test ("https://user:pass@192.168.0.1:8080/ipv4", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .userinfo = "user:pass", .user = "user", .pass = "pass", .host = "192.168.0.1", .port = 8080, .path = "/ipv4", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV4 }, __LINE__); - - rc += _uri_test ("file://///C:/windows/path", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/windows/path", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file:C:/windows/path", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/windows/path", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file:/C:/windows/path", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/windows/path", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file:///C:/windows/path", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/windows/path", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file://?/C:/windows/path", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/windows/path", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file://./C:/windows/path", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/windows/path", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - - // Examples from AAF files external essences - rc += _uri_test ("file:///C:/Users/username/Downloads/441-16b.wav", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/Users/username/Downloads/441-16b.wav", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file://?/E:/ADPAAF/Sequence A Rendu.mxf", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "E:/ADPAAF/Sequence A Rendu.mxf", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file:////C:/Users/username/Desktop/TEST2977052.aaf", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "C:/Users/username/Desktop/TEST2977052.aaf", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file://localhost/Users/username/Music/fonk_2_3#04.wav", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = "localhost", .port = 0, .path = "/Users/username/Music/fonk_2_3#04.wav", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - rc += _uri_test ("file://10.87.230.71/mixage/DR2/Avid MediaFiles/MXF/1/3572607.mxf", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = "10.87.230.71", .port = 0, .path = "/mixage/DR2/Avid MediaFiles/MXF/1/3572607.mxf", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_IPV4 }, __LINE__); - rc += _uri_test ("file:///_system/Users/username/pt2MCCzmhsFRHQgdgsTMQX.mxf", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_FILE, .host = NULL, .port = 0, .path = "/_system/Users/username/pt2MCCzmhsFRHQgdgsTMQX.mxf", .query = NULL, .fragment = NULL, .flags = URI_T_LOCALHOST }, __LINE__); - - // URL Percent Decoding - rc += _uri_test ("https://www.server.com/NON_DECODING/%C2%B0%2B%29%3D%C5%93%21%3A%3B%2C%3F.%2F%C2%A7%C3%B9%2A%24%C2%B5%C2%A3%7D%5D%E2%80%9C%23%7B%5B%7C%5E%40%5D%3C%3E", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/NON_DECODING/%C2%B0%2B%29%3D%C5%93%21%3A%3B%2C%3F.%2F%C2%A7%C3%B9%2A%24%C2%B5%C2%A3%7D%5D%E2%80%9C%23%7B%5B%7C%5E%40%5D%3C%3E", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com/DECODING/%C2%B0%2B%29%3D%C5%93%21%3A%3B%2C%3F.%2F%C2%A7%C3%B9%2A%24%C2%B5%C2%A3%7D%5D%E2%80%9C%23%7B%5B%7C%5E%40%5D%3C%3E", URI_OPT_DECODE_ALL, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .host = "www.server.com", .port = 0, .path = "/DECODING/°+)=œ!:;,?./§ù*$µ£}]“#{[|^@]<>", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - rc += _uri_test ("https://www.server.com/DECODING_UTF8/%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E7%B2%BE%E5%BA%A6%E7%B7%A8%E9%9B%86", URI_OPT_DECODE_ALL, (struct uri){ .scheme_t = URI_SCHEME_T_HTTPS, .userinfo = NULL, .user = NULL, .pass = NULL, .host = "www.server.com", .port = 0, .path = "/DECODING_UTF8/サンプル精度編集", .query = NULL, .fragment = NULL, .flags = URI_T_HOST_REGNAME }, __LINE__); - - // Examples from https://en.wikipedia.org/wiki/Uniform_Resource_Identifier - rc += _uri_test ("tel:+1-816-555-1212", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_TEL, .userinfo = NULL, .user = NULL, .pass = NULL, .host = NULL, .port = 0, .path = "+1-816-555-1212", .query = NULL, .fragment = NULL, .flags = 0 }, __LINE__); - rc += _uri_test ("mailto:John.Doe@example.com", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_MAILTO, .userinfo = NULL, .user = NULL, .pass = NULL, .host = NULL, .port = 0, .path = "John.Doe@example.com", .query = NULL, .fragment = NULL, .flags = 0 }, __LINE__); - rc += _uri_test ("urn:oasis:names:specification:docbook:dtd:xml:4.1.2", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_UNKNOWN, .userinfo = NULL, .user = NULL, .pass = NULL, .host = NULL, .port = 0, .path = "oasis:names:specification:docbook:dtd:xml:4.1.2", .query = NULL, .fragment = NULL, .flags = 0 }, __LINE__); - rc += _uri_test ("ldap://[2001:db8::7]/c=GB?objectClass?one", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_UNKNOWN, .userinfo = NULL, .user = NULL, .pass = NULL, .host = "2001:db8::7", .port = 0, .path = "/c=GB", .query = "objectClass?one", .fragment = NULL, .flags = URI_T_HOST_IPV6 }, __LINE__); - rc += _uri_test ("news:comp.infosystems.www.servers.unix", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_UNKNOWN, .userinfo = NULL, .user = NULL, .pass = NULL, .host = NULL, .port = 0, .path = "comp.infosystems.www.servers.unix", .query = NULL, .fragment = NULL, .flags = 0 }, __LINE__); - - // rc += _uri_test( "xxxxxxxx", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_UNKNOWN, .userinfo = NULL, .user = NULL, .pass = NULL, .host = NULL, .port = 0, .path = NULL, .query = NULL, .fragment = NULL, .flags = 0 }, __LINE__ ); - // rc += _uri_test( "xxxxxxxx", URI_OPT_NONE, (struct uri){ .scheme_t = URI_SCHEME_T_UNKNOWN, .userinfo = NULL, .user = NULL, .pass = NULL, .host = NULL, .port = 0, .path = NULL, .query = NULL, .fragment = NULL, .flags = 0 }, __LINE__ ); - - return rc; -} - -#endif // BUILD_URI_TEST diff --git a/libs/aaf/aaf/AAFCore.h b/libs/aaf/aaf/AAFCore.h index 0e081197b1..91a06f3836 100644 --- a/libs/aaf/aaf/AAFCore.h +++ b/libs/aaf/aaf/AAFCore.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -119,15 +119,17 @@ typedef struct aafPropertyDefinition { aafBoolean_t meta; - wchar_t* name; + char* name; /* * Looks like nobody cares about AAF standard TypeDefinition. All observed files * had incorrect values for Type's Name and Identification, even Avid's files. - * Thus, PDef->type should NOT be trusted + * Thus, PDef->type should NOT be trusted. + * + * TODO: Should be set by attachNewProperty() in AAFClass.c */ - aafUID_t type; // TODO: Should be set by attachNewProperty() in AAFClass.c + aafUID_t type; /** * Pointer to the next aafPropertyDef in the list. @@ -183,7 +185,7 @@ typedef struct aafclass { * A Class is #CONCRETE if it can be retrieved as an * object. Else, a Class is #ABSTRACT if it can't be * directly retrieved and can only be inherited by - * another Class, so only its memebers can be retrieved. + * another Class, so only its members can be retrieved. */ aafBoolean_t isConcrete; @@ -206,7 +208,8 @@ typedef struct aafclass { aafBoolean_t meta; - wchar_t* name; // this is set at runtime + /* name is set at runtime */ + char* name; /** * Pointer to the next Class in the AAF_Data.Class list. @@ -297,10 +300,10 @@ typedef struct aafObject { cfbNode* Node; /** - * The name of the Node in the Compound File Tree : cfbNode._ab. + * UTF-8 name of the Node in the Compound File Tree, set from cfbNode._ab. */ - wchar_t Name[CFB_NODE_NAME_SZ]; + char* Name; /** * Pointer to an aafProperty list. This list holds the retrieved @@ -362,7 +365,8 @@ typedef struct aafObject { struct aafObject* nextObj; - struct _aafData* aafd; // only to access aafd->verb + /* keeps track of aafd, mostly to access aafd->verb without having to pass aafd to some functions */ + struct _aafData* aafd; } aafObject; @@ -416,14 +420,14 @@ typedef struct _aafData { struct Identification { aafObject* obj; - wchar_t* CompanyName; - wchar_t* ProductName; + char* CompanyName; + char* ProductName; aafProductVersion_t* ProductVersion; - wchar_t* ProductVersionString; + char* ProductVersionString; aafUID_t* ProductID; aafTimeStamp_t* Date; aafProductVersion_t* ToolkitVersion; - wchar_t* Platform; + char* Platform; aafUID_t* GenerationAUID; } Identification; @@ -542,7 +546,7 @@ typedef struct _aafData { aafObject* TaggedValueDefinition; - struct dbg* dbg; + struct aafLog* log; } AAF_Data; @@ -586,7 +590,10 @@ typedef struct _aafData { */ #define aafRationalToFloat(r) \ - (((r).denominator == 0) ? 0 : ((float)(r).numerator / (r).denominator)) + (((r).denominator == 0) ? 0 : ((float)(r).numerator / (float)(r).denominator)) + +#define aafRationalToDouble(r) \ + (((r).denominator == 0) ? 0 : ((double)(r).numerator / (r).denominator)) /** * Converts an aafRational_t to a int64 number. @@ -596,6 +603,25 @@ typedef struct _aafData { #define aafRationalToint64(r) \ (((r).denominator == 0) ? 0 : (int64_t) ((r).numerator / (r).denominator)) +/** + * Loops through each aafPropertyIndexEntry_t of a "properties" node stream. + * + * @param Header Pointer to the stream's aafPropertyIndexHeader_t struct. + * @param Entry Pointer that will receive each aafPropertyIndexEntry_t struct. + * @param Value Pointer to each property's data value, of aafPropertyIndexEntry_t._length + * bytes length. + * @param i uint32_t iterator. + */ + +#define foreachPropertyEntry(propStream, Header, Entry, Value, valueOffset, i) \ + for (valueOffset = sizeof (aafPropertyIndexHeader_t) + (Header._entryCount * sizeof (aafPropertyIndexEntry_t)), \ + i = 0; \ + i < Header._entryCount && \ + memcpy (&Entry, (propStream + ((sizeof (aafPropertyIndexHeader_t)) + (sizeof (aafPropertyIndexEntry_t) * i))), sizeof (aafPropertyIndexEntry_t)) && \ + (Value = propStream + valueOffset); \ + valueOffset += Entry._length, \ + i++) + /** * @name Initialisation functions * @{ @@ -608,7 +634,7 @@ typedef struct _aafData { */ AAF_Data* -aaf_alloc (struct dbg* dbg); +aaf_alloc (struct aafLog* log); /** * Loads an AAF file and sets the AAF_Data sructure accordingly. @@ -661,7 +687,7 @@ aaf_release (AAF_Data** aafd); * @return Pointer to a null-terminated string holding the Object's path. */ -wchar_t* +char* aaf_get_ObjectPath (aafObject* Obj); /** @@ -680,6 +706,21 @@ aafObject* aaf_get_ObjectByWeakRef (aafObject* list, aafWeakRef_t* ref); +aafUID_t* +aaf_get_InterpolationIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* InterpolationDefWeakRef); +aafUID_t* +aaf_get_OperationIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* OperationDefWeakRef); +aafUID_t* +aaf_get_ContainerIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* ContainerDefWeakRef); +aafUID_t* +aaf_get_DataIdentificationByWeakRef (AAF_Data* aafd, aafWeakRef_t* DataDefWeakRef); + +aafObject* +aaf_get_ObjectAncestor (aafObject* Obj, const aafUID_t* ClassID); + +int +aaf_ObjectInheritsClass (aafObject* Obj, const aafUID_t* classID); + /** * Retrieves a Mob Object by its given MobID. * @@ -698,6 +739,9 @@ aafObject* aaf_get_MobSlotBySlotID (aafObject* MobSlots, aafSlotID_t SlotID); +aafObject* +aaf_get_EssenceDataByMobID (AAF_Data* aafd, aafMobID_t* MobID); + /** * Loops through each aafObject of a list, that is of a Set or Vector. It is also * possible to filter the returned Object by ClassID. @@ -724,9 +768,12 @@ _aaf_foreach_ObjectInSet (aafObject** Obj, * be used istead of directly calling _aaf_foreach_ObjectInSet(). */ -#define aaf_foreach_ObjectInSet(Obj, head, filter) \ +#define AAF_foreach_ObjectInSet(Obj, head, filter) \ while (_aaf_foreach_ObjectInSet (Obj, head, filter)) +void* +aaf_get_TaggedValueByName (AAF_Data* aafd, aafObject* TaggedValueVector, const char* name, const aafUID_t* type); + /** * Retrieves an Object property by ID. * @@ -741,6 +788,9 @@ aafProperty* aaf_get_property (aafObject* Obj, aafPID_t pid); +aafUID_t* +aaf_get_ParamDefIDByName (AAF_Data* aafd, const char* name); + /** * Retrieves a Property ID by its name. * @@ -752,8 +802,11 @@ aaf_get_property (aafObject* Obj, */ aafPID_t -aaf_get_PropertyIDByName (AAF_Data* aafd, - const wchar_t* name); +aaf_get_PropertyIDByName (AAF_Data* aafd, + const char* name); + +aafUID_t* +aaf_get_OperationDefIDByName (AAF_Data* aafd, const char* OpDefName); /** * Retrieves an Object property by ID, and returns its value. @@ -781,7 +834,7 @@ aaf_get_propertyValue (aafObject* Obj, /** * Safely get an Indirect value, after it was retrieved using aaf_get_propertyValue(). * Function checks value type and in case of AAFTypeID_String, performs allocation - * and conversion to system wchar_t*. + * and UTF8 conversion. * * Caller must free the returned value, only if Indirect is of type * AAFTypeID_String. @@ -790,7 +843,7 @@ aaf_get_propertyValue (aafObject* Obj, * @param Indirect Pointer to the Indirect structure. * @param typeDef Type definition expected from the Indirect. * - * @return A pointer to the Indirect value, or a pointer to an allocated wchar_t if Indirect is AAFTypeID_String\n + * @return A pointer to the Indirect value, or a pointer to an allocated char if Indirect is AAFTypeID_String\n * NULL in case of error. */ diff --git a/libs/aaf/aaf/AAFDump.h b/libs/aaf/aaf/AAFDump.h index 9ced4b6ad7..be21ded606 100644 --- a/libs/aaf/aaf/AAFDump.h +++ b/libs/aaf/aaf/AAFDump.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -26,27 +26,30 @@ #include "aaf/LibCFB.h" void -aaf_dump_Header (AAF_Data* aafd); +aaf_dump_Header (AAF_Data* aafd, const char* padding); void -aaf_dump_Identification (AAF_Data* aafd); +aaf_dump_Identification (AAF_Data* aafd, const char* padding); void -aaf_dump_rawProperties (AAF_Data* aafd, aafByte_t* propStream); +aaf_dump_rawProperties (AAF_Data* aafd, aafByte_t* propStream, const char* padding); void -aaf_dump_ObjectProperty (AAF_Data* aafd, aafProperty* Prop); +aaf_dump_ObjectProperty (AAF_Data* aafd, aafProperty* Prop, const char* padding); void -aaf_dump_ObjectProperties (AAF_Data* aafd, aafObject* Obj); +aaf_dump_ObjectProperties (AAF_Data* aafd, aafObject* Obj, const char* padding); void -aaf_dump_nodeStreamProperties (AAF_Data* aafd, cfbNode* node); +aaf_dump_TaggedValueSet (AAF_Data* aafd, aafObject* ObjCollection, const char* padding); void -aaf_dump_MetaDictionary (AAF_Data* aafd); +aaf_dump_nodeStreamProperties (AAF_Data* aafd, cfbNode* node, const char* padding); void -aaf_dump_Classes (AAF_Data* aafd); +aaf_dump_MetaDictionary (AAF_Data* aafd, const char* padding); + +void +aaf_dump_Classes (AAF_Data* aafd, const char* padding); #endif // ! __AAFDump_h__ diff --git a/libs/aaf/aaf/AAFIEssenceFile.h b/libs/aaf/aaf/AAFIEssenceFile.h new file mode 100644 index 0000000000..a3b020f118 --- /dev/null +++ b/libs/aaf/aaf/AAFIEssenceFile.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017-2024 Adrien Gesta-Fline + * + * This file is part of libAAF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __AAFIEssenceFile_h__ +#define __AAFIEssenceFile_h__ + +/** + * @file LibAAF/AAFIface/AAFIEssenceFile.h + * @brief AAF processing + * @author Adrien Gesta-Fline + * @version 0.1 + * @date 27 june 2024 + * + * @ingroup AAFIface + * @addtogroup AAFIface + * @{ + */ + +#include "aaf/AAFIface.h" + +char* +aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_filepath, const char* search_location); + +/** + * Extract audio essence file. + * + * @param aafi XXXXXX + */ +int +aafi_extractAudioEssenceFile (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFile, enum aafiExtractFormat extractFormat, const char* outfilepath, uint64_t sampleOffset, uint64_t sampleLength, const char* forcedFileName, char** usable_file_path); + +int +aafi_extractAudioClip (AAF_Iface* aafi, aafiAudioClip* audioClip, enum aafiExtractFormat extractFormat, const char* outfilepath); + +int +aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFile); + +int +aafi_build_unique_audio_essence_name (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFile); + +/** + * @} + */ +#endif // !__AAFIEssenceFile_h__ diff --git a/libs/aaf/aaf/AAFIParser.h b/libs/aaf/aaf/AAFIParser.h index 304894bb92..729023920b 100644 --- a/libs/aaf/aaf/AAFIParser.h +++ b/libs/aaf/aaf/AAFIParser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -50,8 +50,6 @@ typedef struct trace_dump { int lv; // current level int* ll; // level loop : each entry correspond to a level and tell if there is more to print int eob; // end of branch - int hc; // have children - int sub; } td; #define __td_set(__td, __ptd, offset) \ @@ -60,26 +58,28 @@ typedef struct trace_dump { __td.lv = __ptd->lv + offset; \ __td.ll = __ptd->ll; \ __td.ll[__td.lv] = (offset > 0) ? 0 : __td.ll[__td.lv]; \ - __td.eob = 0; \ - __td.hc = 0; \ - __td.sub = 0; + __td.eob = (offset) ? 0 : __ptd->eob; -#define DUMP_OBJ(aafi, Obj, __td) \ - aafi_dump_obj (aafi, Obj, __td, TD_OK, __LINE__, ""); +#define TRACE_OBJ(aafi, Obj, __td) \ + aafi_dump_obj (aafi, Obj, __td, TD_OK, __func__, __LINE__, ""); -#define DUMP_OBJ_INFO(aafi, Obj, __td, ...) \ - aafi_dump_obj (aafi, Obj, __td, TD_OK, __LINE__, __VA_ARGS__); +#define TRACE_OBJ_INFO(aafi, Obj, __td, ...) \ + aafi_dump_obj (aafi, Obj, __td, TD_INFO, __func__, __LINE__, __VA_ARGS__); -#define DUMP_OBJ_WARNING(aafi, Obj, __td, ...) \ - aafi_dump_obj (aafi, Obj, __td, TD_WARNING, __LINE__, __VA_ARGS__); +#define TRACE_OBJ_WARNING(aafi, Obj, __td, ...) \ + aafi_dump_obj (aafi, Obj, __td, TD_WARNING, __func__, __LINE__, __VA_ARGS__); -#define DUMP_OBJ_ERROR(aafi, Obj, __td, ...) \ - (__td)->eob = 1; \ - aafi_dump_obj (aafi, Obj, __td, TD_ERROR, __LINE__, __VA_ARGS__); +#define TRACE_OBJ_ERROR(aafi, Obj, __td, ...) \ + (__td)->eob = 1; \ + aafi_dump_obj (aafi, Obj, __td, TD_ERROR, __func__, __LINE__, __VA_ARGS__); -#define DUMP_OBJ_NO_SUPPORT(aafi, Obj, __td) \ - (__td)->eob = 1; \ - aafi_dump_obj_no_support (aafi, Obj, __td, __LINE__); +#define TRACE_OBJ_NO_SUPPORT(aafi, Obj, __td) \ + aafi_dump_obj (aafi, Obj, __td, TD_NOT_SUPPORTED, __func__, __LINE__, ""); + +#define AAFI_foreach_ObjectInSet(Obj, head, i, __td) \ + i = 0; \ + while (_aaf_foreach_ObjectInSet (Obj, head, NULL) && \ + (__td.ll[__td.lv] = (head->Header->_entryCount > 1) ? (int)(head->Header->_entryCount - i++) : 0) >= 0) int aafi_retrieveData (AAF_Iface* aafi); @@ -90,15 +90,9 @@ aafi_retrieveData (AAF_Iface* aafi); */ void -aafi_dump_obj (AAF_Iface* aafi, aafObject* Obj, struct trace_dump* __td, int state, int line, const char* fmt, ...); - -void -aafi_dump_obj_no_support (AAF_Iface* aafi, aafObject* Obj, struct trace_dump* __td, int line); +aafi_dump_obj (AAF_Iface* aafi, aafObject* Obj, struct trace_dump* __td, int state, const char* func, int line, const char* fmt, ...); void aafi_trace_obj (AAF_Iface* aafi, aafObject* Obj, const char* color); -int -aafi_parse_Segment (AAF_Iface* aafi, aafObject* Segment, td* __ptd); - #endif // !__AAFIParser_h__ diff --git a/libs/aaf/aaf/AAFIface.h b/libs/aaf/aaf/AAFIface.h index 993f926c26..9ad3785986 100644 --- a/libs/aaf/aaf/AAFIface.h +++ b/libs/aaf/aaf/AAFIface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -42,7 +42,13 @@ enum aafiEssenceType { AAFI_ESSENCE_TYPE_WAVE = 0x02, AAFI_ESSENCE_TYPE_AIFC = 0x03, AAFI_ESSENCE_TYPE_BWAV = 0x04, - AAFI_ESSENCE_TYPE_UNK = 0xff, /* non-pcm */ + AAFI_ESSENCE_TYPE_UNK = 0xff /* non-pcm */ +}; + +enum aafiExtractFormat { + AAFI_EXTRACT_DEFAULT = 0, + AAFI_EXTRACT_WAV, + AAFI_EXTRACT_BWAV }; /** @@ -50,8 +56,8 @@ enum aafiEssenceType { */ typedef enum aafiAudioGain_e { - AAFI_AUDIO_GAIN_CONSTANT = 1 << 0, //0x0001 - AAFI_AUDIO_GAIN_VARIABLE = 1 << 1, //0x0002 + AAFI_AUDIO_GAIN_CONSTANT = 1 << 0, + AAFI_AUDIO_GAIN_VARIABLE = 1 << 1, } aafiAudioGain_e; @@ -63,12 +69,12 @@ typedef enum aafiAudioGain_e { */ typedef enum aafiTransition_e { - AAFI_TRANS_SINGLE_CURVE = 1 << 4, //0x0010 - AAFI_TRANS_TWO_CURVE = 1 << 5, //0x0020 + AAFI_TRANS_SINGLE_CURVE = 1 << 4, + AAFI_TRANS_TWO_CURVE = 1 << 5, - AAFI_TRANS_FADE_IN = 1 << 6, //0x0040 - AAFI_TRANS_FADE_OUT = 1 << 7, //0x0080 - AAFI_TRANS_XFADE = 1 << 8, //0x0100 + AAFI_TRANS_FADE_IN = 1 << 6, + AAFI_TRANS_FADE_OUT = 1 << 7, + AAFI_TRANS_XFADE = 1 << 8, } aafiTransition_e; @@ -83,17 +89,16 @@ typedef enum aafiTransition_e { */ typedef enum aafiInterpolation_e { - AAFI_INTERPOL_NONE = 1 << 10, //0x0400 - AAFI_INTERPOL_LINEAR = 1 << 11, //0x0800 - AAFI_INTERPOL_LOG = 1 << 12, //0x1000 - AAFI_INTERPOL_CONSTANT = 1 << 13, //0x2000 - AAFI_INTERPOL_POWER = 1 << 14, //0x4000 - AAFI_INTERPOL_BSPLINE = 1 << 15, //0x8000 + AAFI_INTERPOL_NONE = 1 << 10, + AAFI_INTERPOL_LINEAR = 1 << 11, + AAFI_INTERPOL_LOG = 1 << 12, + AAFI_INTERPOL_CONSTANT = 1 << 13, + AAFI_INTERPOL_POWER = 1 << 14, + AAFI_INTERPOL_BSPLINE = 1 << 15, } aafiInterpolation_e; -#define AAFI_INTERPOL_MASK ( \ - AAFI_INTERPOL_NONE | AAFI_INTERPOL_LINEAR | AAFI_INTERPOL_LOG | AAFI_INTERPOL_CONSTANT | AAFI_INTERPOL_POWER | AAFI_INTERPOL_BSPLINE) +#define AAFI_INTERPOL_MASK (unsigned)(AAFI_INTERPOL_NONE | AAFI_INTERPOL_LINEAR | AAFI_INTERPOL_LOG | AAFI_INTERPOL_CONSTANT | AAFI_INTERPOL_POWER | AAFI_INTERPOL_BSPLINE) /** * Specifies a Transition that can be a fade in, a fade out or a Cross fade, and that can @@ -109,12 +114,14 @@ typedef enum aafiInterpolation_e { */ typedef struct aafiTransition { + struct aafiTimelineItem* timelineItem; + /** * Should hold the transition type (either single param or two param), * the transition fade type (in, out, x) and the interpolation used. */ - int flags; + uint32_t flags; /** * Length of the transition, in edit units. @@ -205,8 +212,8 @@ typedef struct aafiAudioGain { * the interpolation used to calculate the values between two time points. */ - uint16_t flags; // Type : Constant (single multiplier for entire clip) or - // Variable (automation) + uint32_t flags; // Type : Constant (single multiplier for entire clip) or + // Variable (automation) // Interpolation : Linear, Log, Constant, Power, BSpline /** @@ -214,7 +221,7 @@ typedef struct aafiAudioGain { * gain automation, and is consequently the size of time[] and value[] arrays. */ - int64_t pts_cnt; + unsigned int pts_cnt; /** * Array of time points, where the corresponding level value should apply. @@ -234,65 +241,130 @@ typedef struct aafiAudioGain { typedef struct aafiAudioGain aafiAudioPan; -typedef struct aafiAudioEssence { - wchar_t* original_file_path; // NetworkLocator::URLString the original external essence URI holded in AAF - wchar_t* usable_file_path; // Holds a real usable file path, once an embedded essence has been extracted, or once en external essence has been found. - wchar_t* file_name; // MasterMob::Name the original file name. Might be NULL if MasterMob has no name. One should always use unique_file_name which is guaranted to be set. - wchar_t* unique_file_name; // unique name generated from file_name. Sometimes, multiple files share the same names so this unique name should be used on export. +typedef struct aafiMetaData { + char* name; - uint16_t clip_count; // number of clips using this essence + char* text; - /* - * total samples for 1 channel (no matter channel count). - * Might be retrieved from FileDescriptor::Length property, - * or from WAV/AIFF summary or file : - * (data chunk size / channels / samplesize / 8) + struct aafiMetaData* next; + +} aafiMetaData; + +/** + * Describe a single audio essence file. + */ +typedef struct aafiAudioEssenceFile { + /** + * Holds the name of essence file, as specified in MasterMob::Name. + * This is usually the name exposed in the original software. + * This name *might* not be unique accross all essences. For a + * unique name, use #aafiAudioEssenceFile.unique_name instead. */ - uint64_t length; - cfbNode* node; // The node holding the audio stream if embedded + char* name; + + /** + * This is the same as #aafiAudioEssenceFile.name, but this one is guaranted to + * be unique. If an AAF has different essence files sharing the same name, + * then libaaf will add a suffix to unique_name. Thus, unique_name can be used + * instead of name when exporting embedded essences. + */ + + char* unique_name; // TODO: see creative_post.aaf + + /** + * Holds the URI path to the essence file, as specified in NetworkLocator::URLString. + * This path is *not* uri-decoded. + */ + + char* original_file_path; + + /** + * Holds a usable filepath to the essence file. It is set, either when an + * embedded essence has been extracted using aafi_extractAudioEssenceFile() or + * when an external essence file has been successfully located by libaaf. + */ + + char* usable_file_path; + + /** + * Total sample count for 1 audio channel (no matter channel count). + * + * Might be retrieved from FileDescriptor::Length property, or from WAV/AIFF + * summary or file : `data chunk size / channels / samplesize / 8` + * + * `duration = length / samplerate` + */ + + aafPosition_t length; + + /** + * Data stream CFB node, containing essence data if it's embedded. + */ + + cfbNode* node; + + /** + * Flag to tell if essence data is embedded or external. It is set only if + * FileSourceMob contains EssenceData. + */ + + uint8_t is_embedded; + + aafObject* SourceMob; + aafMobID_t* sourceMobID; // Holds the SourceMob Mob::ID references this EssenceData + uint32_t sourceMobSlotID; // SlotID of the MobSlot inside MasterMob (CompoMob's Sequence SourceClip::SourceMobSlotID) + aafRational_t* sourceMobSlotEditRate; + aafPosition_t sourceMobSlotOrigin; // SourceMob TimelineMobSlot::Origin - aafMobID_t* sourceMobID; // Holds the SourceMob Mob::ID references this EssenceData - uint32_t sourceMobSlotID; // SlotID of the MobSlot inside MasterMob (CompoMob's Sequence SourceClip::SourceMobSlotID) aafMobID_t* masterMobID; // Holds the MasterMob Mob::ID (used by CompoMob's Sequence SourceClip::SourceID) uint32_t masterMobSlotID; // SlotID of the MobSlot inside MasterMob (CompoMob's Sequence SourceClip::SourceMobSlotID) - aafObject* SourceMob; - enum aafiEssenceType type; // depends on PCMDescriptor WAVEDescriptor AIFCDescriptor - /* - * is only set if FileSourceMob contains EssenceData - */ - uint8_t is_embedded; - aafProperty* summary; // WAVEDescriptor AIFCDescriptor + uint64_t pcm_audio_start_offset; - // uint32_t format; uint32_t samplerate; aafRational_t* samplerateRational; // eg. { 48000, 1 } - int16_t samplesize; - int16_t channels; + uint16_t samplesize; - aafRational_t* mobSlotEditRate; + /** + * Audio essence file channel count. Might be different of #aafiAudioClip.channels + */ + uint16_t channels; // BWF BEXT chunk data char description[256]; char originator[32]; // could be set with header::ProductName char originatorReference[32]; - uint64_t timeReference; // SourceMob TimelineMobSlot::Origin + aafPosition_t timeReference; // SourceMob TimelineMobSlot::Origin unsigned char umid[64]; // SourceMob::MobID (32 Bytes, basic form) char originationDate[10 + 1]; // SourceMob::CreationDate char originationTime[8 + 1]; // SourceMob::CreationTime - void* user; - // TODO peakEnveloppe - struct aafiAudioEssence* next; // aafi->Audio->essences -} aafiAudioEssence; + /** + * Metadata retrieved from main MasterMob::UserComments + */ + aafiMetaData* metadata; + void* user; + + /** + * Pointer to the next essence in global essence list #aafiAudio.essenceFiles + */ + + struct aafiAudioEssenceFile* next; + +} aafiAudioEssenceFile; + +/** + * aafiAudioEssencePointer is used by aafiAudioClip, to points to one or more + * aafiAudioEssenceFile and specify which channel of essence file the clip uses. + */ typedef struct aafiAudioEssencePointer { - aafiAudioEssence* essence; // single essence, not list ! - int essenceChannel; // channel selector inside multichannel essence. If zero, then all essence channels must be used. + aafiAudioEssenceFile* essenceFile; + uint32_t essenceChannel; // channel selector inside multichannel essence. If zero, then all essence channels must be used. void* user; @@ -304,12 +376,12 @@ typedef struct aafiAudioEssencePointer { } aafiAudioEssencePointer; typedef struct aafiVideoEssence { - wchar_t* original_file_path; // NetworkLocator::URLString should point to original essence file if external (and in some cases, points to the AAF itself if internal..) - wchar_t* usable_file_path; // TODO, not that used.. to be tweaked. ---- Holds the file path, once the essence has been exported, copied or linked. - wchar_t* file_name; // MasterMob::Name -> file name - wchar_t* unique_file_name; // unique name generated from file_name. Sometimes, multiple files share the same names so this unique name should be used on export. + char* original_file_path; // NetworkLocator::URLString should point to original essence file if external (and in some cases, points to the AAF itself if internal..) + char* usable_file_path; // TODO, not that used.. to be tweaked. ---- Holds the file path, once the essence has been exported, copied or linked. + char* name; // MasterMob::Name -> file name + char* unique_name; // unique name generated from aafiVideoEssence->name. Sometimes, multiple files share the same names so this unique name should be used on export. - uint64_t length; // Length of Essence Data + aafPosition_t length; // Length of Essence Data cfbNode* node; // The node holding the audio stream if embedded @@ -328,6 +400,11 @@ typedef struct aafiVideoEssence { aafProperty* summary; + /** + * Metadata retrieved from main MasterMob::UserComments + */ + aafiMetaData* metadata; + // TODO peakEnveloppe struct aafiVideoEssence* next; @@ -338,10 +415,33 @@ struct aafiAudioTrack; struct aafiVideoTrack; typedef struct aafiAudioClip { + /** + * The track that audio clip is attached to. + */ struct aafiAudioTrack* track; - int channels; // channel count of clip (might be different of essence->channels) + /** + * Audio channel count of audio clip. Might be different of #aafiAudioEssenceFile.channels + */ + int channels; + + /** + * List of essence pointer that compose an audio clip. + * + * An audio clip can hold a single aafiAudioEssencePointer, if clip is mono or + * Each aafiAudioEssencePointer points to a single aafiAudioEssenceFile. + * + * If clip is mono, it has a single aafiAudioEssencePointer which points to a + * single aafiAudioEssenceFile. + */ aafiAudioEssencePointer* essencePointerList; + + /** + * SubCLip name is set in rare cases, when a SourceClip targets a SubClip + * CompositionMob with a name (see AAFUsage_SubClip) + */ + char* subClipName; + /* * Some editors (like Resolve) support automation attached to a clip AND a fixed value clip gain */ @@ -350,8 +450,6 @@ typedef struct aafiAudioClip { int mute; - int channel_count; - aafPosition_t pos; /* in edit unit, edit rate definition is aafiAudioTrack->edit_rate */ aafPosition_t len; /* in edit unit, edit rate definition is aafiAudioTrack->edit_rate */ @@ -378,7 +476,9 @@ typedef struct aafiAudioClip { */ aafPosition_t essence_offset; - struct aafiTimelineItem* Item; // Corresponding timeline item, currently used in ardour to retrieve fades/x-fades + aafiMetaData* metadata; + + struct aafiTimelineItem* timelineItem; // Corresponding timeline item } aafiAudioClip; @@ -395,6 +495,8 @@ typedef struct aafiVideoClip { aafMobID_t* masterMobID; // MobID of the associated MasterMob (PID_SourceReference_SourceID) + struct aafiTimelineItem* timelineItem; // Corresponding timeline item + } aafiVideoClip; typedef enum aafiTimelineItem_type_e { @@ -409,13 +511,30 @@ typedef enum aafiTimelineItem_type_e { */ typedef struct aafiTimelineItem { - int type; + /** + * Identifies timelineItem type. + */ + aafiTimelineItem_type_e type; + + /** + * Item position on the timeline. Value is in edit unit, specified by #aafiAudioTrack.edit_rate. + */ + aafPosition_t pos; + + /** + * Item length on the timeline. Value is in edit unit, specified by #aafiAudioTrack.edit_rate. + */ + aafPosition_t len; + + /** + * The actual timelineItem object data. Can hold an aafiTransition, aafiAudioClip + * or aafiVideoClip structure, depending on #aafiTimelineItem.type value. + */ + void* data; struct aafiTimelineItem* next; struct aafiTimelineItem* prev; - void* data; /* aafiTransition or aafiAudioClip or aafiVideoClip */ - } aafiTimelineItem; /** @@ -471,8 +590,6 @@ struct aafiVideo; typedef struct aafiAudioTrack { /** * Track number - * TODO Should it start at one ? - * TODO Optional, should have a guess (i++) option. */ uint32_t number; @@ -483,7 +600,7 @@ typedef struct aafiAudioTrack { * Track name */ - wchar_t* name; + char* name; /** * Holds the Gain to apply on that track, that is the track volume Fader. @@ -493,12 +610,16 @@ typedef struct aafiAudioTrack { aafiAudioPan* pan; + char solo; + char mute; + /** * Holds the timeline items of that track, that is aafiAudioClip and aafiTransition * structures. */ - struct aafiTimelineItem* Items; + struct aafiTimelineItem* timelineItems; + int clipCount; /** * The edit rate of all the contained Clips, Transitions, also lengths and track->current_pos; @@ -535,14 +656,14 @@ typedef struct aafiVideoTrack { * Track name */ - wchar_t* name; + char* name; /** * Holds the timeline items of that track, that is aafiVideoClip and aafiTransition * structures. */ - struct aafiTimelineItem* Items; + struct aafiTimelineItem* timelineItems; /** * The edit rate of all the contained Clips and Transitions. @@ -566,15 +687,6 @@ typedef struct aafiVideoTrack { } aafiVideoTrack; -typedef struct aafiUserComment { - wchar_t* name; - - wchar_t* text; - - struct aafiUserComment* next; - -} aafiUserComment; - typedef struct aafiAudio { /** * Holds the sequence start timecode. @@ -582,15 +694,16 @@ typedef struct aafiAudio { aafPosition_t start; - int16_t samplesize; - int64_t samplerate; + uint16_t samplesize; + uint32_t samplerate; aafRational_t* samplerateRational; // eg. { 48000, 1 } /** * Holds the Essence list. */ - aafiAudioEssence* Essences; + int essenceCount; + aafiAudioEssenceFile* essenceFiles; aafiAudioEssencePointer* essencePointerList; /** @@ -613,7 +726,7 @@ typedef struct aafiVideo { * Holds the Essence list. */ - aafiVideoEssence* Essences; + aafiVideoEssence* essenceFiles; /** * Holds the Track list. @@ -632,8 +745,8 @@ typedef struct aafiMarker { aafPosition_t length; aafRational_t* edit_rate; - wchar_t* name; - wchar_t* comment; + char* name; + char* comment; uint16_t RGBColor[3]; struct aafiMarker* prev; @@ -641,17 +754,7 @@ typedef struct aafiMarker { } aafiMarker; -// typedef enum aafiCurrentTreeType_e -// { -// AAFI_TREE_TYPE_AUDIO = 0, -// AAFI_TREE_TYPE_VIDEO = 1 -// -// } aafiCurrentTreeType_e; - typedef struct aafiContext { - /* Set in parse_MobSlot(), specifies if we're inside an audio or video context */ - // aafiCurrentTreeType_e current_tree_type; - /* * Current MobSlot Segment's DataDefinition * Mob::Slots > MobSlot::Segment > Component::DataDefinition @@ -660,11 +763,10 @@ typedef struct aafiContext { // aafUID_t *DataDef; /* Clip */ + aafObject* TopLevelCompositionMob; aafiAudioTrack* current_track; - /* Must be casted to aafiAudioTrack or aafiVideoTrack, according to aafiContext::current_tree_type */ - // void * current_track; // int current_track_number; // used only when missing MobSlot::PhysicalTrackNumber // aafPosition_t current_pos; @@ -673,41 +775,46 @@ typedef struct aafiContext { int current_clip_is_muted; int current_clip_is_combined; // Inside OperationGroup::AAFOperationDef_AudioChannelCombiner - int current_combined_clip_total_channel; + uint32_t current_combined_clip_total_channel; int current_combined_clip_channel_num; // current SourceClip represents channel num aafPosition_t current_combined_clip_forced_length; /* Transition */ aafiTransition* current_transition; + char* subClipName; + + int current_opgroup_affect_track; + /* Gain */ aafiAudioGain* current_clip_gain; - aafiAudioGain* current_clip_automation; - int clips_using_gain; // if none then free( current_clip_gain ); - int clips_using_automation; + int current_clip_gain_is_used; // if not then free( current_clip_gain ); + + aafiAudioGain* current_clip_variable_gain; + int current_clip_variable_gain_is_used; /* Essence */ - // aafiAudioEssence *current_audioEssence; - // void *current_essence; - aafiAudioEssence* current_essence; - aafiVideoEssence* current_video_essence; + aafiAudioEssenceFile* current_audio_essence; + aafiVideoEssence* current_video_essence; aafRational_t* current_markers_edit_rate; - int is_inside_derivation_chain; + aafRational_t* avid_warp_clip_edit_rate; struct options { - int trace; - int trace_meta; - wchar_t* dump_class_aaf_properties; - wchar_t* dump_class_raw_properties; - char* media_location; - char forbid_nonlatin_filenames; + int trace; + int dump_meta; + int dump_tagged_value; + char* dump_class_aaf_properties; + char* dump_class_raw_properties; + char* media_location; + // int forbid_nonlatin_filenames; + int mobid_essence_filename; + /* vendor specific */ - uint32_t resolve; - uint32_t protools; + int protools; } options; } aafiContext; @@ -729,7 +836,7 @@ typedef struct AAF_Iface { aafiMarker* Markers; - wchar_t* compositionName; + char* compositionName; aafPosition_t compositionStart; // sets from aafi->Timecode->start aafRational_t* compositionStart_editRate; @@ -737,88 +844,242 @@ typedef struct AAF_Iface { aafPosition_t compositionLength; // sets from the longest audio or video track->current_pos aafRational_t* compositionLength_editRate; /* might be NULL if file empty ! */ - aafiUserComment* Comments; + /** + * Metadata retrieved from main CompositionMob::UserComments + */ + aafiMetaData* metadata; - struct dbg* dbg; + struct aafLog* log; } AAF_Iface; -#define foreach_audioTrack(audioTrack, aafi) \ - for (audioTrack = aafi->Audio->Tracks; \ - audioTrack != NULL; \ +/** + * @name Function macros + * @{ + */ + +/** + * Loops through each audio track in AAF file. + * + * @param aafi Pointer to the current AAF_Iface struct. + * @param audioTrack NULL pointer to an aafiAudioTrack struct. + */ +#define AAFI_foreachAudioTrack(aafi, audioTrack) \ + for (audioTrack = aafi->Audio->Tracks; \ + audioTrack != NULL; \ audioTrack = audioTrack->next) -#define foreach_videoTrack(videoTrack, aafi) \ - for (videoTrack = aafi->Video->Tracks; \ - videoTrack != NULL; \ +/** + * Loops through each video track in AAF file. + * + * @param aafi Pointer to the current AAF_Iface struct. + * @param videoTrack NULL pointer to an aafiVideoTrack struct. + */ +#define AAFI_foreachVideoTrack(aafi, videoTrack) \ + for (videoTrack = aafi->Video->Tracks; \ + videoTrack != NULL; \ videoTrack = videoTrack->next) -#define foreach_Item(item, track) \ - for (item = track->Items; \ - item != NULL; \ - item = item->next) +/** + * Loops through each timelineItem of a track. Audio tracks can contain + * either clips (AAFI_AUDIO_CLIP) or crossfades (AAFI_TRANS). + * + * @param track Pointer to an aafiAudioTrack struct. + * @param timelineItem NULL pointer to an aafiTimelineItem struct. + */ +#define AAFI_foreachTrackItem(track, timelineItem) \ + for (timelineItem = track->timelineItems; \ + timelineItem != NULL; \ + timelineItem = timelineItem->next) -#define AAFI_foreachAudioEssencePointerInFile(essencePointer, aafi) \ - for (essencePointer = aafi->Audio->essencePointerList; essencePointer != NULL; essencePointer = essencePointer->aafiNext) +/** + * Loops through each audio essence pointer in AAF file. + * + * @param aafi Pointer to the current AAF_Iface struct. + * @param audioEssencePointer NULL pointer to an aafiAudioEssencePointer struct. + */ +#define AAFI_foreachAudioEssencePointer(aafi, audioEssencePointer) \ + for (audioEssencePointer = aafi->Audio->essencePointerList; \ + audioEssencePointer != NULL; \ + audioEssencePointer = audioEssencePointer->aafiNext) -#define AAFI_foreachAudioEssencePointer(essencePointer, essencePtrList) \ - for (essencePointer = essencePtrList; essencePointer != NULL; essencePointer = essencePointer->next) +/** + * Loops through each audio essence file in AAF file. + * + * @param aafi Pointer to the current AAF_Iface struct. + * @param audioEssenceFile NULL pointer to an aafiAudioEssenceFile struct. + */ +#define AAFI_foreachAudioEssenceFile(aafi, audioEssenceFile) \ + for (audioEssenceFile = aafi->Audio->essenceFiles; \ + audioEssenceFile != NULL; \ + audioEssenceFile = audioEssenceFile->next) -#define foreachEssence(essence, essenceList) \ - for (essence = essenceList; essence != NULL; essence = essence->next) +/** + * Loops through each video essence file in AAF file. + * + * @param aafi Pointer to the current AAF_Iface struct. + * @param videoEssenceFile NULL pointer to an aafiVideoEssence struct. + */ +#define AAFI_foreachVideoEssence(aafi, videoEssenceFile) \ + for (videoEssenceFile = aafi->Video->essenceFiles; \ + videoEssenceFile != NULL; \ + videoEssenceFile = videoEssenceFile->next) -#define foreachMarker(marker, aafi) \ - for (marker = aafi->Markers; marker != NULL; marker = marker->next) +/** + * Loops through each essence pointer in a list (usualy aafiAudioClip->essencePointerList). + * + * @param essencePointerList Pointer to any aafiAudioEssencePointer struct list. + * @param essencePointer NULL pointer to an aafiAudioEssencePointer struct. + */ +#define AAFI_foreachEssencePointer(essencePointerList, essencePointer) \ + for (essencePointer = essencePointerList; \ + essencePointer != NULL; \ + essencePointer = essencePointer->next) -void -aafi_set_debug (AAF_Iface* aafi, verbosityLevel_e v, int ansicolor, FILE* fp, void (*callback) (struct dbg* dbg, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user), void* user); +#define AAFI_foreachEssence(essenceFileList, essenceFile) \ + for (essenceFile = essenceFileList; \ + essenceFile != NULL; \ + essenceFile = essenceFile->next) -int -aafi_set_option_int (AAF_Iface* aafi, const char* optname, int val); -int -aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val); +/** + * Loops through each marker in AAF file. + * + * @param aafi Pointer to the current AAF_Iface struct. + * @param marker NULL pointer to an aafiMarker struct. + */ +#define AAFI_foreachMarker(aafi, marker) \ + for (marker = aafi->Markers; \ + marker != NULL; \ + marker = marker->next) + +#define AAFI_foreachMetadata(metadataList, metadata) \ + for (metadata = metadataList; \ + metadata != NULL; \ + metadata = metadata->next) + +/** + * @} + */ AAF_Iface* aafi_alloc (AAF_Data* aafd); void -aafi_release (AAF_Iface** aafi); +aafi_set_debug (AAF_Iface* aafi, verbosityLevel_e v, int ansicolor, FILE* fp, void (*callback) (struct aafLog* log, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user), void* user); + +int +aafi_set_option_int (AAF_Iface* aafi, const char* optname, int val); + +int +aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val); int aafi_load_file (AAF_Iface* aafi, const char* file); -aafiTransition* -aafi_get_fadein (aafiTimelineItem* audioItem); - -aafiTransition* -aafi_get_fadeout (aafiTimelineItem* audioItem); - -aafiTransition* -aafi_get_xfade (aafiTimelineItem* audioItem); - -aafiMarker* -aafi_newMarker (AAF_Iface* aafi, aafRational_t* editRate, aafPosition_t start, aafPosition_t length, wchar_t* name, wchar_t* comment, uint16_t* RGBColor[3]); - void -aafi_freeMarkers (aafiMarker** aafi); +aafi_release (AAF_Iface** aafi); + +aafiAudioClip* +aafi_timelineItemToAudioClip (aafiTimelineItem* audioItem); + +aafiTransition* +aafi_timelineItemToCrossFade (aafiTimelineItem* audioItem); + +aafiTransition* +aafi_getFadeIn (aafiAudioClip* audioClip); + +aafiTransition* +aafi_getFadeOut (aafiAudioClip* audioClip); + +int +aafi_get_clipIndex (aafiAudioClip* audioClip); + +aafPosition_t +aafi_convertUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate); + +uint64_t +aafi_convertUnitUint64 (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate); + +int +aafi_removeTimelineItem (AAF_Iface* aafi, aafiTimelineItem* timelineItem); + +int +aafi_getAudioEssencePointerChannelCount (aafiAudioEssencePointer* essencePointerList); + +int +aafi_applyGainOffset (AAF_Iface* aafi, aafiAudioGain** gain, aafiAudioGain* offset); aafiAudioTrack* aafi_newAudioTrack (AAF_Iface* aafi); -void -aafi_freeAudioTracks (aafiAudioTrack** tracks); - aafiVideoTrack* aafi_newVideoTrack (AAF_Iface* aafi); +aafiTimelineItem* +aafi_newTimelineItem (AAF_Iface* aafi, void* track, int itemType, void* data); + +aafiAudioClip* +aafi_newAudioClip (AAF_Iface* aafi, aafiAudioTrack* track); + +aafiVideoClip* +aafi_newVideoClip (AAF_Iface* aafi, aafiVideoTrack* track); + +aafiTransition* +aafi_newTransition (AAF_Iface* aafi, aafiAudioTrack* track); + +aafiMarker* +aafi_newMarker (AAF_Iface* aafi, aafRational_t* editRate, aafPosition_t start, aafPosition_t length, char* name, char* comment, uint16_t* RGBColor[]); + +aafiMetaData* +aafi_newMetadata (AAF_Iface* aafi, aafiMetaData** CommentList); + +aafiAudioEssencePointer* +aafi_newAudioEssencePointer (AAF_Iface* aafi, aafiAudioEssencePointer** list, aafiAudioEssenceFile* audioEssenceFile, uint32_t* essenceChannelNum); + +aafiAudioEssenceFile* +aafi_newAudioEssence (AAF_Iface* aafi); + +aafiVideoEssence* +aafi_newVideoEssence (AAF_Iface* aafi); + +aafiAudioGain* +aafi_newAudioGain (AAF_Iface* aafi, enum aafiAudioGain_e type, enum aafiInterpolation_e interpol, aafRational_t* singleValue); + +aafiAudioGain* +aafi_newAudioPan (AAF_Iface* aafi, enum aafiAudioGain_e type, enum aafiInterpolation_e interpol, aafRational_t* singleValue); + +void +aafi_freeAudioTracks (aafiAudioTrack** tracks); + void aafi_freeVideoTracks (aafiVideoTrack** tracks); -aafiTimelineItem* -aafi_newTimelineItem (AAF_Iface* aafi, void* track, int itemType); +void +aafi_freeTimelineItems (aafiTimelineItem** timelineItems); -int -aafi_removeTimelineItem (AAF_Iface* aafi, aafiTimelineItem* item); +void +aafi_freeTimelineItem (aafiTimelineItem* timelineItem); + +void +aafi_freeAudioClip (aafiAudioClip* audioClip); + +void +aafi_freeTransition (aafiTransition* trans); + +void +aafi_freeMarkers (aafiMarker** aafi); + +void +aafi_freeMetadata (aafiMetaData** CommentList); + +void +aafi_freeAudioEssencePointer (aafiAudioEssencePointer* audioEssenceGroupEntry); + +void +aafi_freeAudioEssences (aafiAudioEssenceFile** audioEssenceFiles); + +void +aafi_freeVideoEssences (aafiVideoEssence** videoEssenceFile); void aafi_freeAudioGain (aafiAudioGain* gain); @@ -826,45 +1087,6 @@ aafi_freeAudioGain (aafiAudioGain* gain); void aafi_freeAudioPan (aafiAudioPan* pan); -void -aafi_freeAudioClip (aafiAudioClip* audioClip); - -void -aafi_freeAudioEssencePointer (aafiAudioEssencePointer* audioEssenceGroupEntry); - -void -aafi_freeTimelineItem (aafiTimelineItem** item); - -void -aafi_freeTimelineItems (aafiTimelineItem** items); - -aafiUserComment* -aafi_newUserComment (AAF_Iface* aafi, aafiUserComment** CommentList); - -void -aafi_freeUserComments (aafiUserComment** CommentList); - -void -aafi_freeTransition (aafiTransition* trans); - -aafiAudioEssence* -aafi_newAudioEssence (AAF_Iface* aafi); - -aafiAudioEssencePointer* -aafi_newAudioEssencePointer (AAF_Iface* aafi, aafiAudioEssencePointer** list, aafiAudioEssence* audioEssence, uint32_t* essenceChannelNum); - -void -aafi_freeAudioEssences (aafiAudioEssence** essences); - -aafiVideoEssence* -aafi_newVideoEssence (AAF_Iface* aafi); - -void -aafi_freeVideoEssences (aafiVideoEssence** videoEssence); - -int -aafi_getAudioEssencePointerChannelCount (aafiAudioEssencePointer* essencePointerList); - /** * @} */ diff --git a/libs/aaf/aaf/AAFToText.h b/libs/aaf/aaf/AAFToText.h index def7a4a5fa..7d9a7e7bb8 100644 --- a/libs/aaf/aaf/AAFToText.h +++ b/libs/aaf/aaf/AAFToText.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -21,9 +21,6 @@ #ifndef __AAFToText_h__ #define __AAFToText_h__ -#include -#include - #include "aaf/AAFCore.h" #include "aaf/AAFTypes.h" #include "aaf/LibCFB.h" @@ -31,115 +28,118 @@ #define AUIDToText(auid) \ cfb_CLSIDToText ((const cfbCLSID_t*)auid) -const wchar_t* +const char* aaft_MobIDToText (aafMobID_t* mobid); -const wchar_t* +const char* aaft_TimestampToText (aafTimeStamp_t* ts); -const wchar_t* +const char* aaft_VersionToText (aafVersionType_t* vers); -const wchar_t* +const char* aaft_ProductVersionToText (aafProductVersion_t* vers); -const wchar_t* +const char* aaft_FileKindToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_TapeCaseTypeToText (aafTapeCaseType_t t); -const wchar_t* +const char* aaft_VideoSignalTypeToText (aafVideoSignalType_t v); -const wchar_t* +const char* aaft_TapeFormatTypeToText (aafTapeFormatType_t t); -const wchar_t* +const char* aaft_FilmTypeToText (aafFilmType_t f); -const wchar_t* +const char* aaft_SignalStandardToText (aafSignalStandard_t s); -const wchar_t* +const char* aaft_FieldNumberToText (aafFieldNumber_t f); -const wchar_t* +const char* aaft_AlphaTransparencyToText (aafAlphaTransparency_t a); -const wchar_t* +const char* aaft_FrameLayoutToText (aafFrameLayout_t f); -const wchar_t* +const char* aaft_ColorSitingToText (aafColorSiting_t c); -const wchar_t* +const char* aaft_ProductReleaseTypeToText (aafProductReleaseType_t t); -const wchar_t* +const char* aaft_FadeTypeToText (aafFadeType_t f); -const wchar_t* +const char* aaft_BoolToText (aafBoolean_t b); -const wchar_t* +const char* aaft_OperationCategoryToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_PluginCategoryToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_ScanningDirectionToText (aafScanningDirection_t s); -const wchar_t* +const char* aaft_ByteOrderToText (int16_t e); -const wchar_t* +const char* aaft_ElectroSpatialToText (aafElectroSpatialFormulation_t e); -const wchar_t* +const char* aaft_TypeIDToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_StoredFormToText (enum aafStoredForm_e sf); -const wchar_t* +const char* aaft_OPDefToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_DataDefToText (AAF_Data* aafd, const aafUID_t* auid); -const wchar_t* +const char* aaft_OperationDefToText (AAF_Data* aafd, const aafUID_t* auid); -const wchar_t* +const char* aaft_InterpolationToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_ParameterToText (AAF_Data* aafd, const aafUID_t* auid); -const wchar_t* +const char* aaft_TransferCharacteristicToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_CodingEquationsToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_ColorPrimariesToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_UsageCodeToText (const aafUID_t* auid); -const wchar_t* +const char* aaft_PIDToText (AAF_Data* aafd, aafPID_t pid); -const wchar_t* +const char* aaft_ClassIDToText (AAF_Data* aafd, const aafUID_t* auid); -const wchar_t* +const char* aaft_ContainerToText (const aafUID_t* auid); -const wchar_t* +const char* +aaft_IndirectValueToText (AAF_Data* aafd, aafIndirect_t* Indirect); + +const char* aaft_CompressionToText (const aafUID_t* auid); #endif // !__AAFToText_h__ diff --git a/libs/aaf/aaf/AAFTypes.h b/libs/aaf/aaf/AAFTypes.h index c137b2105b..c7c27d8b5e 100644 --- a/libs/aaf/aaf/AAFTypes.h +++ b/libs/aaf/aaf/AAFTypes.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -184,6 +184,8 @@ typedef struct _aafUID_t { static const aafUID_t AUID_NULL = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; +static const aafUID_t AAFUID_NULL = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; + typedef struct _aafMobID_t { uint8_t SMPTELabel[12]; // 12-bytes of label prefix uint8_t length; @@ -194,6 +196,8 @@ typedef struct _aafMobID_t { } aafMobID_t; // 32 bytes total +static const aafMobID_t AAFMOBID_NULL = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0x00, 0x00, 0x00, 0x00, { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }; + typedef struct _aafIndirect_t { /* * byteOrder disabled for memory alignement and to avoid -Waddress-of-packed-member @@ -367,8 +371,6 @@ typedef struct _aafRGBAComponent_t { //typedef aafRGBAComponent_t aafRGBALayout[8]; -static const aafUID_t AAFUID_NULL = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; - /** * This structure map the first bytes in a **properties** stream * node. diff --git a/libs/aaf/aaf/CFBDump.h b/libs/aaf/aaf/CFBDump.h index 0283119199..90bee4b722 100644 --- a/libs/aaf/aaf/CFBDump.h +++ b/libs/aaf/aaf/CFBDump.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -21,36 +21,33 @@ #ifndef __CFBDump_h__ #define __CFBDump_h__ -#include -#include - #include "aaf/LibCFB.h" void -cfb_dump_node (CFB_Data* cfbd, cfbNode* node, int print_stream); +cfb_dump_node (CFB_Data* cfbd, cfbNode* node, int print_stream, const char* padding); void -cfb_dump_nodePath (CFB_Data* cfbd, const wchar_t* path, int print_stream); +cfb_dump_nodePath (CFB_Data* cfbd, const char* path, int print_stream, const char* padding); void -cfb_dump_nodeStream (CFB_Data* cfbd, cfbNode* node); +cfb_dump_nodeStream (CFB_Data* cfbd, cfbNode* node, const char* padding); void -cfb_dump_nodePathStream (CFB_Data* cfbd, const wchar_t* path); +cfb_dump_nodePathStream (CFB_Data* cfbd, const char* path, const char* padding); void -cfb_dump_nodePaths (CFB_Data* cfbd, uint32_t prevPath, char* strArray[], uint32_t* str_i, cfbNode* node); +cfb_dump_nodePaths (CFB_Data* cfbd, uint32_t prevPath, char* strArray[], uint32_t* str_i, cfbNode* node, const char* padding, int firstIteration); void -cfb_dump_header (CFB_Data* cfbd); +cfb_dump_header (CFB_Data* cfbd, const char* padding); void -cfb_dump_FAT (CFB_Data* cfbd); +cfb_dump_FAT (CFB_Data* cfbd, const char* padding); void -cfb_dump_MiniFAT (CFB_Data* cfbd); +cfb_dump_MiniFAT (CFB_Data* cfbd, const char* padding); void -cfb_dump_DiFAT (CFB_Data* cfbd); +cfb_dump_DiFAT (CFB_Data* cfbd, const char* padding); #endif // !__CFBDump_h__ diff --git a/libs/aaf/aaf/LibCFB.h b/libs/aaf/aaf/LibCFB.h index 6d2a35247c..0271e8258a 100644 --- a/libs/aaf/aaf/LibCFB.h +++ b/libs/aaf/aaf/LibCFB.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -22,18 +22,16 @@ #define __LibCFB_h__ #include -#include +#include +#include -#include "aaf/debug.h" +#include "aaf/log.h" #if defined(__linux__) +#include #include #elif defined(__APPLE__) #include -#elif defined(_MSC_VER) // MSVC -#include // MAX_PATH -#include -#define PATH_MAX MAX_PATH // TODO: can we get rid of it ? #elif defined(_WIN32) #include // MAX_PATH #include @@ -51,8 +49,6 @@ * @{ */ -#define CFB_W16TOWCHAR_STRLEN SIZE_MAX - /** * Class Identifier structure. * @@ -456,9 +452,6 @@ typedef struct StructuredStorageDirectoryEntry { * * A 64-byte array, for a maximum of 32 Unicode characters including a terminating * Unicode NULL character. The string shall be padded with zeros to fill the array. - * - * Should be wchar_t, but on linux wchar_t is 32 bits wide as opposed to windows - * (and thus CFB) defining wchar_t to 16 bits. Conversion is done by cfb_w16towchar() */ uint16_t _ab[CFB_NODE_NAME_SZ]; @@ -571,7 +564,7 @@ typedef struct CFB_Data { * CFB file path. */ - char file[PATH_MAX + 1]; + char* file; /** * CFB file size. @@ -639,7 +632,7 @@ typedef struct CFB_Data { cfbNode* nodes; - struct dbg* dbg; + struct aafLog* log; } CFB_Data; @@ -657,7 +650,7 @@ typedef struct CFB_Data { * @param id Index of the first sector in the Chain. */ -#define cfb_foreachSectorInChain(cfbd, buf, id) \ +#define CFB_foreachSectorInChain(cfbd, buf, id) \ for (buf = cfb_getSector (cfbd, id); \ id < CFB_MAX_REG_SECT && \ buf != NULL; \ @@ -673,7 +666,7 @@ typedef struct CFB_Data { * @param id Index of the first mini-sector in the Chain. */ -#define cfb_foreachMiniSectorInChain(cfbd, buf, id) \ +#define CFB_foreachMiniSectorInChain(cfbd, buf, id) \ for (buf = cfb_getMiniSector (cfbd, id); \ id < CFB_MAX_REG_SECT; \ id = cfbd->miniFat[id], \ @@ -690,7 +683,7 @@ typedef struct CFB_Data { * sector data. */ -#define cfb_foreachSectorInDiFATChain(cfbd, buf, id) \ +#define CFB_foreachSectorInDiFATChain(cfbd, buf, id) \ for (id = cfbd->hdr->_sectDifStart, \ buf = cfb_getSector (cfbd, id); \ id < CFB_MAX_REG_SECT; \ @@ -705,7 +698,7 @@ typedef struct CFB_Data { * @param id Index of each FAT sector. */ -#define cfb_foreachFATSectorIDInDiFAT(cfbd, id) \ +#define CFB_foreachFATSectorIDInDiFAT(cfbd, id) \ for (id = 0; \ id < cfbd->DiFAT_sz && \ id < cfbd->hdr->_csectFat; \ @@ -716,21 +709,21 @@ typedef struct CFB_Data { * When 512 bytes sectors we don't care about _ulSizeHigh. */ -#define cfb_getNodeStreamLen(cfbd, node) \ +#define CFB_getNodeStreamLen(cfbd, node) \ ((cfbd->hdr->_uSectorShift > 9) ? (uint64_t) (((uint64_t) (node->_ulSizeHigh) << 32) | (node->_ulSizeLow)) : node->_ulSizeLow) -#define cfb_getStreamSectorShift(cfbd, node) \ - ((cfb_getNodeStreamLen (cfbd, node) < cfbd->hdr->_ulMiniSectorCutoff) ? cfbd->hdr->_uMiniSectorShift : cfbd->hdr->_uSectorShift) +#define CFB_getStreamSectorShift(cfbd, node) \ + ((CFB_getNodeStreamLen (cfbd, node) < cfbd->hdr->_ulMiniSectorCutoff) ? cfbd->hdr->_uMiniSectorShift : cfbd->hdr->_uSectorShift) /* * @} */ -const wchar_t* +const char* cfb_CLSIDToText (const cfbCLSID_t* clsid); -wchar_t* -cfb_w16towchar (wchar_t* buf, uint16_t* w16buf, size_t w16blen); +char* +cfb_w16toUTF8 (const uint16_t* w16buf, size_t w16blen); /** * @name Constructor function @@ -739,7 +732,7 @@ cfb_w16towchar (wchar_t* buf, uint16_t* w16buf, size_t w16blen); */ CFB_Data* -cfb_alloc (struct dbg* dbg); +cfb_alloc (struct aafLog* log); /** * @} @@ -783,7 +776,7 @@ cfb_getStream (CFB_Data* cfbd, cfbNode* node, unsigned char** stream, uint64_t* int cfb__foreachSectorInStream (CFB_Data* cfbd, cfbNode* node, unsigned char** buf, size_t* bytesRead, cfbSectorID_t* sectID); -#define cfb_foreachSectorInStream(cfbd, node, buf, bytesRead, sectID) \ +#define CFB_foreachSectorInStream(cfbd, node, buf, bytesRead, sectID) \ while (cfb__foreachSectorInStream (cfbd, node, buf, bytesRead, sectID)) /** @@ -794,10 +787,10 @@ cfb__foreachSectorInStream (CFB_Data* cfbd, cfbNode* node, unsigned char** buf, */ cfbNode* -cfb_getNodeByPath (CFB_Data* cfbd, const wchar_t* name, cfbSID_t id); +cfb_getNodeByPath (CFB_Data* cfbd, const char* path, cfbSID_t id); cfbNode* -cfb_getChildNode (CFB_Data* cfbd, const wchar_t* name, cfbNode* startNode); +cfb_getChildNode (CFB_Data* cfbd, const char* name, cfbNode* startNode); /** * @} diff --git a/libs/aaf/aaf/AAFIAudioFiles.h b/libs/aaf/aaf/MediaComposer.h similarity index 61% rename from libs/aaf/aaf/AAFIAudioFiles.h rename to libs/aaf/aaf/MediaComposer.h index 9c3ffe2925..f567ff0270 100644 --- a/libs/aaf/aaf/AAFIAudioFiles.h +++ b/libs/aaf/aaf/MediaComposer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -18,20 +18,16 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __AAFIAudioFiles_h__ -#define __AAFIAudioFiles_h__ - -#include +#ifndef __MediaComposer_h__ +#define __MediaComposer_h__ +#include "aaf/AAFIParser.h" #include "aaf/AAFIface.h" -wchar_t* -aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_file_path, const char* search_location); +#define AVID_MEDIA_COMPOSER_CURVE_TYPE_LINEAR 0 +#define AVID_MEDIA_COMPOSER_CURVE_TYPE_EQUAL_POWER 1 int -aafi_extract_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence, const char* outfilepath, const wchar_t* forcedFileName); +mediaComposer_AAF (struct AAF_Iface* aafi); -int -aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence); - -#endif // !__AAFIAudioFiles_h__ +#endif // !__MediaComposer_h__ diff --git a/libs/aaf/aaf/ProTools.h b/libs/aaf/aaf/ProTools.h index 07e92e45b9..1886759137 100644 --- a/libs/aaf/aaf/ProTools.h +++ b/libs/aaf/aaf/ProTools.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -25,11 +25,11 @@ #include "aaf/AAFIface.h" enum protools_options { - PROTOOLS_REMOVE_SAMPLE_ACCURATE_EDIT = 1 << 0, - PROTOOLS_REPLACE_CLIP_FADES = 1 << 1, + AAFI_PROTOOLS_OPT_REMOVE_SAMPLE_ACCURATE_EDIT = 1 << 0, + AAFI_PROTOOLS_OPT_REPLACE_CLIP_FADES = 1 << 1, }; -#define PROTOOLS_ALL (PROTOOLS_REMOVE_SAMPLE_ACCURATE_EDIT | PROTOOLS_REPLACE_CLIP_FADES) +#define PROTOOLS_ALL_OPT (AAFI_PROTOOLS_OPT_REMOVE_SAMPLE_ACCURATE_EDIT | AAFI_PROTOOLS_OPT_REPLACE_CLIP_FADES) int protools_AAF (struct AAF_Iface* aafi); diff --git a/libs/aaf/aaf/RIFFParser.h b/libs/aaf/aaf/RIFFParser.h index c35b20acae..8358b64186 100644 --- a/libs/aaf/aaf/RIFFParser.h +++ b/libs/aaf/aaf/RIFFParser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Adrien Gesta-Fline + * Copyright (C) 2023-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -21,7 +21,17 @@ #ifndef __RIFFParser__ #define __RIFFParser__ -#include "aaf/debug.h" +#include "aaf/log.h" + +#if defined(__linux__) +#include +#include +#elif defined(__APPLE__) +#include +#elif defined(_WIN32) +#include // MAX_PATH +#include +#endif #ifdef __GNUC__ #define PACK(__Declaration__) __Declaration__ __attribute__ ((__packed__)) @@ -31,6 +41,8 @@ #define PACK(__Declaration__) __pragma (pack (push, 1)) __Declaration__ __pragma (pack (pop)) #endif +#define RIFF_READER_ERROR SIZE_MAX + enum RIFF_PARSER_FLAGS { RIFF_PARSE_ONLY_HEADER = (1 << 0), RIFF_PARSE_AAF_SUMMARY = (1 << 1), @@ -42,6 +54,7 @@ struct RIFFAudioFile { uint16_t sampleSize; uint16_t channels; uint64_t sampleCount; /* total samples for 1 channel (no matter channel count). (sampleCount / sampleRate) = duration in seconds */ + size_t pcm_audio_start_offset; }; PACK (struct riffHeaderChunk { @@ -60,7 +73,7 @@ PACK (struct riffChunk { }); PACK (struct wavFmtChunk { - char ckid[4]; //'fmt ' + char ckid[4]; /* 'fmt ' */ uint32_t cksz; uint16_t format_tag; @@ -72,7 +85,7 @@ PACK (struct wavFmtChunk { }); PACK (struct wavBextChunk { - char ckid[4]; //'bext' + char ckid[4]; /* 'bext' */ uint32_t cksz; char description[256]; @@ -114,7 +127,7 @@ PACK (struct wavBextChunk { }); PACK (struct aiffCOMMChunk { - char ckid[4]; //'COMM' + char ckid[4]; /* 'COMM' */ uint32_t cksz; uint16_t numChannels; @@ -123,10 +136,18 @@ PACK (struct aiffCOMMChunk { unsigned char sampleRate[10]; // 80 bit IEEE Standard 754 floating point number }); -int -riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS flags, size_t (*readerCallback) (unsigned char*, size_t, size_t, void*, void*, void*), void* user1, void* user2, void* user3, struct dbg* dbg); +PACK (struct aiffSSNDChunk { + char ckid[4]; /* 'SSND' */ + uint32_t cksz; + + uint32_t offset; + uint32_t blockSize; +}); int -riff_writeWavFileHeader (FILE* fp, struct wavFmtChunk* wavFmt, struct wavBextChunk* wavBext, uint32_t audioDataSize, struct dbg* dbg); +laaf_riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS flags, size_t (*readerCallback) (unsigned char*, size_t, size_t, void*, void*, void*), void* user1, void* user2, void* user3, struct aafLog* log); + +int +laaf_riff_writeWavFileHeader (FILE* fp, struct wavFmtChunk* wavFmt, struct wavBextChunk* wavBext, uint32_t audioDataSize, struct aafLog* log); #endif // ! __RIFFParser__ diff --git a/libs/aaf/aaf/Resolve.h b/libs/aaf/aaf/Resolve.h index 682330cd5d..5668790acd 100644 --- a/libs/aaf/aaf/Resolve.h +++ b/libs/aaf/aaf/Resolve.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Adrien Gesta-Fline + * Copyright (C) 2023-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -24,19 +24,7 @@ #include "aaf/AAFIParser.h" #include "aaf/AAFIface.h" -enum resolve_options { - RESOLVE_INCLUDE_DISABLED_CLIPS = 1 << 0, -}; - -#define RESOLVE_ALL (RESOLVE_INCLUDE_DISABLED_CLIPS) - int resolve_AAF (struct AAF_Iface* aafi); -int -resolve_parse_aafObject_Selector (struct AAF_Iface* aafi, aafObject* Selector, td* __ptd); - -int -resolve_parse_aafObject_DescriptiveMarker (struct AAF_Iface* aafi, aafObject* DescriptiveMarker, td* __ptd); - #endif // !__Resolve_h__ diff --git a/libs/aaf/aaf/URIParser.h b/libs/aaf/aaf/URIParser.h index 629bc5e2f1..719716b21a 100644 --- a/libs/aaf/aaf/URIParser.h +++ b/libs/aaf/aaf/URIParser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Adrien Gesta-Fline + * Copyright (C) 2023-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -21,7 +21,17 @@ #ifndef URI_PARSER_H #define URI_PARSER_H -#include "aaf/debug.h" +#include "aaf/log.h" + +#if defined(__linux__) +#include +#include +#elif defined(__APPLE__) +#include +#elif defined(_WIN32) +#include // MAX_PATH +#include +#endif #define MAX_URI_LENGTH 64000 @@ -118,25 +128,9 @@ struct uri { }; struct uri* -uriParse (const char*, enum uri_option, struct dbg* dbg); +laaf_uri_parse (const char*, enum uri_option, struct aafLog* log); void -uriFree (struct uri*); - -/* - * if dst is NULL of equals src, then encoded source string will be overwritten - * by decoded string. - */ -char* -uriDecodeString (char* src, char* dst); - -char* -uriDecodeWString (wchar_t* src, wchar_t* dst); - -int -uriIsIPv4 (const char* s, int size, char** err); - -int -uriIsIPv6 (const char* s, int size, char** err); +laaf_uri_free (struct uri*); #endif // ! URI_PARSER_H diff --git a/libs/aaf/aaf/debug.h b/libs/aaf/aaf/debug.h deleted file mode 100644 index e1d83eeafd..0000000000 --- a/libs/aaf/aaf/debug.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2017-2023 Adrien Gesta-Fline - * - * This file is part of libAAF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __debug_h__ -#define __debug_h__ - -#include -#include -#include -#include - -#include "aaf/utils.h" - -#define __FILENAME__ (strrchr (__FILE__, '/') ? strrchr (__FILE__, '/') + 1 : __FILE__) - -enum debug_source_id { - DEBUG_SRC_ID_LIB_CFB, - DEBUG_SRC_ID_AAF_CORE, - DEBUG_SRC_ID_AAF_IFACE, - DEBUG_SRC_ID_TRACE, - DEBUG_SRC_ID_DUMP -}; - -typedef enum verbosityLevel_e { - VERB_QUIET = 0, - VERB_ERROR, - VERB_WARNING, - VERB_DEBUG, - MAX_VERB -} verbosityLevel_e; - -struct dbg { - void (*debug_callback) (struct dbg* dbg, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user); - - FILE* fp; - verbosityLevel_e verb; - int ansicolor; - - char* _dbg_msg; - int _dbg_msg_size; - int _dbg_msg_pos; - - char* _dbg_msg_tmp; - int _dbg_msg_pos_tmp; - - void* user; -}; - -#define _dbg(dbg, ctxdata, lib, type, ...) \ - { \ - const char* dbgfile = __FILENAME__; \ - const char* dbgfunc = __func__; \ - int dbgline = __LINE__; \ - if (dbg && dbg->verb >= type && dbg->debug_callback) { \ - if (dbg->_dbg_msg_pos) { \ - dbg->_dbg_msg_pos_tmp = dbg->_dbg_msg_pos; \ - dbg->_dbg_msg_tmp = laaf_util_c99strdup (dbg->_dbg_msg); \ - } \ - int msgsize = snprintf (NULL, 0, __VA_ARGS__) + 1; \ - if (msgsize >= dbg->_dbg_msg_size) { \ - char* msgtmp = realloc (dbg->_dbg_msg, msgsize); \ - if (msgtmp) { \ - dbg->_dbg_msg = msgtmp; \ - dbg->_dbg_msg_size = msgsize; \ - snprintf (dbg->_dbg_msg, dbg->_dbg_msg_size, __VA_ARGS__); \ - dbg->debug_callback (dbg, (void*)ctxdata, lib, type, dbgfile, dbgfunc, dbgline, dbg->_dbg_msg, dbg->user); \ - } else { \ - /* realloc() error */ \ - } \ - } else { \ - snprintf (dbg->_dbg_msg, dbg->_dbg_msg_size, __VA_ARGS__); \ - dbg->debug_callback (dbg, (void*)ctxdata, lib, type, dbgfile, dbgfunc, dbgline, dbg->_dbg_msg, dbg->user); \ - } \ - if (dbg->_dbg_msg_pos_tmp) { \ - dbg->_dbg_msg_pos = dbg->_dbg_msg_pos_tmp; \ - strcpy (dbg->_dbg_msg, dbg->_dbg_msg_tmp); \ - free (dbg->_dbg_msg_tmp); \ - dbg->_dbg_msg_tmp = NULL; \ - dbg->_dbg_msg_pos_tmp = 0; \ - } \ - } \ - } - -#define DBG_BUFFER_WRITE(dbg, ...) \ - dbg->_dbg_msg_pos += laaf_util_snprintf_realloc (&dbg->_dbg_msg, &dbg->_dbg_msg_size, dbg->_dbg_msg_pos, __VA_ARGS__); - -#define DBG_BUFFER_RESET(dbg) \ - dbg->_dbg_msg_pos = 0; - -struct dbg* -laaf_new_debug (void); - -void -laaf_free_debug (struct dbg* dbg); - -void -laaf_debug_callback (struct dbg* dbg, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user); - -#endif // !__debug_h__ diff --git a/libs/aaf/aaf/libaaf.h b/libs/aaf/aaf/libaaf.h index 5d6f54299a..d17a6d2886 100644 --- a/libs/aaf/aaf/libaaf.h +++ b/libs/aaf/aaf/libaaf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -28,13 +28,14 @@ extern "C" { #include "aaf/version.h" #include "aaf/AAFCore.h" -#include "aaf/AAFIAudioFiles.h" +#include "aaf/AAFIEssenceFile.h" #include "aaf/AAFIface.h" #include "aaf/LibCFB.h" #include "aaf/AAFDump.h" #include "aaf/CFBDump.h" +#include "aaf/MediaComposer.h" #include "aaf/ProTools.h" #include "aaf/Resolve.h" diff --git a/libs/aaf/aaf/log.h b/libs/aaf/aaf/log.h new file mode 100644 index 0000000000..b631de4dda --- /dev/null +++ b/libs/aaf/aaf/log.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2017-2024 Adrien Gesta-Fline + * + * This file is part of libAAF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef laaf_log_h__ +#define laaf_log_h__ + +#include +#include // PRIi64 PRIu64 +#include +#include +#include +#include + +#define __FILENAME__ (strrchr (__FILE__, '/') ? strrchr (__FILE__, '/') + 1 : __FILE__) + +enum debug_source_id { + DEBUG_SRC_ID_LIB_CFB, + DEBUG_SRC_ID_AAF_CORE, + DEBUG_SRC_ID_AAF_IFACE, + DEBUG_SRC_ID_TRACE, + DEBUG_SRC_ID_DUMP +}; + +typedef enum verbosityLevel_e { + VERB_QUIET = 0, + VERB_ERROR, + VERB_WARNING, + VERB_DEBUG, + MAX_VERB +} verbosityLevel_e; + +#define VERB_SUCCESS 99 + +struct aafLog { + void (*debug_callback) (struct aafLog* log, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user); + + FILE* fp; + verbosityLevel_e verb; + int ansicolor; + + const char* color_reset; + + char* _msg; + size_t _msg_size; + size_t _msg_pos; + + char* _previous_msg; + size_t _previous_pos; + + int _tmp_dbg_msg_pos; + + void* user; +}; + +#define AAF_LOG(log, ctxdata, lib, type, ...) \ + laaf_write_log (log, ctxdata, lib, type, __FILENAME__, __func__, __LINE__, __VA_ARGS__) + +#define LOG_BUFFER_WRITE(log, ...) \ + log->_tmp_dbg_msg_pos = laaf_util_snprintf_realloc (&log->_msg, &log->_msg_size, log->_msg_pos, __VA_ARGS__); \ + log->_msg_pos += (log->_tmp_dbg_msg_pos < 0) ? 0 : (size_t)log->_tmp_dbg_msg_pos; + +#define DBG_BUFFER_RESET(log) \ + log->_msg_pos = 0; + +struct aafLog* +laaf_new_log (void); + +void +laaf_free_log (struct aafLog* log); + +void +laaf_log_callback (struct aafLog* log, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user); + +void +laaf_write_log (struct aafLog* log, void* ctxdata, enum debug_source_id lib, enum verbosityLevel_e type, const char* dbgfile, const char* dbgfunc, int dbgline, const char* format, ...); + +#endif // !laaf_log_h__ diff --git a/libs/aaf/aaf/utils.h b/libs/aaf/aaf/utils.h index d68bdbed4f..7a5d594dce 100644 --- a/libs/aaf/aaf/utils.h +++ b/libs/aaf/aaf/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -21,10 +21,11 @@ #ifndef __utils_h__ #define __utils_h__ -#include "aaf/AAFTypes.h" #include #include +#include "aaf/AAFTypes.h" + #ifdef __cplusplus extern "C" { #endif @@ -32,76 +33,89 @@ extern "C" { #ifdef _WIN32 #define DIR_SEP '\\' #define DIR_SEP_STR "\\" -/* - * swprintf() specific string format identifiers - * https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170#type - */ -#define WPRIs L"S" // char* -#ifdef XBUILD_WIN -#define WPRIws L"s" // wchar_t* -#else -#define WPRIws L"ls" // wchar_t* -#endif #else #define DIR_SEP '/' #define DIR_SEP_STR "/" -/* - * swprintf() specific string format identifiers - * https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170#type - */ -#define WPRIs L"s" // char* -#define WPRIws L"ls" // wchar_t* #endif +#if defined(__linux__) +#include +#include +#elif defined(__APPLE__) +#include +#elif defined(_WIN32) +#include // MAX_PATH +#include +#include +#endif + +#define AAF_DIR_SEP '/' +#define AAF_DIR_SEP_STR "/" + #define IS_DIR_SEP(c) \ ((((c) == DIR_SEP) || ((c) == '/'))) -#define ANSI_COLOR_RED(dbg) (((dbg)->ansicolor) ? "\033[38;5;124m" : "") //"\x1b[31m" -#define ANSI_COLOR_GREEN(dbg) (((dbg)->ansicolor) ? "\x1b[92m" : "") -#define ANSI_COLOR_YELLOW(dbg) (((dbg)->ansicolor) ? "\x1b[33m" : "") //"\x1b[93m" -#define ANSI_COLOR_ORANGE(dbg) (((dbg)->ansicolor) ? "\033[38;5;130m" : "") -#define ANSI_COLOR_BLUE(dbg) (((dbg)->ansicolor) ? "\x1b[34m" : "") -#define ANSI_COLOR_MAGENTA(dbg) (((dbg)->ansicolor) ? "\x1b[35m" : "") -#define ANSI_COLOR_CYAN(dbg) (((dbg)->ansicolor) ? "\033[38;5;81m" : "") //"\x1b[36m" -#define ANSI_COLOR_DARKGREY(dbg) (((dbg)->ansicolor) ? "\x1b[38;5;242m" : "") -#define ANSI_COLOR_BOLD(dbg) (((dbg)->ansicolor) ? "\x1b[1m" : "") -#define ANSI_COLOR_RESET(dbg) (((dbg)->ansicolor) ? "\x1b[0m" : "") +#define IS_ANY_DIR_SEP(c) \ + ((((c) == '/') || ((c) == '\\'))) -aafPosition_t -laaf_util_converUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate); +#define ANSI_COLOR_RED(log) (((log)->ansicolor) ? "\x1b[38;5;124m" : "") +#define ANSI_COLOR_GREEN(log) (((log)->ansicolor) ? "\x1b[92m" : "") +#define ANSI_COLOR_YELLOW(log) (((log)->ansicolor) ? "\x1b[33m" : "") +#define ANSI_COLOR_ORANGE(log) (((log)->ansicolor) ? "\x1b[38;5;130m" : "") +#define ANSI_COLOR_BLUE(log) (((log)->ansicolor) ? "\x1b[34m" : "") +#define ANSI_COLOR_MAGENTA(log) (((log)->ansicolor) ? "\x1b[35m" : "") +#define ANSI_COLOR_CYAN(log) (((log)->ansicolor) ? "\x1b[38;5;81m" : "") +#define ANSI_COLOR_DARKGREY(log) (((log)->ansicolor) ? "\x1b[38;5;242m" : "") +#define ANSI_COLOR_BOLD(log) (((log)->ansicolor) ? "\x1b[1m" : "") +#define ANSI_COLOR_RESET(log) (((log)->ansicolor) ? (log->color_reset) ? log->color_reset : "\x1b[0m" : "") + +#define TREE_LINE "\xe2\x94\x82" /* │ */ +#define TREE_PADDED_LINE "\xe2\x94\x82\x20\x20" /* │ */ +#define TREE_ENTRY "\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80" /* ├── */ +#define TREE_LAST_ENTRY "\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80" /* └── */ + +size_t +laaf_util_utf8strCharLen (const char* u8str); char* -laaf_util_wstr2str (const wchar_t* wstr); +laaf_util_utf16Toutf8 (const uint16_t* u16str); +#ifdef _WIN32 wchar_t* -laaf_util_str2wstr (const char* str); +laaf_util_windows_utf8toutf16 (const char* str); +char* +laaf_util_windows_utf16toutf8 (const wchar_t* wstr); +#endif int -laaf_util_wstr_contains_nonlatin (const wchar_t* str); +laaf_util_file_exists (const char* filepath); char* laaf_util_clean_filename (char* filename); -const char* -laaf_util_fop_get_file (const char* filepath); - int -laaf_util_fop_is_wstr_fileext (const wchar_t* filepath, const wchar_t* ext); +laaf_util_is_fileext (const char* filepath, const char* ext); char* laaf_util_build_path (const char* sep, const char* first, ...); -int -laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* format, ...); +char* +laaf_util_relative_path (const char* filepath, const char* refpath); -int -laaf_util_vsnprintf_realloc (char** str, int* size, int offset, const char* fmt, va_list* args); +char* +laaf_util_absolute_path (const char* relpath); char* laaf_util_c99strdup (const char* src); int -laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, int* bufsz, int offset); +laaf_util_snprintf_realloc (char** str, size_t* size, size_t offset, const char* format, ...); + +int +laaf_util_vsnprintf_realloc (char** str, size_t* size, size_t offset, const char* fmt, va_list args); + +int +laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, size_t* bufsz, size_t offset, const char* padding); #ifdef __cplusplus } diff --git a/libs/aaf/aaf/version.h b/libs/aaf/aaf/version.h index 157e2fc31b..2f346f6f87 100644 --- a/libs/aaf/aaf/version.h +++ b/libs/aaf/aaf/version.h @@ -1,2 +1,2 @@ #pragma once -#define LIBAAF_VERSION "v0.6-45-g9171e40" +#define LIBAAF_VERSION "v1.0-1-gdef35bf" diff --git a/libs/aaf/debug.c b/libs/aaf/debug.c deleted file mode 100644 index 7dfb72e7b6..0000000000 --- a/libs/aaf/debug.c +++ /dev/null @@ -1,102 +0,0 @@ -#include - -#include "aaf/debug.h" - -#include "aaf/AAFCore.h" -#include "aaf/AAFIParser.h" -#include "aaf/AAFIface.h" -#include "aaf/LibCFB.h" - -#include "aaf/utils.h" - -struct dbg* -laaf_new_debug (void) -{ - struct dbg* dbg = calloc (sizeof (struct dbg), sizeof (char)); - - dbg->debug_callback = &laaf_debug_callback; - dbg->fp = stdout; - dbg->ansicolor = 0; - - return dbg; -} - -void -laaf_free_debug (struct dbg* dbg) -{ - if (dbg->_dbg_msg) { - free (dbg->_dbg_msg); - } - - free (dbg); -} - -void -laaf_debug_callback (struct dbg* dbg, void* ctxdata, int libid, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user) -{ - AAF_Iface* aafi = NULL; - AAF_Data* aafd = NULL; - CFB_Data* cfbd = NULL; - - const char* lib = ""; - const char* typestr = ""; - const char* color = ""; - - if (dbg->fp == NULL) { - DBG_BUFFER_RESET (dbg); - return; - } - - switch (libid) { - case DEBUG_SRC_ID_LIB_CFB: - lib = "libCFB"; - aafi = (AAF_Iface*)ctxdata; - break; - case DEBUG_SRC_ID_AAF_CORE: - lib = "AAFCore"; - aafd = (AAF_Data*)ctxdata; - break; - case DEBUG_SRC_ID_AAF_IFACE: - lib = "AAFIface"; - cfbd = (CFB_Data*)ctxdata; - break; - case DEBUG_SRC_ID_TRACE: - lib = "trace"; - aafi = (AAF_Iface*)ctxdata; - break; - case DEBUG_SRC_ID_DUMP: - lib = "dump"; - break; - } - - switch (type) { - case VERB_ERROR: - typestr = " error "; - color = ANSI_COLOR_RED (dbg); - break; - case VERB_WARNING: - typestr = "warning"; - color = ANSI_COLOR_YELLOW (dbg); - break; - case VERB_DEBUG: - typestr = " debug "; - color = ANSI_COLOR_DARKGREY (dbg); - break; - } - - if (libid != DEBUG_SRC_ID_TRACE && libid != DEBUG_SRC_ID_DUMP) { - fprintf (dbg->fp, "[%s%s%s] ", color, typestr, ANSI_COLOR_RESET (dbg)); - fprintf (dbg->fp, "%s%s:%i in %s()%s : ", ANSI_COLOR_DARKGREY (dbg), srcfile, lineno, srcfunc, ANSI_COLOR_RESET (dbg)); - } - - fprintf (dbg->fp, "%s\n", msg); - - DBG_BUFFER_RESET (dbg); - - /* avoids -Wunused-parameter -Wunused-but-set-variable */ - (void)aafi; - (void)aafd; - (void)cfbd; - (void)lib; - (void)user; -} diff --git a/libs/aaf/log.c b/libs/aaf/log.c new file mode 100644 index 0000000000..a57e399ee4 --- /dev/null +++ b/libs/aaf/log.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2017-2024 Adrien Gesta-Fline + * + * This file is part of libAAF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#ifdef _WIN32 +#include +#include +#include +#endif + +#include "aaf/AAFCore.h" +#include "aaf/AAFIParser.h" +#include "aaf/AAFIface.h" +#include "aaf/LibCFB.h" + +#include "aaf/log.h" +#include "aaf/utils.h" + +/* + * swprintf() specific string format identifiers + * https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170#size-prefixes-for-printf-and-wprintf-format-type-specifiers + */ +#ifdef __MINGW32__ +#define WPRIws L"ls" // wchar_t* +#define WPRIs L"s" // char* +#else +#define WPRIws L"ls" // wchar_t* +#define WPRIs L"S" // char* +#endif + +struct aafLog* +laaf_new_log (void) +{ + struct aafLog* log = calloc (1, sizeof (struct aafLog)); + + if (!log) { + return NULL; + } + + log->debug_callback = &laaf_log_callback; + log->fp = stdout; + log->ansicolor = 0; + + return log; +} + +void +laaf_free_log (struct aafLog* log) +{ + if (!log) { + return; + } + + free (log->_msg); + free (log); +} + +void +laaf_log_callback (struct aafLog* log, void* ctxdata, int libid, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user) +{ + AAF_Iface* aafi = NULL; + AAF_Data* aafd = NULL; + CFB_Data* cfbd = NULL; + + const char* lib = ""; + const char* typestr = ""; + const char* color = ""; + + if (log->fp == NULL) { + DBG_BUFFER_RESET (log); + return; + } + + switch (libid) { + case DEBUG_SRC_ID_LIB_CFB: + lib = "libCFB"; + aafi = (AAF_Iface*)ctxdata; + break; + case DEBUG_SRC_ID_AAF_CORE: + lib = "AAFCore"; + aafd = (AAF_Data*)ctxdata; + break; + case DEBUG_SRC_ID_AAF_IFACE: + lib = "AAFIface"; + cfbd = (CFB_Data*)ctxdata; + break; + case DEBUG_SRC_ID_TRACE: + lib = "trace"; + aafi = (AAF_Iface*)ctxdata; + break; + case DEBUG_SRC_ID_DUMP: + lib = "dump"; + break; + } + + switch (type) { + case VERB_SUCCESS: + typestr = "success"; + color = ANSI_COLOR_GREEN (log); + break; + case VERB_ERROR: + typestr = " error "; + color = ANSI_COLOR_RED (log); + break; + case VERB_WARNING: + typestr = "warning"; + color = ANSI_COLOR_YELLOW (log); + break; + case VERB_DEBUG: + typestr = " debug "; + color = ANSI_COLOR_DARKGREY (log); + break; + } + + const char* eol = ""; + + if (libid != DEBUG_SRC_ID_TRACE && libid != DEBUG_SRC_ID_DUMP) { +#ifdef __MINGW32__ + fwprintf (log->fp, L"[%" WPRIs "%" WPRIs "%" WPRIs "] %" WPRIs "%" WPRIs ":%i in %" WPRIs "()%" WPRIs " : ", + color, + typestr, + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + srcfile, + lineno, + srcfunc, + ANSI_COLOR_RESET (log)); +#else + fprintf (log->fp, "[%s%s%s] %s%s:%i in %s()%s : ", + color, + typestr, + ANSI_COLOR_RESET (log), + ANSI_COLOR_DARKGREY (log), + srcfile, + lineno, + srcfunc, + ANSI_COLOR_RESET (log)); +#endif + } + + if (libid != DEBUG_SRC_ID_DUMP) { + eol = "\n"; + } + +#ifdef __MINGW32__ + wchar_t* tmp = laaf_util_windows_utf8toutf16 (msg); + if (!tmp) { + return; + } + fwprintf (log->fp, L"%" WPRIws "%s", tmp, eol); + free (tmp); +#else + fprintf (log->fp, "%s%s", msg, eol); +#endif + + fflush (log->fp); + + DBG_BUFFER_RESET (log); + + /* avoids -Wunused-parameter -Wunused-but-set-variable */ + (void)aafi; + (void)aafd; + (void)cfbd; + (void)lib; + (void)user; +} + +void +laaf_write_log (struct aafLog* log, void* ctxdata, enum debug_source_id lib, enum verbosityLevel_e type, const char* dbgfile, const char* dbgfunc, int dbgline, const char* format, ...) +{ + if (!log) { + return; + } + + if (!log->debug_callback) { + return; + } + + if (type != VERB_SUCCESS && (log->verb == VERB_QUIET || type > log->verb)) { + return; + } + + va_list ap; + + int rc = 0; + size_t msgsize = 0; + + va_start (ap, format); + +#ifdef _WIN32 + /* https://stackoverflow.com/a/4116308 */ + FILE* dummy = fopen ("NUL", "wb"); + + if (!dummy) { + // fprintf( stderr, "Could not fopen() dummy null file\n" ); + return; + } + + rc = vfprintf (dummy, format, ap); + + fclose (dummy); + + if (rc < 0) { + // fprintf( stderr, "vfwprintf() error : %s\n", strerror(errno) ); + va_end (ap); + return; + } + + rc++; + rc *= (int)sizeof (wchar_t); + +#else + rc = vsnprintf (NULL, 0, format, ap); + + if (rc < 0) { + // fprintf( stderr, "vsnprintf() error : %s\n", strerror(errno) ); + va_end (ap); + return; + } + + rc++; +#endif + + va_end (ap); + + msgsize = (size_t)rc; + + if (log->_msg_pos) { + log->_previous_pos = log->_msg_pos; + log->_previous_msg = laaf_util_c99strdup (log->_msg); + if (!log->_previous_msg) { + // fprintf( stderr, "Out of memory\n" ); + return; + } + } + + va_start (ap, format); + + if (msgsize >= log->_msg_size) { + char* msgtmp = realloc (log->_msg, (msgsize * sizeof (char))); + + if (!msgtmp) { + // fprintf( stderr, "Out of memory\n" ); + va_end (ap); + return; + } + + log->_msg = msgtmp; + log->_msg_size = msgsize; + } + + rc = vsnprintf (log->_msg, log->_msg_size, format, ap); + + if (rc < 0 || (size_t)rc >= log->_msg_size) { + // fprintf( stderr, "vsnprintf() error\n" ); + va_end (ap); + return; + } + + log->debug_callback (log, (void*)ctxdata, lib, type, dbgfile, dbgfunc, dbgline, log->_msg, log->user); + + va_end (ap); + + if (log->_previous_pos) { + log->_msg_pos = log->_previous_pos; + strcpy (log->_msg, log->_previous_msg); + free (log->_previous_msg); + log->_previous_msg = NULL; + log->_previous_pos = 0; + } +} diff --git a/libs/aaf/utils.c b/libs/aaf/utils.c index 568029031f..f2a7c32d8d 100644 --- a/libs/aaf/utils.c +++ b/libs/aaf/utils.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2023 Adrien Gesta-Fline + * Copyright (C) 2017-2024 Adrien Gesta-Fline * * This file is part of libAAF. * @@ -18,104 +18,107 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include +#include #include #include #include #include #include +#if defined(__linux__) +#include +#include +#include +#include /* access() */ +#elif defined(__APPLE__) +#include +#include /* access() */ +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#include +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define F_OK 0 /* Test for existence. */ +#ifndef _MSC_VER +#include // access() +#endif +#endif + #include "aaf/utils.h" #define BUILD_PATH_DEFAULT_BUF_SIZE 1024 -aafPosition_t -laaf_util_converUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate) +static int +utf8CodeLen (const uint16_t* u16Code); +static int +utf16CodeLen (const uint16_t* u16Code); +static int +utf16CodeToUTF8 (const uint16_t* u16Code, char* u8Code, int* u16Len, int* u8Len); +static long +utf8strLen (const uint16_t* u16str); + +#ifdef _WIN32 + +wchar_t* +laaf_util_windows_utf8toutf16 (const char* str) { - if (!valueEditRate || !destEditRate) { - return value; + if (!str) { + return NULL; } - if (valueEditRate->numerator == destEditRate->numerator && - valueEditRate->denominator == destEditRate->denominator) { - /* same rate, no conversion */ - return value; + int needed = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0); + + if (needed == 0) { + return NULL; } - double valueEditRateFloat = ((valueEditRate->denominator == 0) ? 0.0 : ((float)valueEditRate->numerator / valueEditRate->denominator)); - double destEditRateFloat = ((destEditRate->denominator == 0) ? 0.0 : ((float)destEditRate->numerator / destEditRate->denominator)); + wchar_t* wbuf = malloc ((size_t)needed * sizeof (wchar_t)); - if (valueEditRateFloat == 0) { - return 0; + if (!wbuf) { + return NULL; } - return value * (destEditRateFloat / valueEditRateFloat); + int rc = MultiByteToWideChar (CP_UTF8, 0, str, -1, wbuf, needed); + + if (rc == 0) { + free (wbuf); + return NULL; + } + + return wbuf; } char* -laaf_util_wstr2str (const wchar_t* wstr) +laaf_util_windows_utf16toutf8 (const wchar_t* wstr) { - if (wstr == NULL) { + if (!wstr) { return NULL; } - size_t strsz = wcslen (wstr) + 1; - char* str = malloc (strsz); + int needed = WideCharToMultiByte (CP_UTF8, 0, wstr, -1, NULL, 0, 0, 0); - if (str == NULL) { - // error( "Could not allocate memory : %s", strerror(errno) ); + if (needed == 0) { return NULL; } - int rc = snprintf (str, strsz, "%ls", wstr); + char* buf = malloc ((size_t)needed * sizeof (char)); - if (rc < 0 || (unsigned)rc >= strsz) { - // error( "Failed converting wide char str to byte char str%s", (reqlen < 0) ? " : encoding error" : "" ); - free (str); + if (!buf) { return NULL; } - return str; + int rc = WideCharToMultiByte (CP_UTF8, 0, wstr, -1, buf, needed, 0, 0); + + if (rc == 0) { + free (buf); + return NULL; + } + + return buf; } -wchar_t* -laaf_util_str2wstr (const char* str) -{ - if (str == NULL) { - return NULL; - } - - size_t strsz = strlen (str) + 1; - wchar_t* wstr = malloc (strsz * sizeof (wchar_t)); - - if (str == NULL) { - // error( "Could not allocate memory : %s", strerror(errno) ); - return NULL; - } - - int rc = swprintf (wstr, strsz, L"%" WPRIs, str); - - if (rc < 0 || (unsigned)rc >= strsz) { - // error( "Failed converting byte char str to wide char str%s", (reqlen < 0) ? " : encoding error" : "" ); - free (wstr); - return NULL; - } - - return wstr; -} - -int -laaf_util_wstr_contains_nonlatin (const wchar_t* str) -{ - for (size_t i = 0; str[i] != 0x0000; i++) { - /* if char is out of the Basic Latin range */ - if (str[i] > 0xff) { - return 1; - } - } - - return 0; -} +#endif char* laaf_util_clean_filename (char* fname) @@ -124,62 +127,52 @@ laaf_util_clean_filename (char* fname) * sanitize file/dir name * https://stackoverflow.com/a/31976060 */ - size_t len = strlen (fname); + if (!fname) { + return NULL; + } - for (size_t i = 0; i < len; i++) { - unsigned char c = fname[i]; + char* p = fname; - if (c == '/' || - c == '<' || - c == '>' || - c == ':' || - c == '"' || - c == '|' || - c == '?' || - c == '*' || - c == '\\' || - (c > 0 && c < 0x20)) { - fname[i] = '_'; + while (*p) { + if (*p == '/' || + *p == '<' || + *p == '>' || + *p == ':' || + *p == '"' || + *p == '|' || + *p == '?' || + *p == '*' || + *p == '\\' || + (*p > 0 && *p < 0x20)) { + *p = '_'; } + p++; } /* windows filenames can't end with ' ' or '.' */ - for (int i = len - 1; i > 0; i--) { - char c = fname[i]; - if (c != ' ' && c != '.') { - break; - } - fname[i] = '_'; + + p = fname + strlen (fname) - 1; + + while (*p && (*p == ' ' || *p == '.')) { + *p = '\0'; + p--; } + if (*fname == '\0') + return NULL; + return fname; } -const char* -laaf_util_fop_get_file (const char* filepath) -{ - if (filepath == NULL) { - return NULL; - } - - const char* end = filepath + strlen (filepath); - - while (end > filepath && !IS_DIR_SEP (*end)) { - --end; - } - - return (IS_DIR_SEP (*end)) ? end + 1 : end; -} - int -laaf_util_fop_is_wstr_fileext (const wchar_t* filepath, const wchar_t* ext) +laaf_util_is_fileext (const char* filepath, const char* ext) { - if (filepath == NULL) { + if (!filepath || !ext) { return 0; } - const wchar_t* end = filepath + wcslen (filepath); - size_t extlen = 0; + const char* end = filepath + strlen (filepath); + size_t extlen = 0; while (end > filepath && (*end) != '.') { --end; @@ -191,14 +184,11 @@ laaf_util_fop_is_wstr_fileext (const wchar_t* filepath, const wchar_t* ext) extlen--; } - if (extlen != wcslen (ext)) { + if (!extlen || extlen != strlen (ext)) { return 0; } - // printf(" end: %ls ext: %ls\n", end, ext ); - for (size_t i = 0; i < extlen; i++) { - // printf("end: %c != %c\n", *(end+i), *(ext+i)); if (tolower (*(end + i)) != tolower (*(ext + i))) { return 0; } @@ -212,7 +202,7 @@ laaf_util_build_path (const char* sep, const char* first, ...) { char* str = malloc (BUILD_PATH_DEFAULT_BUF_SIZE); - if (str == NULL) { + if (!str) { return NULL; } @@ -232,13 +222,13 @@ laaf_util_build_path (const char* sep, const char* first, ...) const char* arg = first; do { - int arglen = strlen (arg); - int argstart = 0; - int has_leading_sep = 0; + size_t arglen = strlen (arg); + size_t argstart = 0; + int has_leading_sep = 0; /* trim leading DIR_SEP */ for (int i = 0; arg[i] != 0x00; i++) { - if (IS_DIR_SEP (arg[i])) { + if (IS_ANY_DIR_SEP (arg[i])) { has_leading_sep = 1; argstart++; } else { @@ -247,39 +237,41 @@ laaf_util_build_path (const char* sep, const char* first, ...) } /* trim trailing DIR_SEP */ - for (int i = arglen - 1; i >= argstart; i--) { - if (IS_DIR_SEP (arg[i])) { + for (size_t i = arglen - 1; i >= argstart; i--) { + if (IS_ANY_DIR_SEP (arg[i])) { arglen--; } else { break; } } - /* TODO ? */ - if (element_count == 0 && has_leading_sep) { - } else { - } - - size_t reqlen = snprintf (NULL, 0, "%.*s", arglen - argstart, arg + argstart) + 1; + size_t reqlen = (arglen - argstart) + 2; if (offset + reqlen >= len) { - reqlen = ((offset + reqlen) > (len + BUILD_PATH_DEFAULT_BUF_SIZE)) ? (offset + reqlen) : (len + BUILD_PATH_DEFAULT_BUF_SIZE); + reqlen = ((offset + reqlen) > (len + BUILD_PATH_DEFAULT_BUF_SIZE)) ? (reqlen) : (len + BUILD_PATH_DEFAULT_BUF_SIZE); char* tmp = realloc (str, (offset + reqlen)); - if (tmp) { - str = tmp; - len = (offset + reqlen); - } else { + if (!tmp) { free (str); return NULL; } + + str = tmp; + len = (offset + reqlen); } - offset += snprintf (str + offset, len - offset, "%s%.*s", - ((element_count == 0 && has_leading_sep) || (element_count > 0)) ? sep : "", - arglen - argstart, - arg + argstart); + int written = snprintf (str + offset, len - offset, "%s%.*s", + ((element_count == 0 && has_leading_sep) || (element_count > 0)) ? sep : "", + (uint32_t) (arglen - argstart), + arg + argstart); + + if (written < 0 || (size_t)written >= (len - offset)) { + free (str); + return NULL; + } + + offset += (size_t)written; element_count++; @@ -287,29 +279,183 @@ laaf_util_build_path (const char* sep, const char* first, ...) va_end (args); + /* do not mix between different dirseps and removes any consecutive dirseps */ + char* i = str; + char* o = str; + int dirseppassed = 0; + while (*i) { + if (!dirseppassed && IS_ANY_DIR_SEP (*i)) { + *o = *sep; + o++; + dirseppassed = 1; + } else if (!IS_ANY_DIR_SEP (*i)) { + dirseppassed = 0; + *o = *i; + o++; + } + i++; + } + *o = '\0'; + return str; } -int -laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* format, ...) +char* +laaf_util_relative_path (const char* filepath, const char* refpath) { - int tmpsize = 0; + if (!filepath || !refpath || filepath[0] == '\0' || refpath[0] == '\0') { + return NULL; + } + + // fprintf( stderr, "%s\n", filepath ); + // fprintf( stderr, "%s\n", refpath ); + + int isWindowsPath = 0; + int aWindowsPath = 0; + int bWindowsPath = 0; + + char* relpath = NULL; + + if (filepath[0] != '\0' && isalpha (filepath[0]) && filepath[1] == ':') { + aWindowsPath = 1; + } + + if (refpath[0] != '\0' && isalpha (refpath[0]) && refpath[1] == ':') { + bWindowsPath = 1; + } + + isWindowsPath = (aWindowsPath + bWindowsPath); + + if (isWindowsPath == 1) { + // fprintf( stderr, "Trying to make a relative path out of a windows path and a non-windows path\n" ); + return NULL; + } + + if (isWindowsPath == 2) { + if (tolower (filepath[0]) != tolower (refpath[0])) { + // fprintf( stderr, "Both paths target different drives\n" ); + return NULL; + } + } + + int winDriveLetterOffset = isWindowsPath; + + if (strncmp (filepath + winDriveLetterOffset, refpath + winDriveLetterOffset, strlen (refpath)) == 0) { + relpath = laaf_util_build_path ("/", "./", filepath + strlen (refpath), NULL); + return relpath; + } + + char* _filepath = laaf_util_build_path ("/", filepath, NULL); + char* _refpath = laaf_util_build_path ("/", refpath, "/", NULL); /* ensures there is always a trailing '/' */ + + if (!_filepath || !_refpath) { + return NULL; + } + + char* parents = NULL; + size_t parentsLen = 0; + size_t parentsOffset = 0; + + char* p = _refpath + strlen (_refpath); + + while (p > (_refpath + winDriveLetterOffset)) { + while (p > (_refpath + winDriveLetterOffset) && !IS_DIR_SEP (*p)) { + *p = '\0'; + p--; + } + + if (strncmp (_filepath + winDriveLetterOffset, _refpath + winDriveLetterOffset, strlen (_refpath + winDriveLetterOffset)) == 0) { + if (!parents) { + relpath = laaf_util_build_path ("/", "./", _filepath + strlen (_refpath), NULL); + goto end; + } else { + relpath = laaf_util_build_path ("/", parents, _filepath + strlen (_refpath), NULL); + goto end; + } + } + + int ret = laaf_util_snprintf_realloc (&parents, &parentsLen, parentsOffset, "../"); + + assert (ret >= 0); + + parentsOffset += (size_t)ret; + p--; + } + +end: + free (parents); + free (_filepath); + free (_refpath); + + return relpath; +} + +char* +laaf_util_absolute_path (const char* relpath) +{ + if (!relpath) { + return NULL; + } + +#ifdef _WIN32 + // char *abspath = NULL; + wchar_t buf[_MAX_PATH]; + + wchar_t* wrelpath = laaf_util_windows_utf8toutf16 (relpath); + + if (!wrelpath) { + return NULL; + } + + if (!_wfullpath (buf, wrelpath, _MAX_PATH)) { + free (wrelpath); + return NULL; + } + + char* abspath = laaf_util_windows_utf16toutf8 (buf); + + if (!abspath) { + free (wrelpath); + return NULL; + } + + free (wrelpath); + + return abspath; + +#else + char buf[PATH_MAX + 1]; + + if (!realpath (relpath, buf)) { + return NULL; + } + + return laaf_util_c99strdup (buf); + +#endif +} + +int +laaf_util_snprintf_realloc (char** str, size_t* size, size_t offset, const char* format, ...) +{ + size_t tmpsize = 0; if (!size) { size = &tmpsize; } - int retval, needed; + int retval = 0; + size_t needed = 0; va_list ap; va_start (ap, format); - while (0 <= (retval = vsnprintf ((*str) + offset, (*size) - offset, format, ap)) && (int64_t) ((*size) - offset) < (needed = retval + 1)) { + while (0 <= (retval = vsnprintf ((*str) + offset, (*size) - offset, format, ap)) && ((*size) - offset) < (needed = (unsigned)retval + 1)) { va_end (ap); *size *= 2; - if ((int64_t) ((*size) - offset) < needed) + if (((*size) - offset) < needed) *size = needed + offset; char* p = realloc (*str, *size); @@ -320,7 +466,7 @@ laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* fo free (*str); *str = NULL; *size = 0; - return -1; + return 0; } va_start (ap, format); @@ -328,38 +474,254 @@ laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* fo va_end (ap); - return retval; + return (retval > 0) ? retval : 0; } int -laaf_util_vsnprintf_realloc (char** str, int* size, int offset, const char* fmt, va_list* args) +laaf_util_file_exists (const char* filepath) { - va_list args2, args3; +#ifdef _WIN32 + int needed = MultiByteToWideChar (CP_UTF8, 0, filepath, -1, NULL, 0); - va_copy (args2, *args); - va_copy (args3, *args); + if (needed == 0) { + return -1; + } - int needed = vsnprintf (NULL, 0, fmt, args2) + 1; + wchar_t* wfilepath = malloc ((size_t)needed * sizeof (wchar_t)); + + if (!wfilepath) { + return -1; + } + + int rc = MultiByteToWideChar (CP_UTF8, 0, filepath, -1, wfilepath, needed); + + if (rc == 0) { + free (wfilepath); + return -1; + } + + if (_waccess (wfilepath, F_OK) == 0) { + free (wfilepath); + return 1; + } + + free (wfilepath); + +#else + if (access (filepath, F_OK) == 0) { + return 1; + } +#endif + + return 0; +} + +static int +utf8CodeLen (const uint16_t* u16Code) +{ + if (u16Code[0] < 0x80) { + return 1; + } else if (u16Code[0] < 0x800) { + return 2; + } else if (u16Code[0] < 0xD800 || + u16Code[0] > 0xDFFF) { + return 3; + } else if (((u16Code[0] & 0xFC00) == 0xD800) && + ((u16Code[1] & 0xFC00) == 0xDC00)) { + return 4; + } else { + return -1; + } +} + +static int +utf16CodeLen (const uint16_t* u16Code) +{ + if (u16Code[0] < 0xD800 || + u16Code[0] > 0xDFFF) { + return 1; + } else if (((u16Code[0] & 0xFC00) == 0xD800) && + ((u16Code[1] & 0xFC00) == 0xDC00)) { + return 2; + } else { + return -1; + } +} + +static int +utf16CodeToUTF8 (const uint16_t* u16Code, char* u8Code, int* u16Len, int* u8Len) +{ + int len8 = utf8CodeLen (u16Code); + int len16 = utf16CodeLen (u16Code); + + if (len8 < 0 || len16 < 0) { + return -1; + } + + *u8Len = len8; + *u16Len = len16; + + if (len8 == 1) { + u8Code[0] = (char)(u16Code[0]); + } else if (len8 == 2) { + u8Code[0] = (char)(0xC0 | (u16Code[0] >> 6)); + u8Code[1] = (char)(0x80 | (u16Code[0] & 0x3F)); + } else if (len8 == 3) { + u8Code[0] = (char)(0xE0 | (u16Code[0] >> 12)); + u8Code[1] = (char)(0x80 | ((u16Code[0] >> 6) & 0x3F)); + u8Code[2] = (char)(0x80 | (u16Code[0] & 0x3F)); + } else { + uint32_t c = (u16Code[0] & 0x03FF) << 10; + + c |= (u16Code[1] & 0x03FF); + c += 0x10000; + + u8Code[0] = (char)(0xF0 | ((c >> 18) & 0x07)); + u8Code[1] = (char)(0x80 | ((c >> 12) & 0x3F)); + u8Code[2] = (char)(0x80 | ((c >> 6) & 0x3F)); + u8Code[3] = (char)(0x80 | (c & 0x3F)); + } + + return *u8Len; +} + +static long +utf8strLen (const uint16_t* u16str) +{ + long len = 0; + const uint16_t* p = u16str; + + while (*p != 0x0000) { + int u8CodeLen = utf8CodeLen (p); + int u16CodeLen = utf16CodeLen (p); + + if (u8CodeLen < 0 || u16CodeLen < 0) { + len = -1; + break; + } + + p += u16CodeLen; + len += u8CodeLen; + } + + return len; +} + +size_t +laaf_util_utf8strCharLen (const char* u8str) +{ + size_t count = 0; + + while (*u8str) { + count += (*u8str++ & 0xC0) != 0x80; + } + + return count; +} + +char* +laaf_util_utf16Toutf8 (const uint16_t* u16str) +{ + long u8len = utf8strLen (u16str); + + if (u8len < 0) { + return 0; + } + + char* u8str = calloc ((size_t)u8len + 1, sizeof (char)); + + if (!u8str) { + return NULL; + } + + const uint16_t* u16ptr = u16str; + char* u8ptr = u8str; + + while (*u16ptr != 0x0000) { + int u8codelen = 0; + int u16codelen = 0; + + utf16CodeToUTF8 (u16ptr, u8ptr, &u16codelen, &u8codelen); + + if (u16codelen < 0 || u8codelen < 0) { + free (u8str); + return NULL; + } + + u8ptr += u8codelen; + u16ptr += u16codelen; + } + + *u8ptr = 0x00; + + return u8str; +} + +int +laaf_util_vsnprintf_realloc (char** str, size_t* size, size_t offset, const char* fmt, va_list args) +{ + FILE* dummy = NULL; + va_list args1; + + size_t tmpsize = 0; + + if (size == NULL) { + size = &tmpsize; + } + + va_copy (args1, args); + + /* https://stackoverflow.com/a/4116308 */ +#ifndef _WIN32 + dummy = fopen ("/dev/null", "wb"); +#else + dummy = fopen ("NUL", "wb"); +#endif + + if (!dummy) { + // fprintf( stderr, "Could not fopen() dummy null file\n" ); + goto err; + } + + int retval = vfprintf (dummy, fmt, args); + + if (retval < 0) { + // fprintf( stderr, "vfprintf() error : %s\n", strerror(errno) ); + goto err; + } + + unsigned needed = (unsigned)retval + 1; if (needed >= (*size) - offset) { - char* p = realloc (*str, offset + needed); + char* p = realloc (*str, (offset + needed) * sizeof (char)); if (p) { *str = p; *size = offset + needed; } else { - /* If realloc() fails, the original block is left untouched; it is not freed or moved. */ - va_end (args2); - va_end (args3); - - return -1; + goto err; } } - va_end (args2); - int written = vsnprintf ((*str) + offset, (*size) - offset, fmt, args3); + int written = vsnprintf ((*str) + offset, (*size) - offset, fmt, args1); - va_end (args3); + // assert( written >= 0 && (size_t)written < (*size)-offset ); + + if (written < 0 && (size_t)written >= (*size) - offset) { + fprintf (stderr, "vsnprintf() error : %s\n", strerror (errno)); + goto err; + } + + goto end; + +err: + written = -1; + +end: + + if (dummy) { + fclose (dummy); + } return written; } @@ -371,7 +733,7 @@ laaf_util_c99strdup (const char* src) return NULL; } - int len = 0; + size_t len = 0; while (src[len]) { len++; @@ -379,8 +741,9 @@ laaf_util_c99strdup (const char* src) char* str = malloc (len + 1); - if (!str) + if (!str) { return NULL; + } char* p = str; @@ -394,24 +757,30 @@ laaf_util_c99strdup (const char* src) } int -laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, int* bufsz, int offset) +laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, size_t* bufsz, size_t offset, const char* padding) { if (stream == NULL) { return -1; } - int initialOffset = offset; + size_t initialOffset = offset; uint32_t i = 0; char hex[49]; char ascii[19]; - uint32_t count = 0; + size_t count = 0; - offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " ______________________________ Hex Dump ______________________________\n\n"); + int rc = laaf_util_snprintf_realloc (buf, bufsz, offset, "%s______________________________ Hex Dump ______________________________\n\n", padding); + + if (rc < 0) { + goto end; + } + + offset += (size_t)rc; while (count < stream_sz) { - uint32_t lineLen = (stream_sz - count) / 16; + size_t lineLen = (stream_sz - count) / 16; if (lineLen <= 0) lineLen = (stream_sz) % 16; @@ -424,22 +793,28 @@ laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, i uint32_t linepos = 0; for (i = 0; i < lineLen; i++) { - linepos += snprintf (&hex[linepos], sizeof (hex) - (linepos), "%02x%s", *(const unsigned char*)(stream + count + i), (i == 7) ? " " : " "); + rc = snprintf (&hex[linepos], sizeof (hex) - (linepos), "%02x%s", *(const unsigned char*)(stream + count + i), (i == 7) ? " " : " "); + + if (rc < 0) { + goto end; + } + + linepos += (uint32_t)rc; if (i < 8) { if (isalnum (*(stream + count + i))) - ascii[i] = *(const unsigned char*)(stream + count + i); + ascii[i] = *(const char*)(stream + count + i); else ascii[i] = '.'; } else if (i > 8) { if (isalnum (*(stream + count + i))) - ascii[i + 1] = *(const unsigned char*)(stream + count + i); + ascii[i + 1] = *(const char*)(stream + count + i); else ascii[i + 1] = '.'; } else { if (isalnum (*(stream + count + i))) { ascii[i] = ' '; - ascii[i + 1] = *(const unsigned char*)(stream + count + i); + ascii[i + 1] = *(const char*)(stream + count + i); } else { ascii[i] = ' '; ascii[i + 1] = '.'; @@ -459,10 +834,21 @@ laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, i count += lineLen; - offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " %s | %s\n", hex, ascii); + rc = laaf_util_snprintf_realloc (buf, bufsz, offset, "%s%s | %s\n", padding, hex, ascii); + + if (rc < 0) { + goto end; + } + + offset += (size_t)rc; } - offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " ______________________________________________________________________\n\n"); + rc = laaf_util_snprintf_realloc (buf, bufsz, offset, "%s______________________________________________________________________\n\n", padding); - return offset - initialOffset; /* bytes written */ + if (rc < 0) { + goto end; + } + +end: + return (int)(offset - initialOffset); /* bytes written */ } diff --git a/libs/aaf/wscript b/libs/aaf/wscript index 3135f9229c..9c9f089567 100644 --- a/libs/aaf/wscript +++ b/libs/aaf/wscript @@ -19,18 +19,19 @@ libaaf_sources = [ 'AAFClass.c', 'AAFCore.c', 'AAFDump.c', - 'AAFIAudioFiles.c', + 'AAFIEssenceFile.c', 'AAFIface.c', 'AAFIParser.c', 'AAFToText.c', 'CFBDump.c', 'LibCFB.c', 'ProTools.c', + 'MediaComposer.c', 'Resolve.c', 'RIFFParser.c', 'URIParser.c', 'utils.c', - 'debug.c', + 'log.c', ] def options(opt):