2015-01-30 6 views
0

Я пытаюсь воспроизвести звуковую дорожку из файла mp4 на свой динамик. Я знаю, что Media Foundation способен декодировать аудиопоток, поскольку я могу воспроизвести его с помощью инструмента TopoEdit.Воспроизведение аудио из файла в динамик с помощью Media Foundation

В приведенном ниже примере кода я не использую медиа-сеанс или топологию. Я пытаюсь вручную подключить медиа-источник к записывающей машине. Причина, по которой я хочу сделать это, заключается в том, что я в конечном итоге намерен получать исходные образцы из сети, а не из файла.

Ошибка, которую я получаю на линии pSinkWriter-> WriteSample при запуске примера ниже, это MF_E_INVALIDREQUEST (0xC00D36B2). Поэтому я подозреваю, что я не правильно подключился.

#include <stdio.h> 
#include <tchar.h> 
#include <mfapi.h> 
#include <mfplay.h> 
#include <mfreadwrite.h> 

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

#define CHECK_HR(hr, msg) if (hr != S_OK) { printf(msg); printf("Error: %.2X.\n", hr); goto done; } 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 
    MFStartup(MF_VERSION); 

    IMFSourceResolver *pSourceResolver = NULL; 
    IUnknown* uSource = NULL; 
    IMFMediaSource *mediaFileSource = NULL; 
    IMFSourceReader *pSourceReader = NULL; 
    IMFMediaType *pAudioOutType = NULL; 
    IMFMediaType *pFileAudioMediaType = NULL; 
    MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; 
    IMFMediaSink *pAudioSink = NULL; 
    IMFStreamSink *pStreamSink = NULL; 
    IMFMediaTypeHandler *pMediaTypeHandler = NULL; 
    IMFMediaType *pMediaType = NULL; 
    IMFMediaType *pSinkMediaType = NULL; 
    IMFSinkWriter *pSinkWriter = NULL; 

    // Set up the reader for the file. 
    CHECK_HR(MFCreateSourceResolver(&pSourceResolver), "MFCreateSourceResolver failed.\n"); 

    CHECK_HR(pSourceResolver->CreateObjectFromURL(
     L"big_buck_bunny.mp4",  // URL of the source. 
     MF_RESOLUTION_MEDIASOURCE, // Create a source object. 
     NULL,      // Optional property store. 
     &ObjectType,    // Receives the created object type. 
     &uSource     // Receives a pointer to the media source. 
     ), "Failed to create media source resolver for file.\n"); 

    CHECK_HR(uSource->QueryInterface(IID_PPV_ARGS(&mediaFileSource)), 
     "Failed to create media file source.\n"); 

    CHECK_HR(MFCreateSourceReaderFromMediaSource(mediaFileSource, NULL, &pSourceReader), 
     "Error creating media source reader.\n"); 

    CHECK_HR(pSourceReader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &pFileAudioMediaType), 
     "Error retrieving current media type from first audio stream.\n"); 

    // printf("File Media Type:\n"); 
    // Dump pFileAudioMediaType. 

    // Set the audio output type on the source reader. 
    CHECK_HR(MFCreateMediaType(&pAudioOutType), "Failed to create audio output media type.\n"); 
    CHECK_HR(pAudioOutType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), "Failed to set audio output media major type.\n"); 
    CHECK_HR(pAudioOutType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float), "Failed to set audio output audio sub type (Float).\n"); 

    CHECK_HR(pSourceReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, pAudioOutType), 
     "Error setting reader audio output type.\n"); 

    // printf("Source Reader Output Type:"); 
    // Dump pAudioOutType. 

    CHECK_HR(MFCreateAudioRenderer(NULL, &pAudioSink), "Failed to create audio sink.\n"); 

    CHECK_HR(pAudioSink->GetStreamSinkByIndex(0, &pStreamSink), "Failed to get audio renderer stream by index.\n"); 

    CHECK_HR(pStreamSink->GetMediaTypeHandler(&pMediaTypeHandler), "Failed to get media type handler.\n"); 

    // My speaker has 3 audio types of which I got the furthesr with the third one. 
    CHECK_HR(pMediaTypeHandler->GetMediaTypeByIndex(2, &pSinkMediaType), "Failed to get sink media type.\n"); 

    CHECK_HR(pMediaTypeHandler->SetCurrentMediaType(pSinkMediaType), "Failed to set current media type.\n"); 

    // printf("Sink Media Type:\n"); 
    // Dump pSinkMediaType. 

    CHECK_HR(MFCreateSinkWriterFromMediaSink(pAudioSink, NULL, &pSinkWriter), "Failed to create sink writer from audio sink.\n"); 

    printf("Read audio samples from file and write to speaker.\n"); 

    IMFSample *audioSample = NULL; 
    DWORD streamIndex, flags; 
    LONGLONG llAudioTimeStamp; 

    for (int index = 0; index < 10; index++) 
    //while (true) 
    { 
     // Initial read results in a null pSample?? 
     CHECK_HR(pSourceReader->ReadSample(
      MF_SOURCE_READER_FIRST_AUDIO_STREAM, 
      0,        // Flags. 
      &streamIndex,     // Receives the actual stream index. 
      &flags,       // Receives status flags. 
      &llAudioTimeStamp,    // Receives the time stamp. 
      &audioSample     // Receives the sample or NULL. 
      ), "Error reading audio sample."); 

     if (flags & MF_SOURCE_READERF_ENDOFSTREAM) 
     { 
      printf("End of stream.\n"); 
      break; 
     } 
     if (flags & MF_SOURCE_READERF_STREAMTICK) 
     { 
      printf("Stream tick.\n"); 
      pSinkWriter->SendStreamTick(0, llAudioTimeStamp); 
     } 

     if (!audioSample) 
     { 
      printf("Null audio sample.\n"); 
     } 
     else 
     { 
      CHECK_HR(audioSample->SetSampleTime(llAudioTimeStamp), "Error setting the audio sample time.\n"); 

      CHECK_HR(pSinkWriter->WriteSample(0, audioSample), "The stream sink writer was not happy with the sample.\n"); 
     } 
    } 

