Windows мультимедиа основы декодирования аудиопотоков - PullRequest
1 голос
/ 27 февраля 2020

Я новичок в Windows Media Foundation, в настоящее время я следую некоторым учебникам по основам, чтобы начать работу и декодировать аудио. Тем не менее, я запускаю несколько вопросов. Используя: Windows 10 64 бит (1809), и я использую Python (ctypes и COM для взаимодействия).

1) IMFSourceReader не позволит мне выбрать или отменить выбор любого потока из. Я пробовал форматы wav и mp3 (и несколько разных файлов), но все они выдают ошибку. Согласно документации, для повышения производительности вы хотите отменить выбор других потоков и выбрать нужный поток, в данном случае аудио.

Однако: source_reader.SetStreamSelection(MF_SOURCE_READER_ANY_STREAM, False)

Выдает ошибку: OSError: [WinError -1072875853] The stream number provided was invalid.

Что должно быть правильным, поскольку значение MF_SOURCE_READER_ANY_STREAM (DWORD 4294967294) должно быть универсальным? Или я не прав в этом?

Я пытался увидеть, могу ли я просто выбрать аудиопоток: source_reader.SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, True)

, который вызывает другую ошибку: OSError: exception: access violation reading 0x0000000000000001

Мой текущий код до этого момента:

MFStartup(MF_VERSION)  # initialize

source_reader = IMFSourceReader() 

filename = "C:\\test.mp3"

MFCreateSourceReaderFromURL(filename, None, ctypes.byref(source_reader))  # out: source reader.

if source_reader:  # Not null
    source_reader.SetStreamSelection(MF_SOURCE_READER_ANY_STREAM, False)  # invalid stream #?

    source_reader.SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, True)  # access violation??

IMFSourceReader, кажется, работает нормально для других функций, таких как GetCurrentMediaType, SetCurrentMediaType, et c. Может ли он по-прежнему возвращать IMFSourceReader, если есть какие-либо проблемы?

2) Я не уверен, что неспособность выбрать потоки вызывает дальнейшие проблемы (я подозреваю, что это так). Если я просто пропущу выделение или отмена выбора потоков, все на самом деле работает до тех пор, пока не будет выполнена попытка преобразовать семпл в один буфер с ConvertToContiguousBuffer, который, согласно документации, выводит в IMFMediaBuffer. Проблема в том, что после запуска он возвращается как S_OK, но буфер равен null. Я использовал GetBufferCount, чтобы убедиться, что в образце есть хотя бы несколько буферов, и он всегда возвращает 1-3 в зависимости от используемого файла, поэтому он не должен быть пустым.

Вот соответствующий код:

while True:
    flags = DWORD()
    sample = IMFSample()

    source_reader.ReadSample(streamIndex, 0, None, ctypes.byref(flags), None, ctypes.byref(sample))  # flags, sample [out]

    if flags.value & MF_SOURCE_READERF_ENDOFSTREAM:
        print("READ ALL OF STREAM")
        break

    if sample:
        buffer_count = DWORD()
        sample.GetBufferCount(ctypes.byref(buffer_count))
        print("BUFFER COUNT IN SAMPLE", buffer_count.value)
    else:
        print("NO SAMPLE")
        continue

    buffer = IMFMediaBuffer()
    hr = sample.ConvertToContiguousBuffer(ctypes.byref(buffer))

    print("Conversion succeeded", hr == 0)  # true

    if buffer:
        print("CREATED BUFFER")
    else:
        print("BUFFER IS NULL")
        break

Я не уверен, где отсюда go, я не смог найти много объяснений по inte rnet относительно этих специфических c проблем. WMF все еще готов для Windows 10? Должен ли я использовать что-то еще? Я действительно в тупик, и любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

Обычно с MediaFoundation вам необходимо вызвать CoInitializeEx перед MFStartup:

Media Foundation и COM

Рекомендации для приложений

В Media Foundation асинхронная обработка и обратные вызовы обрабатываются рабочими очередями. Рабочие очереди всегда имеют многопоточные потоки (MTA), поэтому приложение будет иметь более простую реализацию, если оно также будет работать в потоке MTA. Поэтому рекомендуется вызывать CoInitializeEx с флагом COINIT_MULTITHREADED.

Функция MFCreateSourceReaderFromURL

Замечания

Вызовите CoInitialize (Ex) и MFStartup перед вызовом этой функции.

В вашем коде я не вижу вызова CoInitializeEx.

РЕДАКТИРОВАТЬ

Поскольку вы используете аудиофайл, обычно у вас должен быть только один аудиопоток, а индекс должен быть 0. Попробуйте:

source_reader.SetStreamSelection(0, True)

и сообщите нам результат .

0 голосов
/ 27 февраля 2020

Попробуйте использовать MF_SOURCE_READER_ALL_STREAMS вместо MF_SOURCE_READER_ANY_STREAM.

source_reader.SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, False) 

При чтении семплов вам также необходимо указать действительный индекс потока, который, как я подозреваю, в вашем случае не равен 0. Попробуйте:

source_reader.ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, None, ctypes.byref(flags), None, ctypes.byref(sample))

Также ваша обертка Python возвращает результат, когда вы звоните в Media Foundation? Почти все методы Media Foundation возвращают HRESULT, и важно проверить его равным S_OK, прежде чем продолжить. Если нет, то очень трудно определить, где произошел неправильный вызов.

Является ли WMF все еще готовым для Windows 10?

Многие люди спрашивали этот вопрос . Ответ зависит от того, что вам нужно сделать (в вашем случае поддержка аудиокода c очень ограничена, поэтому, возможно, это не лучший вариант). Но для таких вещей, как рендеринг аудио / видео, чтение / запись в медиа-файлы, захват аудио / видео устройств и т. Д. c. До сих пор Media Foundation является самой современной опцией, поддерживаемой Microsoft.

...