Code Monkey home page Code Monkey logo

libaaf's Introduction

libaaf

libaaf is a C coded library for AAF file reading. The AAF beeing a quite complex file format, libaaf provides an easy-to-implement, audio-oriented, FLOSS solution.

libaaf runs under Linux, Windows and OSX.

aaftool

aaftool is a command line tool to inspect AAF structure, essences, tracks and clips, extract embedded media files, etc.

aaftool Copyright (c) 2017-2024 Adrien Gesta-Fline
libaaf v1.0

usage: aaftool [analysis|extraction] [options] [AAFFILE]

 CFB Analysis:

   --cfb-header                       Display CFB Header.
   --cfb-fat                          Display CFB FAT.
   --cfb-minifat                      Display CFB MiniFAT.
   --cfb-difat                        Display CFB DiFAT.
   --cfb-nodes                        Display CFB node list.

   --cfb-node                 <path>  Display node located at the given <path>.


 AAF Analysis:

   --aaf-summary                      Display informations from both header and identification objects.
   --aaf-essences                     Display retrieved AAF audio and video essences.
   --aaf-clips                        Display retrieved AAF audio and video clips.
   --aaf-classes                      Display classes contained in AAF file.
   --aaf-meta                         Display classes and properties from the MetaDictionary.
   --aaf-properties                   Display properties of all objects in file.

   --trace                            Display AAF class/object structure while parsing.
   --dump-meta                        Display MetaProperties details for each parsed class containing meta properties.
   --dump_tagged_value                Display standard TaggedValue properties of Mobs and Components objects.
   --dump-class         <AAFClassID>  Display aaf properties of a specific AAFClass when it is parsed.
   --dump-class-raw     <AAFClassID>  Display raw properties of a specific AAFClass when it is parsed.


 Embedded Media Extraction:

   --extract-essences                 Extract all embedded audio essences as they are stored (wav or aiff),
                                      unless --extract-format is set. Raw PCM is extracted as wav file.
   --extract-clips                    Extract all embedded audio clips (trimed essences) as wav files.
   --extract-path             <path>  Location where embedded files are extracted.
   --extract-format       <bwav|wav>  Force extract format to wav or broadcast wav.
   --extract-mobid                    Name extracted files with their MobID. This also prevents any non-latin
                                      character in filename.


 Software Specific Options:

   --pt-true-fades                    Replace rendered ProTools fade clips with real fades when possible,
                                      when surrounding clips has enough handle size.
   --pt-remove-sae                    Remove all ProTools "sample accurate edit" small clips.


 Options:

   --media-location           <path>  Location of external audio and video essence files.

   --samplerate               <rate>  Sample rate used for converting displayed position
                                      and duration values. If not set, AAF dominant sample
                                      rate is used.
   --pos-format <tc|hms|samples|raw>  Position and duration display format.
   --show-automation                  Show track and clip automation values when --aaf-clips is set.
   --show-metadata                    Show source and clip metadata when --aaf-essences or --aaf-clips is set.

   --relative-path                    Prints AAF's relative essence path when --aaf-essences is set.

   --no-color                         Disable colored output.
   --log-file                 <file>  Save output to file instead of stdout.

   --verb                      <num>  0=quiet 1=error 2=warning 3=debug.

libaaf Features

  • Supports embedded raw PCM/WAV/AIFF essences and provides function for file extraction.
  • Supports external essence files, with auto-location function (relative to AAF file location).
  • Supports multi-channel clip out of a single multi-channel essence file.
  • Supports multi-channel clip out of multiple single-channel essence files.
  • Supports multi-channel tracks.
  • Supports fade in/out and x-fades.
  • Supports clip-based and track-based fixed and varying gain.
  • Supports track-based fixed/varying pan.
  • Supports timecode
  • Supports composition metadata (comments, tapeid, etc.)
  • libaaf being audio-oriented right now, it only supports a single video clip. Better video support could be implemented later.

AAF is known for its poor interoperability, each software having its own way to describe things, some adding non-standard features. libaaf implements all of those proprietary features that have been observed so far in dozens of files coming from the following software :

  • Avid Media Composer 8.4.5 - 8.8.3 - 18.12.5 - 23.12
  • Adobe Premiere Pro 12.0 - 23.5.0
  • ProTools 10.3.10 - 2023.12
  • Davinci Resolve 17.4.6 - 18.5
  • Logic Pro 9.1.7 - 10.7.4
  • Fairlight Evo/Dream 2.5.1 - 4.1.75

