【问题标题】:Get Mp3 total duration in seconds (or millisecond) using Media Foundation使用 Media Foundation 获取以秒(或毫秒)为单位的 Mp3 总持续时间
【发布时间】:2023-04-11 03:27:02
【问题描述】:

我正在为 Windows 8.1 和 wp 8.1 开发通用应用程序

我编写了一个用于解码 mp3 文件的小 C++ 源代码,现在我想找到一种方法来获取总时间长度,然后再使用媒体基础 api 解码文件。

谢谢

【问题讨论】:

  • 我知道如何使用旧的 Windows Media Format SDK(它也解码 MP3)来做到这一点。但这里有一个需要注意的问题。 MP3 文件本身没有“文件头”。它们由每个 500-1500 字节之间的单个 MP3 帧组成。大多数 MP3 文件在整个编码过程中都以相同的比特率进行编码。因此,如果您可以解码第一个 MP3 标头并获取其块大小、采样率和采样数,您可以插入整个文件中的帧数。 ...
  • ... 但是,VBR(可变比特率)MP3 文件将具有不同的帧块,每个帧块具有不同的标头,指示不同的比特率编码。因此,获取 VBR mp3 文件持续时间的唯一准确方法是扫描每个帧块并计算其持续时间。大多数 SDK 不会这样做 - 相反,只会返回基于第一帧和整个文件大小的估计值。

标签: windows visual-c++ windows-phone-8 media


【解决方案1】:

MS Media Foundation 可以为您提供 MP3 文件的属性,包括持续时间。有一个sample app on Github,相关代码摘录在这里。这不是我的代码,它不能与StorageFile 给出的异步接口开箱即用,但是将方形钉安装到圆孔中的工作非常简单。

请注意,这里的 Duration 是 100 纳秒滴答,根据 MF_PD_DURATION documentation on MSDN

#include <collection.h>
#include <ppltasks.h>
#include <mfidl.h>
#include <mfapi.h>
#include <mfreadwrite.h>
#include <wrl.h>

#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfuuid.lib")

using namespace Platform;
using namespace Windows::Storage::Streams;
using namespace Microsoft::WRL;

// Only throw in exception based code (C++/CX), never throw in HRESULT error code based code.
#define THROW_IF_FAILED(hr)     { if (FAILED(hr)) throw Platform::Exception::CreateException(hr); }
#pragma comment(lib, "mfreadwrite.lib")

namespace MFUtils
{
    // This WinRT object provides JavaScript or C# code access to the information in the stream
    // that it needs to construct the AudioEncodingProperties needed to construct the AudioStreamDescriptor
    // needed to create a MediaStreamSource. Here is how to create it
    // var helper = new MFUtils.MFAttributesHelper(self.memoryStream, data.mimeType);

    public ref class MFAttributesHelper sealed
    {
    public:
        property UINT64 Duration;
        property UINT32 BitRate;
        property UINT32 SampleRate;
        property UINT32 ChannelCount;

        // The synchronous design only works with in memory streams.
        MFAttributesHelper(InMemoryRandomAccessStream^ stream, String^ mimeType)
        {
            THROW_IF_FAILED(MFStartup(MF_VERSION));
            // create an IMFByteStream from "stream"
            ComPtr<IMFByteStream> byteStream;
            THROW_IF_FAILED(MFCreateMFByteStreamOnStreamEx(reinterpret_cast<IUnknown*>(stream), &byteStream));

            // assign mime type to the attributes on this byte stream
            ComPtr<IMFAttributes> attributes;
            THROW_IF_FAILED(byteStream.As(&attributes));
            THROW_IF_FAILED(attributes->SetString(MF_BYTESTREAM_CONTENT_TYPE, mimeType->Data()));

            // create a source reader from the byte stream
            ComPtr<IMFSourceReader> sourceReader;
            THROW_IF_FAILED(MFCreateSourceReaderFromByteStream(byteStream.Get(), nullptr, &sourceReader));

            // get current media type
            ComPtr<IMFMediaType> mediaType;
            THROW_IF_FAILED(sourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &mediaType));

            // get all the data we're looking for
            PROPVARIANT prop;
            THROW_IF_FAILED(sourceReader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop));
            Duration = prop.uhVal.QuadPart;

            UINT32 data;
            THROW_IF_FAILED(sourceReader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_AUDIO_ENCODING_BITRATE, &prop));
            BitRate = prop.ulVal;

            THROW_IF_FAILED(mediaType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &data));
            SampleRate = data;

            THROW_IF_FAILED(mediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &data));
            ChannelCount = data;
        }

    private:
        ~MFAttributesHelper()
        {
            MFShutdown();
        }
    };
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多