Update libaaf to v1.0-22-gfab4651

This commit is contained in:
agfline 2024-12-23 12:03:14 +01:00 committed by Robin Gareus
parent 0054078289
commit ae18524da7
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
10 changed files with 346 additions and 156 deletions

View file

@ -117,7 +117,7 @@ aafi_build_unique_audio_essence_name (AAF_Iface* aafi, aafiAudioEssenceFile* aud
}
char*
aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_filepath, const char* search_location)
aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_filepath, const char* commonPathPart, const char* search_location)
{
/*
* Absolute Uniform Resource Locator (URL) complying with RFC 1738 or relative
@ -131,17 +131,18 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_fil
char* local_filepath = NULL;
char* aaf_path = NULL;
const char* foundpath = NULL;
char* retpath = NULL;
const char* foundpath = NULL;
struct uri* uri = NULL;
struct uri* commonPathPartURI = NULL;
if (original_uri_filepath == NULL) {
error ("Cant locate a NULL filepath");
goto err;
}
debug ("Original URI : %s", original_uri_filepath);
debug ("Encoded file URI : %s", original_uri_filepath);
uri = laaf_uri_parse (original_uri_filepath, URI_OPT_DECODE_ALL, aafi->log);
@ -155,54 +156,95 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_fil
goto err;
}
debug ("Decoded URI's path : %s", uri->path);
debug ("Decoded file URI : %s", uri->path);
/* extract relative path to essence file : "<firstparent>/<essence.file>" */
const char* local_path = NULL;
const char* relativeEssencePath = NULL;
const char* essenceFileName = NULL;
if (search_location) {
local_path = search_location;
} else {
/* extract local 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;
}
char* p = aaf_path + strlen (aaf_path);
while (p > aaf_path) {
if (IS_DIR_SEP (*p)) {
*p = 0x00;
break;
}
p--;
}
local_path = aaf_path;
}
if (commonPathPart && *commonPathPart != 0x00) {
/*
* commonPathPart stores the first part of the filepath URI, which is common
* to all essence file.
*
* file:///localhost/C:/data/path/media/essence_a.wav
* file:///localhost/C:/data/path/media/essence_b.wav
* file:///localhost/C:/data/path/media/subdir/essence_c.wav
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
debug ("Encoded commonPathPartURI : %s", commonPathPart);
commonPathPartURI = laaf_uri_parse (commonPathPart, URI_OPT_DECODE_ALL, aafi->log);
if (commonPathPartURI == NULL) {
error ("Could not parse commonPathPartURI");
goto err;
}
if (commonPathPartURI->path == NULL) {
error ("Could not retrieve <path> out of commonPathPartURI");
goto err;
}
debug ("Decoded commonPathPartURI : %s", commonPathPartURI->path);
/*
* Most of the time, the last common directory in path will be the top
* directory for essence media so we want to try it.
*
* file:///localhost/C:/data/path/media/essence_a.wav
* file:///localhost/C:/data/path/media/essence_b.wav
* file:///localhost/C:/data/path/media/subdir/essence_c.wav
* ^^^^^^^
*/
const char* relativeEssencePathWCommonDir = NULL;
int sepcount = 0;
char* p = uri->path + strlen (uri->path);
char* p = commonPathPartURI->path + strlen (commonPathPartURI->path);
while (p > uri->path) {
while (p > commonPathPartURI->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);
if (sepcount == 2) {
relativeEssencePathWCommonDir = uri->path + (p - commonPathPartURI->path);
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) {
/*
* "<search_location>/<essence.file>"
*/
local_filepath = laaf_util_build_path ("/", search_location, essenceFileName, NULL);
local_filepath = laaf_util_build_path (DIR_SEP_STR, local_path, relativeEssencePathWCommonDir, NULL);
if (!local_filepath) {
error ("Could not build search filepath");
error ("Could not build filepath");
goto err;
}
debug ("Search filepath : %s", local_filepath);
debug ("Trying relativeEssencePathWCommonDir : %s", local_filepath);
if (laaf_util_file_exists (local_filepath) == 1) {
foundpath = local_filepath;
@ -213,17 +255,19 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_fil
local_filepath = NULL;
/*
* "<search_location>/<firstparentInOriginalEssencePath>/<essence.file>"
* Try without the last common directory.
*/
local_filepath = laaf_util_build_path ("/", search_location, relativeEssencePath, NULL);
const char* relativeEssencePathWoCommonDir = uri->path + strlen (commonPathPartURI->path);
local_filepath = laaf_util_build_path (DIR_SEP_STR, local_path, relativeEssencePathWoCommonDir, NULL);
if (!local_filepath) {
error ("Could not build search filepath");
error ("Could not build filepath");
goto err;
}
debug ("Search filepath : %s", local_filepath);
debug ("Trying relativeEssencePathWoCommonDir : %s", local_filepath);
if (laaf_util_file_exists (local_filepath) == 1) {
foundpath = local_filepath;
@ -232,6 +276,42 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_fil
free (local_filepath);
local_filepath = NULL;
} else {
/*
* If no commonPathPart was provided (eg. if AAF file has only one source file)
* then we take the full URI path to essence file and try each subpath starting
* from the end (filename).
*
* <local_path>/essence_a.wav
* <local_path>/media/essence_a.wav
* <local_path>/path/media/essence_a.wav
* <local_path>/data/path/media/essence_a.wav
*/
char* p = uri->path + strlen (uri->path);
while (p > uri->path) {
if (*p == '/') { /* parsing URI, so will always be '/' as separator character */
local_filepath = laaf_util_build_path (DIR_SEP_STR, local_path, p, NULL);
if (!local_filepath) {
error ("Could not build filepath");
goto err;
}
debug ("Trying filepath : %s", local_filepath);
if (laaf_util_file_exists (local_filepath) == 1) {
foundpath = local_filepath;
goto found;
}
free (local_filepath);
local_filepath = NULL;
}
p--;
}
}
/* Try raw essence's URI, just in case... */
@ -248,76 +328,6 @@ aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_fil
goto found;
}
/*
* 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--;
}
/*
* "<localPathToAAFfile>/<essence.file>"
*/
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;
/*
* "<localPathToAAFfile>/<firstparentInOriginalEssencePath>/<essence.file>"
*/
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:
@ -336,7 +346,7 @@ found:
goto err;
}
debug ("File found at : %s", foundpath);
debug ("File found : %s", foundpath);
}
goto end;
@ -346,6 +356,7 @@ err:
end:
laaf_uri_free (uri);
laaf_uri_free (commonPathPartURI);
free (local_filepath);
free (aaf_path);
@ -774,10 +785,10 @@ aafi_parse_audio_essence (AAF_Iface* aafi, aafiAudioEssenceFile* audioEssenceFil
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");
fp = laaf_util_fopen_utf8 (audioEssenceFile->usable_file_path, "rb");
if (fp == NULL) {
error ("Could not open external audio essence file for reading : %s", audioEssenceFile->usable_file_path);
error ("Could not open external audio essence file for reading (%i: %s) : %s", errno, strerror (errno), audioEssenceFile->usable_file_path);
goto err;
}

View file

@ -3078,12 +3078,91 @@ aafi_retrieveData (AAF_Iface* aafi)
/* Post processing */
char* commonPathPart = NULL;
int externalAudioEssenceFileCount = 0;
aafiAudioEssenceFile* audioEssenceFile = NULL;
AAFI_foreachAudioEssenceFile (aafi, audioEssenceFile)
{
if (!audioEssenceFile->is_embedded) {
audioEssenceFile->usable_file_path = aafi_locate_external_essence_file (aafi, audioEssenceFile->original_file_path, aafi->ctx.options.media_location);
if (!audioEssenceFile->original_file_path) {
continue;
}
externalAudioEssenceFileCount++;
if (!commonPathPart) {
int rc = laaf_util_snprintf_realloc (&commonPathPart, 0, 0, "%s", audioEssenceFile->original_file_path);
if (rc < 0) {
error ("Failed to set commonPathPart");
free (commonPathPart);
commonPathPart = NULL;
}
// printf("Firstinit: %s\n", commonPathPart);
continue;
}
char* a = commonPathPart;
char* b = audioEssenceFile->original_file_path;
char* aEnd = a + strlen (a);
char* bEnd = b + strlen (b);
while (a < aEnd && b < bEnd) {
if (*a != *b) {
// printf("%c != %c\n", *a, *b );
break;
}
a++;
b++;
}
// printf("Then: %s %s\n", commonPathPart, audioEssenceFile->original_file_path);
if (a < aEnd) {
*a = 0x00;
}
// audioEssenceFile->usable_file_path = aafi_locate_external_essence_file( aafi, audioEssenceFile->original_file_path, aafi->ctx.options.media_location );
//
// if ( audioEssenceFile->usable_file_path == NULL ) {
// warning( "Could not locate external audio essence file '%s'", audioEssenceFile->original_file_path );
// }
}
}
if (externalAudioEssenceFileCount <= 1) {
// printf("commonPathPart: %s\n", commonPathPart );
free (commonPathPart);
commonPathPart = NULL;
} else if (commonPathPart && *commonPathPart != 0x00) {
/*
* Sometimes, all essence file names share a common prefix (Logic Pro).
* That's why we need to trim from the end, up to the last dir sep.
*/
char* p = commonPathPart + strlen (commonPathPart);
while (p > commonPathPart) {
if (*p == '/') { /* parsing URI, so will always be '/' as separator character */
break;
} else {
*p = 0x00;
}
p--;
}
}
audioEssenceFile = NULL;
AAFI_foreachAudioEssenceFile (aafi, audioEssenceFile)
{
if (!audioEssenceFile->is_embedded) {
audioEssenceFile->usable_file_path = aafi_locate_external_essence_file (aafi, audioEssenceFile->original_file_path, commonPathPart, aafi->ctx.options.media_location);
if (audioEssenceFile->usable_file_path == NULL) {
warning ("Could not locate external audio essence file '%s'", audioEssenceFile->original_file_path);
@ -3136,7 +3215,7 @@ aafi_retrieveData (AAF_Iface* aafi)
continue;
}
videoEssenceFile->usable_file_path = aafi_locate_external_essence_file (aafi, videoEssenceFile->original_file_path, aafi->ctx.options.media_location);
videoEssenceFile->usable_file_path = aafi_locate_external_essence_file (aafi, videoEssenceFile->original_file_path, commonPathPart, aafi->ctx.options.media_location);
if (videoEssenceFile->usable_file_path == NULL) {
error ("Could not locate external video essence file '%s'", videoEssenceFile->original_file_path);
@ -3144,6 +3223,8 @@ aafi_retrieveData (AAF_Iface* aafi)
}
}
free (commonPathPart);
aafPosition_t trackEnd = 0;
aafiAudioTrack* audioTrack = NULL;

View file

@ -400,6 +400,76 @@ aafi_convertUnitUint64 (aafPosition_t value, aafRational_t* valueEditRate, aafRa
return (uint64_t)((double)value * (destEditRateFloat / valueEditRateFloat));
}
aafPosition_t
aafi_getClipLength (AAF_Iface* aafi, aafiAudioClip* audioClip, aafRational_t* samplerate, char* isBeyondSource)
{
if (!audioClip) {
return 0;
}
uint64_t smallestFileLength = 0;
aafiAudioEssenceFile* smallestEssenceFile = NULL;
/*
* Common samplerate used for comparison, with a high resolution. Although it
* is very unlikely that each essence file composing the clip has a different
* samplerate, it is still possible...
*/
aafRational_t base_samplerate = { 192000, 1 };
aafiAudioEssencePointer* essencePointer = NULL;
AAFI_foreachEssencePointer (audioClip->essencePointerList, essencePointer)
{
uint64_t fileLen = aafi_convertUnitUint64 (essencePointer->essenceFile->length, essencePointer->essenceFile->samplerateRational, &base_samplerate);
if (!smallestFileLength || fileLen < smallestFileLength) {
smallestEssenceFile = essencePointer->essenceFile;
smallestFileLength = fileLen;
}
}
if (!smallestEssenceFile || !smallestFileLength) {
if (!smallestEssenceFile) {
warning ("Clip has no source essence file");
} else if (smallestFileLength == 0) {
warning ("Could not check source file length (0 or not set)");
}
if (samplerate) {
return aafi_convertUnit (audioClip->len, audioClip->track->edit_rate, samplerate);
}
return aafi_convertUnit (audioClip->len, audioClip->track->edit_rate, smallestEssenceFile->samplerateRational);
}
aafPosition_t clipLen = 0;
aafPosition_t fileLen = 0;
if (samplerate) {
clipLen = aafi_convertUnit (audioClip->len, audioClip->track->edit_rate, samplerate);
fileLen = aafi_convertUnit (smallestEssenceFile->length, smallestEssenceFile->samplerateRational, samplerate);
} else {
clipLen = aafi_convertUnit (audioClip->len, audioClip->track->edit_rate, smallestEssenceFile->samplerateRational);
fileLen = smallestEssenceFile->length;
}
if (clipLen > fileLen) {
if (isBeyondSource) {
*isBeyondSource = 1;
}
warning ("Clip length (%li) is beyond the end of the smallest clip source file (%li). Using file length instead.", clipLen, fileLen);
return fileLen;
}
if (isBeyondSource) {
*isBeyondSource = 0;
}
return clipLen;
}
int
aafi_removeTimelineItem (AAF_Iface* aafi, aafiTimelineItem* timelineItem)
{

View file

@ -458,22 +458,7 @@ cfb_openFile (CFB_Data* cfbd)
return -1;
}
#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
cfbd->fp = laaf_util_fopen_utf8 (cfbd->file, "rb");
if (!cfbd->fp) {
error ("%s.", strerror (errno));

View file

@ -557,7 +557,7 @@ typedef struct _aafData {
#define aafUIDCmp(auid1, auid2) \
((auid1) != NULL && \
(auid2) != NULL && \
((auid2)) != NULL && \
(auid1)->Data1 == (auid2)->Data1 && \
(auid1)->Data2 == (auid2)->Data2 && \
(auid1)->Data3 == (auid2)->Data3 && \

View file

@ -36,7 +36,7 @@
#include "aaf/AAFIface.h"
char*
aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_filepath, const char* search_location);
aafi_locate_external_essence_file (AAF_Iface* aafi, const char* original_uri_filepath, const char* commonPathPart, const char* search_location);
/**
* Extract audio essence file.

View file

@ -988,6 +988,9 @@ aafi_convertUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational
uint64_t
aafi_convertUnitUint64 (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate);
aafPosition_t
aafi_getClipLength (AAF_Iface* aafi, aafiAudioClip* audioClip, aafRational_t* samplerate, char* isBeyondSource);
int
aafi_removeTimelineItem (AAF_Iface* aafi, aafiTimelineItem* timelineItem);

View file

@ -90,6 +90,9 @@ laaf_util_windows_utf16toutf8 (const wchar_t* wstr);
int
laaf_util_file_exists (const char* filepath);
FILE*
laaf_util_fopen_utf8 (const char* filepath, const char* mode);
char*
laaf_util_clean_filename (char* filename);

View file

@ -1,2 +1,2 @@
#pragma once
#define LIBAAF_VERSION "v1.0-11-gb04c547"
#define LIBAAF_VERSION "v1.0-22-gfab4651"

View file

@ -513,6 +513,43 @@ laaf_util_file_exists (const char* filepath)
return 0;
}
FILE*
laaf_util_fopen_utf8 (const char* filepath, const char* mode)
{
FILE* fp = NULL;
if (!filepath) {
return NULL;
}
#ifdef _WIN32
wchar_t* wfile = laaf_util_windows_utf8toutf16 (filepath);
if (!wfile) {
// error( "Unable to convert filepath to wide string : %s", cfbd->file );
return NULL;
}
const wchar_t* wmode = NULL;
if (strcmp (mode, "rb") == 0) {
wmode = L"rb";
} else if (strcmp (mode, "wb") == 0) {
wmode = L"wb";
} else {
return NULL;
}
fp = _wfopen (wfile, wmode);
free (wfile);
#else
fp = fopen (filepath, mode);
#endif
return fp;
}
static int
utf8CodeLen (const uint16_t* u16Code)
{