Avid Media Composer

  • Supports SubClip CompositionMobs.
  • Supports AdjustedClip CompositionMobs.
  • Supports proprietary Audio Warp OperationGroup (leading to a wrong clip source offset when importing in most commercial implementations).
  • Supports proprietary markers: position, length, name, description, color.
  • Supports proprietary track solo / mute.
  • Supports proprietary fade curve types.
  • Supports proprietary source metadata.
  • Supports proprietary SubClip metadata.

ProTools

  • Supports recovering of real fades, out of rendered fade clips.
  • Supports removing of sample accurate edit clips, recovering length of useful clips.

Davinci Resolve

  • Supports proprietary markers.

Library usage

#include <libaaf.h>

/* allocate a new AAF_Iface object */
AAF_Iface *aafi = aafi_alloc( NULL );

if ( !aafi ) {
	return -1; /* error */
}

/* set verbosity level, optional file pointer or callback function */
aafi_set_debug( aafi, VERB_DEBUG, 1, stdout, NULL, NULL );

/* set libaaf options */
aafi_set_option_int( aafi, "trace", 1 );
aafi_set_option_int( aafi, "dump_meta", 1 );
aafi_set_option_int( aafi, "dump_tagged_value", 1 );
aafi_set_option_int( aafi, "protools", (AAFI_PROTOOLS_OPT_REPLACE_CLIP_FADES | AAFI_PROTOOLS_OPT_REMOVE_SAMPLE_ACCURATE_EDIT)  );
aafi_set_option_str( aafi, "media_location", "./media/" );
aafi_set_option_str( aafi, "dump_class_aaf_properties", "AAFClassID_TimelineMobSlot" );

/* load AAF file */
if ( aafi_load_file( aafi, "./file.aaf" ) ) {
	return -1; /* error */
}

Retrieve Media Essences

aafiAudioEssenceFile *audioEssenceFile = NULL;

AAFI_foreachAudioEssenceFile( aafi, audioEssenceFile ) {
	/* process audio essence */
}

Retrieve Tracks and Clips

aafiAudioTrack   *audioTrack = NULL;
aafiTimelineItem *audioItem  = NULL;

AAFI_foreachAudioTrack( aafi, audioTrack ) {

	/* process track */

	AAFI_foreachTrackItem( audioTrack, audioItem ) {

		aafiAudioClip  *audioClip = aafi_timelineItemToAudioClip( audioItem );
		aafiTransition *crossFade = aafi_timelineItemToCrossFade( audioItem );

		if ( audioClip ) {

			/* process clip */

			aafiTransition *fadein  = aafi_getFadeIn( audioClip );
			aafiTransition *fadeout = aafi_getFadeOut( audioClip );

			if ( fadein ) {
				/* process fade in */
			}

			if ( fadeout ) {
				/* process fade out */
			}
		}
		else if ( crossFade ) {
			/* process cross fade */
		}
	}
}

Build

libaaf doesn't rely on any specific dependency.

cd build
cmake ..
make

libaaf's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

libaaf's Issues

Reliance on non-standard location parameters

Hi! ๐Ÿ‘‹
I am currently trying to package this library for Arch Linux as it is now an implied requirement for ardour.

I noticed that in

LibAAF/CMakeLists.txt

Lines 62 to 64 in 3e4c2cd

set( BIN_INSTALL_PATH "/usr/local/bin/" )
set( LIB_INSTALL_PATH "/usr/local/lib/" )
set( HEADERS_INSTALL_PATH "/usr/local/include/" )

you are hardcoding non-standard location parameters.

This is very bad for downstream packaging as one can not override these locations without patching the CMakeLists.txt.

Please instead rely on GNUInstallDirs, which is a builtin facility of cmake. Reinventing the wheel here will unfortunately be very painful for anyone else otherwise.

All that downstreams should have to pass in to cmake when it comes to defining install location is -D CMAKE_INSTALL_PREFIX=/usr to modify the prefix used for the target location.

I can try and have a look whether I can provide a patch for this.

