Update libAAF (upstream v0.6-45-g9171e40)
This commit is contained in:
parent
477cff6980
commit
a5f4bf39d1
@ -880,43 +880,43 @@ parse_Header (AAF_Data* aafd)
|
||||
|
||||
if (ByteOrder == NULL) {
|
||||
warning ("Missing Header::ByteOrder.");
|
||||
} else {
|
||||
aafd->Header.ByteOrder = *ByteOrder;
|
||||
}
|
||||
|
||||
aafd->Header.ByteOrder = *ByteOrder;
|
||||
|
||||
aafTimeStamp_t* LastModified = aaf_get_propertyValue (Header, PID_Header_LastModified, &AAFTypeID_TimeStamp);
|
||||
|
||||
if (LastModified == NULL) {
|
||||
warning ("Missing Header::LastModified.");
|
||||
} else {
|
||||
aafd->Header.LastModified = LastModified;
|
||||
}
|
||||
|
||||
aafd->Header.LastModified = LastModified;
|
||||
|
||||
aafVersionType_t* Version = aaf_get_propertyValue (Header, PID_Header_Version, &AAFTypeID_VersionType);
|
||||
|
||||
if (Version == NULL) {
|
||||
warning ("Missing Header::Version.");
|
||||
} else {
|
||||
aafd->Header.Version = Version;
|
||||
}
|
||||
|
||||
aafd->Header.Version = Version;
|
||||
|
||||
uint32_t* ObjectModelVersion = aaf_get_propertyValue (Header, PID_Header_ObjectModelVersion, &AAFTypeID_UInt32);
|
||||
|
||||
if (ObjectModelVersion == NULL) {
|
||||
warning ("Missing Header::ObjectModelVersion.");
|
||||
} else {
|
||||
aafd->Header.ObjectModelVersion = *ObjectModelVersion;
|
||||
}
|
||||
|
||||
aafd->Header.ObjectModelVersion = *ObjectModelVersion;
|
||||
|
||||
const aafUID_t* OperationalPattern = aaf_get_propertyValue (Header, PID_Header_OperationalPattern, &AAFTypeID_AUID);
|
||||
|
||||
if (OperationalPattern == NULL) {
|
||||
warning ("Missing Header::OperationalPattern.");
|
||||
OperationalPattern = (const aafUID_t*)&AUID_NULL;
|
||||
aafd->Header.OperationalPattern = (const aafUID_t*)&AUID_NULL;
|
||||
} else {
|
||||
aafd->Header.OperationalPattern = OperationalPattern;
|
||||
}
|
||||
|
||||
aafd->Header.OperationalPattern = OperationalPattern;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -934,74 +934,74 @@ parse_Identification (AAF_Data* aafd)
|
||||
|
||||
if (Company == NULL) {
|
||||
warning ("Missing Identification::CompanyName.");
|
||||
} else {
|
||||
aafd->Identification.CompanyName = Company;
|
||||
}
|
||||
|
||||
aafd->Identification.CompanyName = Company;
|
||||
|
||||
wchar_t* ProductName = aaf_get_propertyValue (Identif, PID_Identification_ProductName, &AAFTypeID_String);
|
||||
|
||||
if (ProductName == NULL) {
|
||||
warning ("Missing Identification::ProductName.");
|
||||
} else {
|
||||
aafd->Identification.ProductName = ProductName;
|
||||
}
|
||||
|
||||
aafd->Identification.ProductName = ProductName;
|
||||
|
||||
aafProductVersion_t* ProductVersion = aaf_get_propertyValue (Identif, PID_Identification_ProductVersion, &AAFTypeID_ProductVersion);
|
||||
|
||||
if (ProductVersion == NULL) {
|
||||
warning ("Missing Identification::ProductVersion.");
|
||||
} else {
|
||||
aafd->Identification.ProductVersion = ProductVersion;
|
||||
}
|
||||
|
||||
aafd->Identification.ProductVersion = ProductVersion;
|
||||
|
||||
wchar_t* ProductVersionString = aaf_get_propertyValue (Identif, PID_Identification_ProductVersionString, &AAFTypeID_String);
|
||||
|
||||
if (ProductVersionString == NULL) {
|
||||
warning ("Missing Identification::ProductVersionString.");
|
||||
} else {
|
||||
aafd->Identification.ProductVersionString = ProductVersionString;
|
||||
}
|
||||
|
||||
aafd->Identification.ProductVersionString = ProductVersionString;
|
||||
|
||||
aafUID_t* ProductID = aaf_get_propertyValue (Identif, PID_Identification_ProductID, &AAFTypeID_AUID);
|
||||
|
||||
if (ProductID == NULL) {
|
||||
warning ("Missing Identification::ProductID.");
|
||||
} else {
|
||||
aafd->Identification.ProductID = ProductID;
|
||||
}
|
||||
|
||||
aafd->Identification.ProductID = ProductID;
|
||||
|
||||
aafTimeStamp_t* Date = aaf_get_propertyValue (Identif, PID_Identification_Date, &AAFTypeID_TimeStamp);
|
||||
|
||||
if (Date == NULL) {
|
||||
warning ("Missing Identification::Date.");
|
||||
} else {
|
||||
aafd->Identification.Date = Date;
|
||||
}
|
||||
|
||||
aafd->Identification.Date = Date;
|
||||
|
||||
aafProductVersion_t* ToolkitVersion = aaf_get_propertyValue (Identif, PID_Identification_ToolkitVersion, &AAFTypeID_ProductVersion);
|
||||
|
||||
if (ToolkitVersion == NULL) {
|
||||
warning ("Missing Identification::ToolkitVersion.");
|
||||
} else {
|
||||
aafd->Identification.ToolkitVersion = ToolkitVersion;
|
||||
}
|
||||
|
||||
aafd->Identification.ToolkitVersion = ToolkitVersion;
|
||||
|
||||
wchar_t* Platform = aaf_get_propertyValue (Identif, PID_Identification_Platform, &AAFTypeID_String);
|
||||
|
||||
if (Platform == NULL) {
|
||||
warning ("Missing Identification::Platform.");
|
||||
} else {
|
||||
aafd->Identification.Platform = Platform;
|
||||
}
|
||||
|
||||
aafd->Identification.Platform = Platform;
|
||||
|
||||
aafUID_t* GenerationAUID = aaf_get_propertyValue (Identif, PID_Identification_GenerationAUID, &AAFTypeID_AUID);
|
||||
|
||||
if (GenerationAUID == NULL) {
|
||||
warning ("Missing Identification::GenerationAUID.");
|
||||
} else {
|
||||
aafd->Identification.GenerationAUID = GenerationAUID;
|
||||
}
|
||||
|
||||
aafd->Identification.GenerationAUID = GenerationAUID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ embeddedAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLe
|
||||
static size_t
|
||||
externalAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLen, void* user1, void* user2, void* user3);
|
||||
|
||||
char*
|
||||
wchar_t*
|
||||
aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_filepath, const char* search_location)
|
||||
{
|
||||
/*
|
||||
@ -82,10 +82,11 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
* uses the / character as the path separator.
|
||||
*/
|
||||
|
||||
char* uri_filepath = NULL;
|
||||
char* local_filepath = NULL;
|
||||
char* aaf_path = NULL;
|
||||
char* retpath = NULL;
|
||||
char* uri_filepath = NULL;
|
||||
char* local_filepath = NULL;
|
||||
char* aaf_path = NULL;
|
||||
char* foundpath = NULL;
|
||||
wchar_t* retpath = NULL;
|
||||
|
||||
struct uri* uri = NULL;
|
||||
|
||||
@ -94,23 +95,14 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
goto err;
|
||||
}
|
||||
|
||||
size_t uri_filepath_len = wcslen (original_uri_filepath) + 1;
|
||||
|
||||
uri_filepath = malloc (uri_filepath_len);
|
||||
uri_filepath = laaf_util_wstr2str (original_uri_filepath);
|
||||
|
||||
if (uri_filepath == NULL) {
|
||||
error ("Could not allocate memory : %s", strerror (errno));
|
||||
error ("Could not convert original_uri_filepath from wstr to str : %ls", original_uri_filepath);
|
||||
goto err;
|
||||
}
|
||||
|
||||
int reqlen = snprintf (uri_filepath, uri_filepath_len, "%ls", original_uri_filepath);
|
||||
|
||||
if (reqlen < 0 || (unsigned)reqlen >= uri_filepath_len) {
|
||||
error ("Failed converting wide char URI filepath to byte char%s", (reqlen < 0) ? " : encoding error" : "");
|
||||
goto err;
|
||||
}
|
||||
|
||||
// debug( "Original URI filepath : %s", uri_filepath );
|
||||
// debug( "Original URI : %s", uri_filepath );
|
||||
|
||||
uri = uriParse (uri_filepath, URI_OPT_DECODE_ALL, aafi->dbg);
|
||||
|
||||
@ -124,7 +116,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
goto err;
|
||||
}
|
||||
|
||||
// debug( "Decoded URI's filepath : %s", uri->path );
|
||||
// debug( "Decoded URI's path : %s", uri->path );
|
||||
|
||||
/* extract relative path to essence file : "<firstparent>/<essence.file>" */
|
||||
|
||||
@ -164,7 +156,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
|
||||
if (access (local_filepath, F_OK) != -1) {
|
||||
// debug( "FOUND: %s", local_filepath );
|
||||
retpath = local_filepath;
|
||||
foundpath = local_filepath;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@ -186,7 +178,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
|
||||
if (access (local_filepath, F_OK) != -1) {
|
||||
// debug( "FOUND: %s", local_filepath );
|
||||
retpath = local_filepath;
|
||||
foundpath = local_filepath;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@ -198,7 +190,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
|
||||
if (access (uri_filepath, F_OK) != -1) {
|
||||
// debug( "FOUND: %s", uri_filepath );
|
||||
retpath = uri_filepath;
|
||||
foundpath = uri_filepath;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@ -206,7 +198,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
|
||||
if (access (uri->path, F_OK) != -1) {
|
||||
// debug( "FOUND: %s", uri->path );
|
||||
retpath = uri->path;
|
||||
foundpath = uri->path;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@ -265,7 +257,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
|
||||
if (access (local_filepath, F_OK) != -1) {
|
||||
// debug( "FOUND: %s", filepath );
|
||||
retpath = local_filepath;
|
||||
foundpath = local_filepath;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@ -287,7 +279,7 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
|
||||
if (access (local_filepath, F_OK) != -1) {
|
||||
// debug( "FOUND: %s", filepath );
|
||||
retpath = local_filepath;
|
||||
foundpath = local_filepath;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@ -297,7 +289,15 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_uri_
|
||||
// debug("File not found");
|
||||
|
||||
found:
|
||||
retpath = laaf_util_c99strdup (retpath);
|
||||
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:
|
||||
@ -414,7 +414,7 @@ aafi_extract_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence, con
|
||||
memset (&wavBext, 0x00, sizeof (wavBext));
|
||||
memcpy (wavBext.umid, audioEssence->sourceMobID, sizeof (aafMobID_t));
|
||||
if (audioEssence->mobSlotEditRate) {
|
||||
wavBext.time_reference = eu2sample (audioEssence->samplerate, audioEssence->mobSlotEditRate, audioEssence->timeReference);
|
||||
wavBext.time_reference = laaf_util_converUnit (audioEssence->timeReference, audioEssence->mobSlotEditRate, audioEssence->samplerateRational);
|
||||
}
|
||||
|
||||
if (datasz >= (uint32_t)-1) {
|
||||
@ -443,10 +443,10 @@ aafi_extract_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence, con
|
||||
goto err;
|
||||
}
|
||||
|
||||
reqlen = swprintf (audioEssence->usable_file_path, strlen (filepath) + 1, L"%" WPRIs, filepath);
|
||||
audioEssence->usable_file_path = laaf_util_str2wstr (filepath);
|
||||
|
||||
if (reqlen < 0) {
|
||||
error ("Failed setting usable_file_path");
|
||||
if (audioEssence->usable_file_path == NULL) {
|
||||
error ("Could not convert usable_file_path from str to wstr : %s", filepath);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -473,94 +473,118 @@ end:
|
||||
}
|
||||
|
||||
int
|
||||
aafi_parse_audio_summary (AAF_Iface* aafi, aafiAudioEssence* audioEssence)
|
||||
aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence)
|
||||
{
|
||||
// laaf_util_dump_hex( audioEssence->summary->val, audioEssence->summary->len );
|
||||
|
||||
int rc = 0;
|
||||
char* externalFilePath = NULL;
|
||||
FILE* fp = NULL;
|
||||
// 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;
|
||||
|
||||
if (audioEssence->is_embedded) {
|
||||
if (audioEssence->summary == NULL) {
|
||||
warning ("TODO: Audio essence has no summary. TODO: Should try essence data stream ?");
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adobe Premiere Pro, embedded mp3/mp4 files converted to PCM/AIFF on export, AAFClassID_AIFCDescriptor, 'COMM' is valid.
|
||||
* ______________________________ Hex Dump ______________________________
|
||||
*
|
||||
* 46 4f 52 4d 00 00 00 32 41 49 46 43 43 4f 4d 4d | FORM...2 AIFCCOMM
|
||||
* 00 00 00 26 00 01 00 00 00 00 00 10 40 0e bb 80 | ........ ........
|
||||
* 00 00 00 00 00 00 4e 4f 4e 45 0e 4e 6f 74 20 43 | ......NO NE.Not.C
|
||||
* 6f 6d 70 72 65 73 73 65 64 00 | ompresse d.
|
||||
* ______________________________________________________________________
|
||||
*/
|
||||
fp = fopen (externalFilePath, "rb");
|
||||
|
||||
// laaf_util_dump_hex( audioEssence->summary->val, audioEssence->summary->len );
|
||||
if (fp == NULL) {
|
||||
error ("Could not open external audio essence file for reading : %s", externalFilePath);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = riff_parseAudioFile (&RIFFAudioFile, RIFF_PARSE_ONLY_HEADER, &embeddedAudioDataReaderCallback, audioEssence->summary->val, &audioEssence->summary->len, aafi, aafi->dbg);
|
||||
rc = riff_parseAudioFile (&RIFFAudioFile, 0, &externalAudioDataReaderCallback, fp, externalFilePath, aafi, aafi->dbg);
|
||||
|
||||
if (rc < 0) {
|
||||
warning ("TODO: Could not parse embedded essence summary. Should try essence data stream ?");
|
||||
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.duration;
|
||||
audioEssence->length = RIFFAudioFile.sampleCount;
|
||||
|
||||
audioEssence->samplerateRational->numerator = audioEssence->samplerate;
|
||||
audioEssence->samplerateRational->denominator = 1;
|
||||
} else {
|
||||
/* TODO: can external essence have audioEssence->summary too ? If mp3 (Resolve 18.5.aaf) ? */
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
externalFilePath = aafi_locate_external_essence_file (aafi, audioEssence->original_file_path, aafi->ctx.options.media_location);
|
||||
audioEssence->type = AAFI_ESSENCE_TYPE_UNK;
|
||||
|
||||
if (externalFilePath == NULL) {
|
||||
error ("Could not locate external audio essence file '%ls'", audioEssence->original_file_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
audioEssence->usable_file_path = malloc ((strlen (externalFilePath) + 1) * sizeof (wchar_t));
|
||||
|
||||
if (audioEssence->usable_file_path == NULL) {
|
||||
error ("Could not allocate memory : %s", strerror (errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = swprintf (audioEssence->usable_file_path, strlen (externalFilePath) + 1, L"%" WPRIs, externalFilePath);
|
||||
|
||||
if (rc < 0) {
|
||||
error ("Failed setting usable_file_path");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (laaf_util_fop_is_wstr_fileext (audioEssence->original_file_path, L"wav") ||
|
||||
laaf_util_fop_is_wstr_fileext (audioEssence->original_file_path, L"wave") ||
|
||||
laaf_util_fop_is_wstr_fileext (audioEssence->original_file_path, L"aif") ||
|
||||
laaf_util_fop_is_wstr_fileext (audioEssence->original_file_path, L"aiff") ||
|
||||
laaf_util_fop_is_wstr_fileext (audioEssence->original_file_path, L"aifc")) {
|
||||
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, RIFF_PARSE_ONLY_HEADER, &externalAudioDataReaderCallback, fp, externalFilePath, aafi, aafi->dbg);
|
||||
|
||||
if (rc < 0) {
|
||||
error ("Failed parsing external audio essence file : %s", externalFilePath);
|
||||
goto err;
|
||||
}
|
||||
|
||||
audioEssence->channels = RIFFAudioFile.channels;
|
||||
audioEssence->samplerate = RIFFAudioFile.sampleRate;
|
||||
audioEssence->samplesize = RIFFAudioFile.sampleSize;
|
||||
audioEssence->length = RIFFAudioFile.duration;
|
||||
}
|
||||
// /* clears any wrong data previously retrieved out of AAFClassID_PCMDescriptor */
|
||||
// audioEssence->samplerate = 0;
|
||||
// audioEssence->samplesize = 0;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
@ -586,12 +610,12 @@ embeddedAudioDataReaderCallback (unsigned char* buf, size_t offset, size_t reqLe
|
||||
size_t datasz = *(size_t*)user2;
|
||||
AAF_Iface* aafi = (AAF_Iface*)user3;
|
||||
|
||||
if (offset >= datasz) {
|
||||
if (offset > datasz) {
|
||||
error ("Requested data starts beyond data length");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + reqLen >= datasz) {
|
||||
if (offset + reqLen > datasz) {
|
||||
reqLen = datasz - (offset + reqLen);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,47 +75,37 @@ aafi_alloc (AAF_Data* aafd)
|
||||
aafi->dbg = laaf_new_debug ();
|
||||
|
||||
if (aafi->dbg == NULL) {
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
aafi->Audio = calloc (sizeof (aafiAudio), sizeof (unsigned char));
|
||||
|
||||
if (aafi->Audio == NULL) {
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
aafi->Audio->Essences = NULL;
|
||||
aafi->Audio->samplerate = 0;
|
||||
aafi->Audio->samplesize = 0;
|
||||
aafi->Audio->Tracks = NULL;
|
||||
aafi->Audio->track_count = 0;
|
||||
aafi->Audio->length = 0;
|
||||
|
||||
aafi->Video = calloc (sizeof (aafiVideo), sizeof (unsigned char));
|
||||
|
||||
if (aafi->Video == NULL) {
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
aafi->Video->Essences = NULL;
|
||||
aafi->Video->Tracks = NULL;
|
||||
aafi->Video->length = 0;
|
||||
|
||||
if (aafd != NULL) {
|
||||
aafi->aafd = aafd;
|
||||
} else {
|
||||
aafi->aafd = aaf_alloc (aafi->dbg);
|
||||
|
||||
if (aafi->aafd == NULL) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
aafi->Markers = NULL;
|
||||
|
||||
aafi->compositionName = NULL;
|
||||
|
||||
aafi->ctx.is_inside_derivation_chain = 0;
|
||||
aafi->ctx.options.forbid_nonlatin_filenames = 0;
|
||||
aafi->ctx.options.trace = 0;
|
||||
|
||||
return aafi;
|
||||
|
||||
err:
|
||||
aafi_release (&aafi);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@ -174,17 +164,16 @@ aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val)
|
||||
aafi->ctx.options.dump_class_aaf_properties = NULL;
|
||||
}
|
||||
|
||||
if (val == NULL)
|
||||
if (val == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aafi->ctx.options.dump_class_aaf_properties = malloc ((strlen (val) + 1) * sizeof (wchar_t));
|
||||
aafi->ctx.options.dump_class_aaf_properties = laaf_util_str2wstr (val);
|
||||
|
||||
if (aafi->ctx.options.dump_class_aaf_properties == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
swprintf (aafi->ctx.options.dump_class_aaf_properties, strlen (val) + 1, L"%" WPRIs, val);
|
||||
|
||||
return 0;
|
||||
} else if (strcmp (optname, "dump_class_raw_properties") == 0) {
|
||||
if (aafi->ctx.options.dump_class_raw_properties) {
|
||||
@ -192,17 +181,16 @@ aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val)
|
||||
aafi->ctx.options.dump_class_raw_properties = NULL;
|
||||
}
|
||||
|
||||
if (val == NULL)
|
||||
if (val == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aafi->ctx.options.dump_class_raw_properties = malloc ((strlen (val) + 1) * sizeof (wchar_t));
|
||||
aafi->ctx.options.dump_class_raw_properties = laaf_util_str2wstr (val);
|
||||
|
||||
if (aafi->ctx.options.dump_class_raw_properties == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
swprintf (aafi->ctx.options.dump_class_raw_properties, strlen (val) + 1, L"%" WPRIs, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -212,8 +200,9 @@ aafi_set_option_str (AAF_Iface* aafi, const char* optname, const char* val)
|
||||
void
|
||||
aafi_release (AAF_Iface** aafi)
|
||||
{
|
||||
if (*aafi == NULL)
|
||||
if (*aafi == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
aaf_release (&(*aafi)->aafd);
|
||||
|
||||
@ -541,6 +530,20 @@ aafi_freeAudioClip (aafiAudioClip* audioClip)
|
||||
if (audioClip->automation != NULL) {
|
||||
aafi_freeAudioGain (audioClip->automation);
|
||||
}
|
||||
|
||||
aafi_freeAudioEssencePointer (audioClip->essencePointerList);
|
||||
}
|
||||
|
||||
void
|
||||
aafi_freeAudioEssencePointer (aafiAudioEssencePointer* essencePointer)
|
||||
{
|
||||
aafiAudioEssencePointer* next = NULL;
|
||||
|
||||
while (essencePointer) {
|
||||
next = essencePointer->next;
|
||||
free (essencePointer);
|
||||
essencePointer = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -649,12 +652,9 @@ aafi_newAudioTrack (AAF_Iface* aafi)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
track->Audio = aafi->Audio;
|
||||
track->format = AAFI_TRACK_FORMAT_NOT_SET;
|
||||
track->pan = NULL;
|
||||
track->gain = NULL;
|
||||
track->current_pos = 0;
|
||||
track->next = NULL;
|
||||
track->Audio = aafi->Audio;
|
||||
track->format = AAFI_TRACK_FORMAT_NOT_SET;
|
||||
track->next = NULL;
|
||||
|
||||
/* Add to track list */
|
||||
|
||||
@ -718,9 +718,8 @@ aafi_newVideoTrack (AAF_Iface* aafi)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
track->Video = aafi->Video;
|
||||
track->current_pos = 0;
|
||||
track->next = NULL;
|
||||
track->Video = aafi->Video;
|
||||
track->next = NULL;
|
||||
|
||||
/* Add to track list */
|
||||
|
||||
@ -776,20 +775,52 @@ aafi_newAudioEssence (AAF_Iface* aafi)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audioEssence->next = aafi->Audio->Essences;
|
||||
audioEssence->samplerateRational = malloc (sizeof (aafRational_t));
|
||||
|
||||
audioEssence->original_file_path = NULL;
|
||||
audioEssence->usable_file_path = NULL;
|
||||
audioEssence->file_name = NULL;
|
||||
audioEssence->unique_file_name = NULL;
|
||||
audioEssence->clip_count = 0;
|
||||
audioEssence->user = NULL;
|
||||
if (audioEssence->samplerateRational == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audioEssence->samplerateRational->numerator = 1;
|
||||
audioEssence->samplerateRational->denominator = 1;
|
||||
|
||||
audioEssence->next = aafi->Audio->Essences;
|
||||
|
||||
aafi->Audio->Essences = audioEssence;
|
||||
|
||||
return audioEssence;
|
||||
}
|
||||
|
||||
aafiAudioEssencePointer*
|
||||
aafi_newAudioEssencePointer (AAF_Iface* aafi, aafiAudioEssencePointer** list, aafiAudioEssence* audioEssence, uint32_t* essenceChannelNum)
|
||||
{
|
||||
aafiAudioEssencePointer* essencePointer = calloc (sizeof (aafiAudioEssencePointer), sizeof (char));
|
||||
|
||||
if (essencePointer == NULL) {
|
||||
error ("%s.", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
essencePointer->aafi = aafi;
|
||||
essencePointer->essence = audioEssence;
|
||||
essencePointer->essenceChannel = (essenceChannelNum) ? *essenceChannelNum : 0;
|
||||
|
||||
if (*list) {
|
||||
aafiAudioEssencePointer* last = *list;
|
||||
while (last->next != NULL) {
|
||||
last = last->next;
|
||||
}
|
||||
last->next = essencePointer;
|
||||
} else {
|
||||
*list = essencePointer;
|
||||
|
||||
essencePointer->aafiNext = aafi->Audio->essencePointerList;
|
||||
aafi->Audio->essencePointerList = essencePointer;
|
||||
}
|
||||
|
||||
return *list;
|
||||
}
|
||||
|
||||
void
|
||||
aafi_freeAudioEssences (aafiAudioEssence** audioEssence)
|
||||
{
|
||||
@ -818,6 +849,10 @@ aafi_freeAudioEssences (aafiAudioEssence** audioEssence)
|
||||
free ((*audioEssence)->unique_file_name);
|
||||
}
|
||||
|
||||
if ((*audioEssence)->samplerateRational != NULL) {
|
||||
free ((*audioEssence)->samplerateRational);
|
||||
}
|
||||
|
||||
free (*audioEssence);
|
||||
}
|
||||
|
||||
@ -836,11 +871,6 @@ aafi_newVideoEssence (AAF_Iface* aafi)
|
||||
|
||||
videoEssence->next = aafi->Video->Essences;
|
||||
|
||||
videoEssence->original_file_path = NULL;
|
||||
videoEssence->usable_file_path = NULL;
|
||||
videoEssence->file_name = NULL;
|
||||
videoEssence->unique_file_name = NULL;
|
||||
|
||||
aafi->Video->Essences = videoEssence;
|
||||
|
||||
return videoEssence;
|
||||
@ -880,6 +910,35 @@ aafi_freeVideoEssences (aafiVideoEssence** videoEssence)
|
||||
*videoEssence = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
aafi_getAudioEssencePointerChannelCount (aafiAudioEssencePointer* essencePointerList)
|
||||
{
|
||||
/*
|
||||
* 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++;
|
||||
}
|
||||
|
||||
return (essencePointerCount > 1) ? essencePointerCount : (essencePointerList->essenceChannel) ? 1
|
||||
: essencePointerList->essence->channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -177,7 +177,7 @@ replace_clipfade_with_fade (AAF_Iface* aafi, aafiTimelineItem* Item)
|
||||
if (Item->next->type == AAFI_AUDIO_CLIP) {
|
||||
nextClip = (aafiAudioClip*)Item->next->data;
|
||||
|
||||
if (is_sample_accurate_edit (nextClip->Essence->file_name)) {
|
||||
if (is_sample_accurate_edit (nextClip->essencePointerList->essence->file_name)) {
|
||||
if (Item->next->next != NULL) {
|
||||
nextClip = (aafiAudioClip*)Item->next->next->data;
|
||||
|
||||
@ -281,7 +281,7 @@ protools_post_processing (AAF_Iface* aafi /*, enum protools_options flags*/)
|
||||
|
||||
aafiAudioClip* audioClip = (aafiAudioClip*)audioItem->data;
|
||||
|
||||
wchar_t* clipName = audioClip->Essence->file_name;
|
||||
wchar_t* clipName = audioClip->essencePointerList->essence->file_name;
|
||||
|
||||
if ((aafi->ctx.options.protools & PROTOOLS_REPLACE_CLIP_FADES) && is_rendered_fade (clipName)) {
|
||||
replace_clipfade_with_fade (aafi, audioItem);
|
||||
|
@ -124,7 +124,7 @@ 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)) {
|
||||
error ("Could not read file");
|
||||
error ("Could not read file header");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -152,8 +152,6 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS
|
||||
return -1;
|
||||
}
|
||||
|
||||
// debug( "%.4s %.4s (%u bytes)", riff.ckid, riff.format, riff.cksz );
|
||||
|
||||
size_t filesize = riff.cksz + sizeof (chunk);
|
||||
size_t pos = sizeof (struct riffHeaderChunk);
|
||||
|
||||
@ -161,7 +159,7 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS
|
||||
bytesRead = readerCallback ((unsigned char*)&chunk, pos, sizeof (chunk), user1, user2, user3);
|
||||
|
||||
if (bytesRead < sizeof (chunk)) {
|
||||
error ("Could not read chunk @ %" PRIu64 " (%" PRIu64 " bytes returned)", pos, bytesRead);
|
||||
error ("Could not read chunk \"%.4s\" @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, pos, bytesRead);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -169,7 +167,7 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS
|
||||
chunk.cksz = BE2LE32 (chunk.cksz);
|
||||
}
|
||||
|
||||
// debug( "Got chunk : %.4s (%u bytes)", chunk.ckid, chunk.cksz );
|
||||
debug ("Got chunk \"%.4s\" (%u bytes) @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, chunk.cksz, pos, bytesRead);
|
||||
|
||||
if (!be) { /* WAVE */
|
||||
|
||||
@ -181,6 +179,11 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS
|
||||
|
||||
bytesRead = readerCallback ((unsigned char*)&wavFmtChunk, pos, sizeof (wavFmtChunk), user1, user2, user3);
|
||||
|
||||
if (bytesRead < sizeof (wavFmtChunk)) {
|
||||
error ("Could not read chunk \"%.4s\" content @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, pos, bytesRead);
|
||||
break;
|
||||
}
|
||||
|
||||
RIFFAudioFile->channels = wavFmtChunk.channels;
|
||||
RIFFAudioFile->sampleSize = wavFmtChunk.bits_per_sample;
|
||||
RIFFAudioFile->sampleRate = wavFmtChunk.samples_per_sec;
|
||||
@ -193,7 +196,11 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS
|
||||
chunk.ckid[2] == 't' &&
|
||||
chunk.ckid[3] == 'a') {
|
||||
if (RIFFAudioFile->channels > 0 && RIFFAudioFile->sampleSize > 0) {
|
||||
RIFFAudioFile->duration = chunk.cksz / RIFFAudioFile->channels / (RIFFAudioFile->sampleSize / 8);
|
||||
RIFFAudioFile->sampleCount = chunk.cksz / RIFFAudioFile->channels / (RIFFAudioFile->sampleSize / 8);
|
||||
}
|
||||
|
||||
if (flags & RIFF_PARSE_AAF_SUMMARY) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else { /* AIFF */
|
||||
@ -206,29 +213,40 @@ riff_parseAudioFile (struct RIFFAudioFile* RIFFAudioFile, enum RIFF_PARSER_FLAGS
|
||||
|
||||
bytesRead = readerCallback ((unsigned char*)&aiffCOMMChunk, pos, sizeof (aiffCOMMChunk), user1, user2, user3);
|
||||
|
||||
RIFFAudioFile->channels = BE2LE16 (aiffCOMMChunk.numChannels);
|
||||
RIFFAudioFile->sampleSize = BE2LE16 (aiffCOMMChunk.sampleSize);
|
||||
RIFFAudioFile->sampleRate = beExtended2leUint32 (aiffCOMMChunk.sampleRate);
|
||||
RIFFAudioFile->duration = BE2LE32 (aiffCOMMChunk.numSampleFrames);
|
||||
if (bytesRead < sizeof (aiffCOMMChunk)) {
|
||||
error ("Could not read chunk \"%.4s\" content @ %" PRIu64 " (%" PRIu64 " bytes returned)", chunk.ckid, pos, bytesRead);
|
||||
break;
|
||||
}
|
||||
|
||||
RIFFAudioFile->channels = BE2LE16 (aiffCOMMChunk.numChannels);
|
||||
RIFFAudioFile->sampleSize = BE2LE16 (aiffCOMMChunk.sampleSize);
|
||||
RIFFAudioFile->sampleRate = beExtended2leUint32 (aiffCOMMChunk.sampleRate);
|
||||
RIFFAudioFile->sampleCount = BE2LE32 (aiffCOMMChunk.numSampleFrames);
|
||||
|
||||
if (flags & RIFF_PARSE_ONLY_HEADER) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We don't care about AIFF "SSND" chunk because we already know duration
|
||||
* from "COMM". Could we double check validity of duration by checking
|
||||
* "SSND" chunk size, like we do with WAV "DATA" chunk ? is it possible
|
||||
* with AAF audio file summary ?
|
||||
*/
|
||||
} else if (chunk.ckid[0] == 'S' &&
|
||||
chunk.ckid[1] == 'S' &&
|
||||
chunk.ckid[2] == 'N' &&
|
||||
chunk.ckid[3] == 'D') {
|
||||
/*
|
||||
* Samplecount should be already set with numSampleFrames in COMM chunk.
|
||||
* However in AAF (AIFCDescriptor::Summary), numSampleFrames is often null,
|
||||
* so we must extract samplecount out of SSND chunk, like we do with wav DATA chunk.
|
||||
*/
|
||||
uint64_t sampleCount = chunk.cksz / RIFFAudioFile->channels / (RIFFAudioFile->sampleSize / 8);
|
||||
|
||||
// else
|
||||
// if ( chunk.ckid[0] == 'S' &&
|
||||
// chunk.ckid[1] == 'S' &&
|
||||
// chunk.ckid[2] == 'N' &&
|
||||
// chunk.ckid[3] == 'D' )
|
||||
// {
|
||||
// }
|
||||
if (RIFFAudioFile->sampleCount > 0 && RIFFAudioFile->sampleCount != sampleCount) {
|
||||
debug ("Sample count retrieved from COMM chunk (%" PRIu64 ") does not match SSND chunk (%" PRIu64 ")", RIFFAudioFile->sampleCount, sampleCount);
|
||||
}
|
||||
|
||||
RIFFAudioFile->sampleCount = sampleCount;
|
||||
|
||||
if (flags & RIFF_PARSE_AAF_SUMMARY) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += chunk.cksz + sizeof (chunk);
|
||||
|
@ -25,13 +25,13 @@
|
||||
|
||||
#include "aaf/AAFIface.h"
|
||||
|
||||
char*
|
||||
wchar_t*
|
||||
aafi_locate_external_essence_file (AAF_Iface* aafi, const wchar_t* original_file_path, const char* search_location);
|
||||
|
||||
int
|
||||
aafi_extract_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence, const char* outfilepath, const wchar_t* forcedFileName);
|
||||
|
||||
int
|
||||
aafi_parse_audio_summary (AAF_Iface* aafi, aafiAudioEssence* audioEssence);
|
||||
aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssence* audioEssence);
|
||||
|
||||
#endif // !__AAFIAudioFiles_h__
|
||||
|
@ -42,6 +42,7 @@ enum aafiEssenceType {
|
||||
AAFI_ESSENCE_TYPE_WAVE = 0x02,
|
||||
AAFI_ESSENCE_TYPE_AIFC = 0x03,
|
||||
AAFI_ESSENCE_TYPE_BWAV = 0x04,
|
||||
AAFI_ESSENCE_TYPE_UNK = 0xff, /* non-pcm */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -234,15 +235,20 @@ typedef struct aafiAudioGain {
|
||||
typedef struct aafiAudioGain aafiAudioPan;
|
||||
|
||||
typedef struct aafiAudioEssence {
|
||||
wchar_t* original_file_path; // NetworkLocator::URLString the original URI hold in AAF
|
||||
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.
|
||||
|
||||
uint16_t clip_count; // number of clips with this essence
|
||||
uint16_t clip_count; // number of clips using this essence
|
||||
|
||||
/* total samples for 1 channel (no matter channel count). (duration / sampleRate) = duration in seconds */
|
||||
uint64_t length; // Length of Essence Data
|
||||
/*
|
||||
* 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)
|
||||
*/
|
||||
uint64_t length;
|
||||
|
||||
cfbNode* node; // The node holding the audio stream if embedded
|
||||
|
||||
@ -255,14 +261,18 @@ typedef struct aafiAudioEssence {
|
||||
|
||||
enum aafiEssenceType type; // depends on PCMDescriptor WAVEDescriptor AIFCDescriptor
|
||||
|
||||
/*
|
||||
* is only set if FileSourceMob contains EssenceData
|
||||
*/
|
||||
uint8_t is_embedded;
|
||||
|
||||
aafProperty* summary; // WAVEDescriptor AIFCDescriptor
|
||||
|
||||
// uint32_t format;
|
||||
uint32_t samplerate;
|
||||
int16_t samplesize;
|
||||
int16_t channels;
|
||||
uint32_t samplerate;
|
||||
aafRational_t* samplerateRational; // eg. { 48000, 1 }
|
||||
int16_t samplesize;
|
||||
int16_t channels;
|
||||
|
||||
aafRational_t* mobSlotEditRate;
|
||||
|
||||
@ -277,10 +287,22 @@ typedef struct aafiAudioEssence {
|
||||
|
||||
void* user;
|
||||
// TODO peakEnveloppe
|
||||
struct aafiAudioEssence* next;
|
||||
|
||||
struct aafiAudioEssence* next; // aafi->Audio->essences
|
||||
} aafiAudioEssence;
|
||||
|
||||
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.
|
||||
|
||||
void* user;
|
||||
|
||||
struct aafiAudioEssencePointer* next; // audioClip->essenceGroup
|
||||
struct aafiAudioEssencePointer* aafiNext; // aafi->Audio->essenceGroup
|
||||
|
||||
struct AAF_Iface* aafi;
|
||||
|
||||
} 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.
|
||||
@ -318,8 +340,8 @@ struct aafiVideoTrack;
|
||||
typedef struct aafiAudioClip {
|
||||
struct aafiAudioTrack* track;
|
||||
|
||||
aafiAudioEssence* Essence;
|
||||
|
||||
int channels; // channel count of clip (might be different of essence->channels)
|
||||
aafiAudioEssencePointer* essencePointerList;
|
||||
/*
|
||||
* Some editors (like Resolve) support automation attached to a clip AND a fixed value clip gain
|
||||
*/
|
||||
@ -338,22 +360,26 @@ typedef struct aafiAudioClip {
|
||||
* Start position in source file, set from SourceClip::StartTime
|
||||
*
|
||||
* « Specifies the offset from the origin of the referenced Mob MobSlot in edit units
|
||||
* determined by the SourceClip object’s context.
|
||||
* determined by the SourceClip object’s context. »
|
||||
*
|
||||
* A SourceClip’s StartTime and Length values are in edit units determined by the slot
|
||||
* owning the SourceClip.
|
||||
* « A SourceClip’s StartTime and Length values are in edit units determined by the slot
|
||||
* owning the SourceClip. »
|
||||
|
||||
* Informative note: If the SourceClip references a MobSlot that specifies a different
|
||||
* « Informative note: If the SourceClip references a MobSlot that specifies a different
|
||||
* edit rate than the MobSlot owning the SourceClip, the StartTime and Length are in
|
||||
* edit units of the slot owning the SourceClip, and not edit units of the referenced slot.»
|
||||
*/
|
||||
|
||||
aafPosition_t essence_offset; /* in edit unit, edit rate definition is aafiAudioTrack->edit_rate */
|
||||
/*
|
||||
* set with CompoMob's SourceClip::StartTime. In the case of an OperationGroup(AudioChannelCombiner),
|
||||
* There is one SourceClip per audio channel. So even though it's very unlikely, there could possibly
|
||||
* be one essence_offset per channel.
|
||||
* Value is in edit unit, edit rate definition is aafiAudioTrack->edit_rate
|
||||
*/
|
||||
aafPosition_t essence_offset;
|
||||
|
||||
struct aafiTimelineItem* Item; // Corresponding timeline item, currently used in ardour to retrieve fades/x-fades
|
||||
|
||||
aafMobID_t* masterMobID; // MobID of the associated MasterMob (PID_SourceReference_SourceID)
|
||||
|
||||
} aafiAudioClip;
|
||||
|
||||
typedef struct aafiVideoClip {
|
||||
@ -403,12 +429,6 @@ typedef struct aafiTimecode {
|
||||
|
||||
aafPosition_t start;
|
||||
|
||||
/**
|
||||
* Timecode end in EditUnit. (session end)
|
||||
*/
|
||||
|
||||
aafPosition_t end;
|
||||
|
||||
/**
|
||||
* Frame per second.
|
||||
*/
|
||||
@ -561,17 +581,17 @@ typedef struct aafiAudio {
|
||||
*/
|
||||
|
||||
aafPosition_t start;
|
||||
aafPosition_t length;
|
||||
aafRational_t length_editRate;
|
||||
|
||||
int64_t samplerate;
|
||||
int16_t samplesize;
|
||||
int16_t samplesize;
|
||||
int64_t samplerate;
|
||||
aafRational_t* samplerateRational; // eg. { 48000, 1 }
|
||||
|
||||
/**
|
||||
* Holds the Essence list.
|
||||
*/
|
||||
|
||||
aafiAudioEssence* Essences;
|
||||
aafiAudioEssence* Essences;
|
||||
aafiAudioEssencePointer* essencePointerList;
|
||||
|
||||
/**
|
||||
* Holds the Track list.
|
||||
@ -588,8 +608,6 @@ typedef struct aafiVideo {
|
||||
*/
|
||||
|
||||
aafPosition_t start;
|
||||
aafPosition_t length;
|
||||
aafRational_t length_editRate;
|
||||
|
||||
/**
|
||||
* Holds the Essence list.
|
||||
@ -654,10 +672,10 @@ typedef struct aafiContext {
|
||||
aafiVideoClip* current_video_clip;
|
||||
int current_clip_is_muted;
|
||||
|
||||
int current_clip_is_combined; // Inside OperationGroup::AAFOperationDef_AudioChannelCombiner
|
||||
int current_combined_clip_total_channel;
|
||||
int current_combined_clip_channel_num; // current SourceClip represents channel num
|
||||
|
||||
int current_clip_is_combined; // Inside OperationGroup::AAFOperationDef_AudioChannelCombiner
|
||||
int 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;
|
||||
@ -713,11 +731,11 @@ typedef struct AAF_Iface {
|
||||
|
||||
wchar_t* compositionName;
|
||||
|
||||
aafPosition_t compositionStart; // set from aafi->Timecode->start
|
||||
aafRational_t compositionStart_editRate;
|
||||
aafPosition_t compositionStart; // sets from aafi->Timecode->start
|
||||
aafRational_t* compositionStart_editRate;
|
||||
|
||||
aafPosition_t compositionLength;
|
||||
aafRational_t compositionLength_editRate;
|
||||
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;
|
||||
|
||||
@ -740,30 +758,18 @@ typedef struct AAF_Iface {
|
||||
item != NULL; \
|
||||
item = item->next)
|
||||
|
||||
#define AAFI_foreachAudioEssencePointerInFile(essencePointer, aafi) \
|
||||
for (essencePointer = aafi->Audio->essencePointerList; essencePointer != NULL; essencePointer = essencePointer->aafiNext)
|
||||
|
||||
#define AAFI_foreachAudioEssencePointer(essencePointer, essencePtrList) \
|
||||
for (essencePointer = essencePtrList; essencePointer != NULL; essencePointer = essencePointer->next)
|
||||
|
||||
#define foreachEssence(essence, essenceList) \
|
||||
for (essence = essenceList; essence != NULL; essence = essence->next)
|
||||
|
||||
#define foreachMarker(marker, aafi) \
|
||||
for (marker = aafi->Markers; marker != NULL; marker = marker->next)
|
||||
|
||||
#define aeDuration_h(audioEssence) \
|
||||
((audioEssence->samplerate == 0) ? 0 : ((uint16_t) (audioEssence->length / audioEssence->samplerate / (audioEssence->samplesize / 8)) / 3600))
|
||||
|
||||
#define aeDuration_m(audioEssence) \
|
||||
((audioEssence->samplerate == 0) ? 0 : ((uint16_t) (audioEssence->length / audioEssence->samplerate / (audioEssence->samplesize / 8)) % 3600 / 60))
|
||||
|
||||
#define aeDuration_s(audioEssence) \
|
||||
((audioEssence->samplerate == 0) ? 0 : ((uint16_t) (audioEssence->length / audioEssence->samplerate / (audioEssence->samplesize / 8)) % 3600 % 60))
|
||||
|
||||
#define aeDuration_ms(audioEssence) \
|
||||
((audioEssence->samplerate == 0) ? 0 : ((uint16_t) (audioEssence->length / (audioEssence->samplerate / 1000) / (audioEssence->samplesize / 8)) % 3600000 % 60000 % 1000))
|
||||
|
||||
#define convertEditUnit(val, fromRate, toRate) \
|
||||
(int64_t) ((val) * (aafRationalToFloat ((toRate)) * (1 / aafRationalToFloat ((fromRate)))))
|
||||
|
||||
#define eu2sample(samplerate, edit_rate, val) \
|
||||
(int64_t) (val * (samplerate * (1 / aafRationalToFloat ((*edit_rate)))))
|
||||
|
||||
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);
|
||||
|
||||
@ -823,6 +829,9 @@ aafi_freeAudioPan (aafiAudioPan* pan);
|
||||
void
|
||||
aafi_freeAudioClip (aafiAudioClip* audioClip);
|
||||
|
||||
void
|
||||
aafi_freeAudioEssencePointer (aafiAudioEssencePointer* audioEssenceGroupEntry);
|
||||
|
||||
void
|
||||
aafi_freeTimelineItem (aafiTimelineItem** item);
|
||||
|
||||
@ -841,6 +850,9 @@ 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);
|
||||
|
||||
@ -850,6 +862,9 @@ aafi_newVideoEssence (AAF_Iface* aafi);
|
||||
void
|
||||
aafi_freeVideoEssences (aafiVideoEssence** videoEssence);
|
||||
|
||||
int
|
||||
aafi_getAudioEssencePointerChannelCount (aafiAudioEssencePointer* essencePointerList);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
enum RIFF_PARSER_FLAGS {
|
||||
RIFF_PARSE_ONLY_HEADER = (1 << 0),
|
||||
RIFF_PARSE_AAF_SUMMARY = (1 << 1),
|
||||
};
|
||||
|
||||
struct RIFFAudioFile {
|
||||
@ -40,7 +41,7 @@ struct RIFFAudioFile {
|
||||
uint32_t sampleRate;
|
||||
uint16_t sampleSize;
|
||||
uint16_t channels;
|
||||
uint64_t duration; /* total samples for 1 channel (no matter channel count). (duration / sampleRate) = duration in seconds */
|
||||
uint64_t sampleCount; /* total samples for 1 channel (no matter channel count). (sampleCount / sampleRate) = duration in seconds */
|
||||
};
|
||||
|
||||
PACK (struct riffHeaderChunk {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#ifndef __utils_h__
|
||||
#define __utils_h__
|
||||
|
||||
#include "aaf/AAFTypes.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -35,9 +36,13 @@ extern "C" {
|
||||
* 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 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 "/"
|
||||
/*
|
||||
@ -62,6 +67,15 @@ extern "C" {
|
||||
#define ANSI_COLOR_BOLD(dbg) (((dbg)->ansicolor) ? "\x1b[1m" : "")
|
||||
#define ANSI_COLOR_RESET(dbg) (((dbg)->ansicolor) ? "\x1b[0m" : "")
|
||||
|
||||
aafPosition_t
|
||||
laaf_util_converUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate);
|
||||
|
||||
char*
|
||||
laaf_util_wstr2str (const wchar_t* wstr);
|
||||
|
||||
wchar_t*
|
||||
laaf_util_str2wstr (const char* str);
|
||||
|
||||
int
|
||||
laaf_util_wstr_contains_nonlatin (const wchar_t* str);
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#define LIBAAF_VERSION "v0.5-2-g4dfb754"
|
||||
#define LIBAAF_VERSION "v0.6-45-g9171e40"
|
||||
|
@ -29,6 +29,81 @@
|
||||
|
||||
#define BUILD_PATH_DEFAULT_BUF_SIZE 1024
|
||||
|
||||
aafPosition_t
|
||||
laaf_util_converUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate)
|
||||
{
|
||||
if (!valueEditRate || !destEditRate) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (valueEditRate->numerator == destEditRate->numerator &&
|
||||
valueEditRate->denominator == destEditRate->denominator) {
|
||||
/* same rate, no conversion */
|
||||
return value;
|
||||
}
|
||||
|
||||
double valueEditRateFloat = ((valueEditRate->denominator == 0) ? 0.0 : ((float)valueEditRate->numerator / valueEditRate->denominator));
|
||||
double destEditRateFloat = ((destEditRate->denominator == 0) ? 0.0 : ((float)destEditRate->numerator / destEditRate->denominator));
|
||||
|
||||
if (valueEditRateFloat == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value * (destEditRateFloat / valueEditRateFloat);
|
||||
}
|
||||
|
||||
char*
|
||||
laaf_util_wstr2str (const wchar_t* wstr)
|
||||
{
|
||||
if (wstr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strsz = wcslen (wstr) + 1;
|
||||
char* str = malloc (strsz);
|
||||
|
||||
if (str == NULL) {
|
||||
// error( "Could not allocate memory : %s", strerror(errno) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rc = snprintf (str, strsz, "%ls", wstr);
|
||||
|
||||
if (rc < 0 || (unsigned)rc >= strsz) {
|
||||
// error( "Failed converting wide char str to byte char str%s", (reqlen < 0) ? " : encoding error" : "" );
|
||||
free (str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ def options(opt):
|
||||
|
||||
def configure(conf):
|
||||
if conf.is_defined('USE_EXTERNAL_LIBS'):
|
||||
autowaf.check_pkg(conf, 'libaaf', uselib_store='LIBAAF', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'libaaf', uselib_store='LIBAAF', mandatory=True, atleast_version='0.6.0')
|
||||
|
||||
def build(bld):
|
||||
if bld.is_defined('USE_EXTERNAL_LIBS'):
|
||||
|
Loading…
Reference in New Issue
Block a user