2
votes

I am trying to modify the metadata of some audio files in C++, and I came across [what I thought was] a possible way using Windows Media Foundation. So I tried to put together a simple solution:

#include <atlbase.h>
#include <mfapi.h>
#include <mfidl.h>
#include <Windows.h>

#pragma comment(lib, "Mf.lib")
#pragma comment(lib, "Mfplat.lib")


int main() {
    HRESULT hr;

    CComPtr<IMFSourceResolver> source_resolver(nullptr);
    if (FAILED(hr = MFCreateSourceResolver(&source_resolver))) {
        // Handle errors...
    }

    MF_OBJECT_TYPE object_type = MF_OBJECT_INVALID;
    CComPtr<IUnknown> source_object(nullptr);
    if (FAILED(hr = source_resolver->CreateObjectFromURL(L"audio_file_here", MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_READ | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, NULL, &object_type, &source_object))) {
        // Handle errors...
    }

    CComPtr<IMFMediaSource> source(nullptr);
    if (FAILED(hr = source_object->QueryInterface(IID_PPV_ARGS(&source)))) {
        // Handle errors...
    }

    CComPtr<IMFPresentationDescriptor> presentation_descriptor(nullptr);
    if (FAILED(hr = source->CreatePresentationDescriptor(&presentation_descriptor))) {
        // Handle errors...
    }

    CComPtr<IMFMetadataProvider> metadata_prov(nullptr);
    if (FAILED(hr = MFGetService(source, MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&metadata_prov)))) {
        // Handle errors...
    }

    CComPtr<IMFMetadata> metadata(nullptr);
    if (FAILED(hr = metadata_prov->GetMFMetadata(presentation_descriptor, 0, NULL, &metadata))) {
        // Handle errors...
    }

    /* Use metadata, etc etc */
}

It works fine for a standard MP3 (.mp3) file, yet it always fails on AAC (.m4a from iTunes) audio files. Specifically, the MFGetService() function fails with a return value given by Visual Studio as "The object does not support the specified service.".

I don't understand why this is the case. Right here it says Media Foundation supports AAC, and Windows definitely supports it somehow, because I can play my AAC files perfectly fine via the in-built Groove Music player.
Furthermore, the file metadata is also readable by Windows somehow, because I can view the properties of the file in Explorer, which it lists the title, artist, album, etc just fine.

So how can I read and write metadata from MP3 and AAC audio files? Is it possible through Media Foundation, or do I need another tool from the Windows APIs? (I've seen reference here to a method involving a "Windows Shell interface", is that the way to go?)

1

1 Answers

1
votes

First of all, your question is not actually related to AAC. You don't do AAC files here and your file is a MPEG-4 file (typically .MP4 however your .M4A is just a variant/alias of .MP4).

So the question is whether you can access the metadata of MPEG-4 file using MF_METADATA_PROVIDER_SERVICE or otherwise with Media Foundation.

Note that "support for AAC or MPEG-4" does not necessarily means metadata management as metadata management is, after all, an auxiliary capability.

It seems Microsoft deprecated metadata provider service and is no longer offering it for new media sources. Even though support for MF_METADATA_PROVIDER_SERVICE remains available for .MP3 files, it is no longer offered for .MP4. Instead, Microsoft suggests use of shell property handlers, which, for MP4 files, recourse to Media Foundation internally.

See MF_METADATA_PROVIDER_SERVICE for MP4 file:

To get metadata from the MP4 source you should actually get the IPropertyStore interface from the MF_PROPERTY_HANDLER_SERVICE service. MSDN is being updated to document this new method of retrieving metadata...

For info, the standard Shell property keys are documented here: Windows Properties.

Shell and explorer use exactly this method to retrieve the metadata.

You can also use FilePropertyStore tool from there to quickly list properties available via shell property handler API:

enter image description here