Fails to build with " error: 'aafiAudioClip' has no member named 'subClipName' "

Cloned the repo, followed the instructions to build, but failed with this:

`[ 73%] Building C object CMakeFiles/AAFInfo.dir/tools/AAFInfo.c.o
/home/benalb/tmp/LibAAF/tools/AAFInfo.c: In function 'main':
/home/benalb/tmp/LibAAF/tools/AAFInfo.c:775:59: error: 'aafiAudioClip' has no member named 'subClipName'
775 | (audioClip->subClipName) ? " ClipName: "" : "",
| ^~
/home/benalb/tmp/LibAAF/tools/AAFInfo.c:776:59: error: 'aafiAudioClip' has no member named 'subClipName'
776 | (audioClip->subClipName) ? audioClip->subClipName : L"",
| ^~
/home/benalb/tmp/LibAAF/tools/AAFInfo.c:776:85: error: 'aafiAudioClip' has no member named 'subClipName'
776 | (audioClip->subClipName) ? audioClip->subClipName : L"",
| ^~
/home/benalb/tmp/LibAAF/tools/AAFInfo.c:777:59: error: 'aafiAudioClip' has no member named 'subClipName'
777 | (audioClip->subClipName) ? "" " : "" );
| ^~
make[2]: *** [CMakeFiles/AAFInfo.dir/build.make:76: CMakeFiles/AAFInfo.dir/tools/AAFInfo.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:116: CMakeFiles/AAFInfo.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

`

Unrelated functions in libAAF

libAAF is a library to handle AAF files it should not concern itself with anything else.

Please consider removing unrelated functions from the library that are not directly related to AAF.
e.g. aafi_enable_windows_VT100_output.

Missing build instructions

It would be nice to have some build instructions for people not familiar with C, who whould like to be able to use the provided tools.

All I found was in the "Tools" section of README.md :

To build those, just run `make` 

But that is clearly not enough:

~/src/LibAAF-master$ make
make --no-print-directory -C LibAAF
makedepend -Y LibCFB/LibCFB.c LibCFB/CFBDump.c AAFCore/AAFToText.c AAFCore/AAFDump.c AAFCore/AAFUtils.c AAFCore/AAFCore.c AAFCore/AAFClass.c AAFIface/AAFIAudioFiles.c AAFIface/ProTools.c AAFIface/AAFIface.c AAFIface/AAFIParser.c common/utils.c 2>/dev/null
make[1]: *** [Makefile:30: depend] Error 127
make: *** [Makefile:22: libAAF] Error 2

exclude repository configuration from the release tarballs

This repository tracks repository configuration files (like .gitignore), which is good practice.

Unfortunately, these .gitignore files are also part of the release tarballs (which have nothing to do with a git-repository, apart from accidentally being created from one).

This is kind of problematic, as downstream projects that might want to ignore completely different things will also inherit these .gitignore files.

E.g. for Debian (and Ubuntu, and ...), the source tarballs are imported verbatim into a packaging (git) repository. However, Debian does not do development of LibAAF (or whatever) since this is the job of the upstream developers, and is much more concerned about reproducible build processes and the like. As such we actually are interested to see all the build artifacts when doing a git status.

The solution is simple:
please exclude all repository configuration from the release tarballs.

Missing limits.h include