done: 

    printf("finished.\n"); 
    getchar(); 

    return 0; 
} 

Я пропустил код, который сбрасывает типы носителей для краткости, но их вывод показан ниже. Вполне возможно, что у меня нет надлежащих типов медиа.

File Media Type: 
Audio: MAJOR_TYPE=Audio, PREFER_WAVEFORMATEX=1, {BFBABE79-7434-4D1C-94F0-72A3B9E17188}=0, {7632F0E6-9538-4D61-ACDA-EA29C8C14456}=0, SUBTYPE={00001610-0000-0010-8000-00AA00389B71}, NUM_CHANNELS=2, SAMPLES_PER_SECOND=22050, BLOCK_ALIGNMENT=1, AVG_BYTES_PER_SECOND=8000, BITS_PER_SAMPLE=16, USER_DATA=<BLOB>, {73D1072D-1870-4174-A063-29FF4FF6C11E}={05589F81-C356-11CE-BF01-00AA0055595A}, ALL_SAMPLES_INDEPENDENT=1, FIXED_SIZE_SAMPLES=1, SAMPLE_SIZE=1, MPEG4_SAMPLE_DESCRIPTION=<BLOB>, MPEG4_CURRENT_SAMPLE_ENTRY=0, AVG_BITRATE=64000, 

Source Reader Output Type: 
Audio: MAJOR_TYPE=Audio, SUBTYPE=Float, 

Sink Media Type: 
Audio: MAJOR_TYPE=Audio, SUBTYPE=Float, NUM_CHANNELS=2, SAMPLES_PER_SECOND=48000, BLOCK_ALIGNMENT=8, AVG_BYTES_PER_SECOND=384000, BITS_PER_SAMPLE=32, ALL_SAMPLES_INDEPENDENT=1, CHANNEL_MASK=3, 

Любые подсказки относительно того, где я мог бы выглядеть следующим образом, будут оценены.

ответ

0

Мне не хватало писателя-приемника BeginWriting call.

CHECK_HR(pSinkWriter->BeginWriting(), "Sink writer begin writing call failed.\n"); 

что есть некоторые аудио, выходящий из динамиков, но он имеет очень плохую измельчить к нему так, что-то еще, что я пропускаю.

0

Тип носителя, который вы устанавливаете на Reader, является неполным. MF_MT_AUDIO_AVG_BYTES_PER_SECOND MF_MT_AUDIO_BLOCK_ALIGNMENT и MF_MT_AUDIO_NUM_CHANNELS отсутствуют.

Я установил бы тип носителя, который вы извлекли из обработчика mediatype sink.

+0

Спасибо за предложения. Пробовал эти вещи, но безрезультатно. Тип вывода из обработчика mediatype не подходит для считывателя. Полный образец доступен здесь, если он вызвал ваш интерес https://github.com/sipsorcery/mediafoundationsamples/tree/master/MFAudio. – sipwiz

Смежные вопросы