使用Media Foundation以秒(或毫秒)获取Mp3总持续时间

时间:2014-08-08 19:23:35

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

我正在开发适用于Windows 8.1和wp 8.1的通用应用

我写了一个用于解码mp3文件的小c ++源代码,现在我想找到一种方法来获得使用media foundation api解码文件之前的总时间长度。

由于

1 个答案:

答案 0 :(得分:1)

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

请注意,此Duration符合MF_PD_DURATION documentation on MSDN的100纳秒刻度。

#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();
        }
    };
}