Compiling libAAF on macOS fails with missing INT_MAX, CHAR_MIN, UCHAR_MAX` etc.

Can you backport the following commit from Ardour?
Ardour/ardour@c012ab1

or would you prefer me to file a pull-request?

library prints to stdout/err

It is bad practice for a library to print to stdout/stderr.

Say you write an application that can directly to output to stdout. This will not be possible if any shared library will also produce output there.

Common practice is to either only optionally enable debug messages for the shared-lib, or alternatively add a logger callback. Then the front-end application could set a log callback to receive any messages.

AAF for beta-testing...

I think it's time to gather some consensus on the remaining steps needed before we can make an AAF release available for beta-testing. My personal preference would be to beta-test in Mixbus - because that's where the demand for AAF has traditionally been.

As we've discussed previously, the interface needs to be via a GUI window, rather than it being a command line tool. And there's been a suggestion that we should change to the Pro Tools import strategy, where imported tracks get added to the currently loaded session, instead of generating a new session each time (tho' personally, I'd prefer to see a checkbox so that either strategy can be chosen...)

As a starting point I'd suggest we should switch to the PT import strategy and (initially) limit testing to embedded AAF files. It's just that this strategy would require a trivially simple GUI dialog - which we could gradually enhance later.

So what's the best way forward now? Before we can release AAF in Mixbus we'd first need to merge the branch into Ardour Master - but what should be the order of events..? The PT change and the GUI change are inter-dependent - so is it best to switch development to Master from now on (in readiness for inclusion in Mixbus) or does it all need to be working in the AAF branch first?

Licensing AGPL + Ardour

Is there a reason why you have picked AGPL?
For code to be used with Ardour we have so far avoided any AGPL code and libraries.

Seeing as this is a library, LGPL would be much better suited to begin with. Thanks for considering.

Create a new release

Hi! ๐Ÿ‘‹
As I'm currently looking into packaging this library to be able to upgrade ardour, it would be great if you could create a new release soon.

The import into ardour's sources happened at 85 commits past the 0.1 release (which includes quite a lot of fixes):
Ardour/ardour@7593551

I am currently blocked from even packaging 0.1 by #12, however after that is resolved it would be very good to create a release, as currently this library blocks me from upgrading ardour to 8.2.

code consolidation

int uriIsIPv4( const char *s, int size, char **err ) {
int octets = 0;
const char *currentOctetStart = s;
char prev = 0;
for ( int i = 0; i <= size; i++ ) {
if ( prev == 0 ) {
if ( IS_DIGIT(*(s+i)) ) {
currentOctetStart = (s+i);
prev = 'd';
continue;
}
if ( *(s+i) == '.' ) {
if ( err ) {
_laaf_util_snprintf_realloc( err, NULL, 0, "IPV4 parser error : can't start with a single '.'" );
}
return 0;
}
}
if ( prev == 'p' ) {
if ( IS_DIGIT(*(s+i)) ) {
currentOctetStart = (s+i);
prev = 'd';
continue;
}
if ( *(s+i) == '.' ) {
if ( err ) {
_laaf_util_snprintf_realloc( err, NULL, 0, "IPV4 parser error : can't have successive '.'" );
}
return 0;
}
}
if ( prev == 'd' ) {
if ( IS_DIGIT(*(s+i)) ) {
prev = 'd';
continue;
}
if ( i == size || *(s+i) == '.' ) { // period
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 );
}
return 0;
}
if ( i+1 == size ) {
if ( err ) {
_laaf_util_snprintf_realloc( err, NULL, 0, "IPV4 parser error : can't end with a single '.'" );
}
return 0;
}
prev = 'p';
octets++;
continue;
}
}
if ( i == size ) {
break;
}
if ( err ) {
_laaf_util_snprintf_realloc( err, NULL, 0, "IPV4 parser error : illegal char '%c' (0x%02x)", *(s+i), *(s+i) );
}
return 0;
}

Is there any reason why you don't just use sscanf (s, "%d.%d.%d.%d", &a, &b, c&, &d) == 4 here? or better yet just use libcurl for all methods in this file?

allow out-of-tree builds

Cmake allows for out-of-tree builds (e.g. where the srouce direcctory is read-only).

Unfortunately, LibAAF seems to actively prevent out-of-tree builds, by basing the output directory on PROJECT_SOURCE_DIR

LibAAF/CMakeLists.txt

Lines 73 to 75 in c095386

set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin )

i think instead the output directory should be based on CMAKE_BINARY_DIR

allow overriding the version

currently the version is calculated from git describe:

COMMAND ${GIT_EXECUTABLE} describe --tags --dirty --match "v*"

if git cannot be found, this falls back to some dummy version:

if ( NOT DEFINED LIBAAF_VERSION )
set( LIBAAF_VERSION v0.0.0-unknown )

this is somewhat problematic for downstream projects that also use git for their own reasons (with different tags, and whatnot).

it would be great if you could add a LIBAFF_VERSION option that allows to override the calculated version.

common named symbols in global namespace

utils.c and debug.c have some methods that may conflict with symbols provided by the app (or in Ardour's case plugins)

notably dump_hex, snprintf_realloc, clean_filename It is good practice for a library to either hide local functions (static) and/or prefix them with the library's name e.g aaf_dump_hex.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.