2017-02-20 14 views
3

Я застрять в такой ситуации, когда я получаю противоречивую информацию:GetOutputStatus говорит выход готов, ProcessOutput говорит NEED_MORE_INPUT

hr = pDecoder->lpVtbl->ProcessInput(pDecoder, dwInputStreamID, pSample, dwFlags); 
if (FAILED(hr) ...) 
//ProcessInput went well, no warnings from here. 

hr = pDecoder->lpVtbl->GetOutputStatus(pDecoder, &dwFlags); 
if (SUCCEEDED(hr)) { 
     if (dwFlags == MFT_OUTPUT_STATUS_SAMPLE_READY) { 
      // I get to here, sample is ready, yay! 
     } 
    } 
dwFlags = 0; 

hr = pDecoder->lpVtbl->GetInputStatus(pDecoder, 0, &dwFlags); 
if (SUCCEEDED(hr)) { 
    if (dwFlags == MFT_INPUT_STATUS_ACCEPT_DATA) { 
     //... 
    } else { 
     // we go here, input does not accept more data it seems. 
     // Sounds ok, we read the output that is ready and then we fill in more 
    } 

} 
dwFlags = 0; 

hr = pDecoder->lpVtbl->ProcessOutput(pDecoder, 
    dwFlags, 
    1, 
    pOutputSamples, 
    &pdwStatus 
); 
if (FAILED(hr)) { 
    if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { 
     // Ok, but why did GetOutputStatus say we were ready then? 
    } 
} 

// Calling GetOutputStatus to see whats going on 
hr = pDecoder->lpVtbl->GetOutputStatus(pDecoder, &dwFlags); 
if (SUCCEEDED(hr)) { 
    if (dwFlags == MFT_OUTPUT_STATUS_SAMPLE_READY) { 
     // nope. 
    } else { 
     // Now dwFlags is 0. 
    } 
} 

hr = pDecoder->lpVtbl->GetInputStatus(pDecoder, 0, &dwFlags); 
if (SUCCEEDED(hr)) { 
    if (dwFlags == MFT_INPUT_STATUS_ACCEPT_DATA) { 
     // this time we go here, we can now give more input again. 
     // but we got no data from ProcessOutput 
    } else { 
     //... 
    } 

} 
dwFlags = 0; 

Глядя на выборке данных средств массовой информации я послал к processOutput, чтобы заполнить в нем просто записывает нулевой ограничитель '\0' в начале буфера, но в противном случае он не записывает никакого вывода.

GetOutputStatus

Если метод возвращает флаг MFT_OUTPUT_STATUS_SAMPLE_READY, это означает, что вы можете создать один или несколько выходных отсчетов путем вызова IMFTransform :: ProcessOutput.

...

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

У меня пока нет ошибок при настройке входных и выходных потоков декодеров, поэтому я думаю, что потоки должны быть хорошими. И у меня нет никаких предупреждений при отправке на входной носитель, так что я думаю, что я должен быть в правильном состоянии. Но поведение, похоже, не соответствует тому, что, по моему мнению, предлагает документация. Также у меня есть только 1 входной и 1 выходной поток, если это интересно.

Как это могло случиться? У меня есть противоречивая информация из инструмента. Готовы ли данные, но я читаю это неправильно или что-то еще происходит?

Edit:

Были несколько замечаний с просьбой о дополнительной информации, а также один просящих минимальный полный пример, поэтому я решил попробовать его. Ниже приведена небольшая программа c, которая запускает все то, что я запускаю, и она имитирует мою среду, читая входные данные из файла и отправляя их так же, как я получаю свои данные. Я прервал почти всю обработку ошибок, удалил вспомогательные функции и закодировал несколько вещей. Эта программа воспроизводит эту проблему. Я бегу это в Visual Studio 2015.

#include <stdlib.h> 

//windows media foundation test 
#include <windows.h> 
#include <mfapi.h> 
#include <mfidl.h> 
#include <mfreadwrite.h> 
#include <stdio.h> 
#include <mferror.h> 

int chunk_handler(unsigned char* pBuf, unsigned short length); 

IMFTransform *pDecoder = NULL; 
DWORD dwInputStreamID; 
DWORD dwOutputStreamID; 


// inspierd by FindDecoder here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms701774(v=vs.85).aspx 
HRESULT FindDecoder(
    IMFTransform **ppDecoder // Receives a pointer to the decoder. 
) 
{ 
    HRESULT hr = S_OK; 
    UINT32 count = 0; 

    IMFActivate **ppActivate = NULL; 

    MFT_REGISTER_TYPE_INFO inputType = { 0 }; 

    inputType.guidMajorType = MFMediaType_Audio; 
    inputType.guidSubtype = MFAudioFormat_AAC; 

    hr = MFTEnumEx(
     MFT_CATEGORY_AUDIO_DECODER, 
     MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER, 
     &inputType,  // Input type 
     NULL,  // Output type 
     &ppActivate, 
     &count 
    ); 

    if (SUCCEEDED(hr) && count == 0) 
    { 
     hr = MF_E_TOPO_CODEC_NOT_FOUND; 
    } 

    // Create the first decoder in the list. 

    if (SUCCEEDED(hr)) 
    { 
     hr = ppActivate[0]->lpVtbl->ActivateObject(ppActivate[0], &IID_IMFTransform, (IUnknown**)ppDecoder); 
    } 

    for (UINT32 i = 0; i < count; i++) 
    { 
     ppActivate[i]->lpVtbl->Release(ppActivate[i]); 
    } 
    CoTaskMemFree(ppActivate); 

    return hr; 
} 

int main() 
{ 
    UINT32 samplesPerSec = 44100; 
    UINT32 bitsPerSample = 16; 
    UINT32 cChannels = 2; 

    HRESULT hr = S_OK; 
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); 

    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 

    DWORD dwFlags = MFSTARTUP_FULL; 
    hr = MFStartup(MF_VERSION, dwFlags); 

    // Create decoder 
    pDecoder = NULL; 
    hr = FindDecoder(&pDecoder); 

    // Create input and output audio types 
    IMFMediaType *pMediaIn = NULL;  // Pointer to an encoded audio type. 
    IMFMediaType *pMediaOut = NULL;  // Receives a matching PCM audio type. 

    /* Create pMediaIn */ 

    // Calculate derived values. 
    UINT32 blockAlign = cChannels * (bitsPerSample/8); 
    UINT32 bytesPerSecond = blockAlign * samplesPerSec; 

    // Create the empty media type. 
    hr = MFCreateMediaType(&pMediaIn); 

    // Set attributes on the type. 
    hr = pMediaIn->lpVtbl->SetGUID(pMediaIn, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); 
    hr = pMediaIn->lpVtbl->SetGUID(pMediaIn, &MF_MT_SUBTYPE, &MFAudioFormat_AAC); 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0x2a); // value can be found in my onenote, (AAC Profile, Level 4) 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AAC_PAYLOAD_TYPE, 3); // (LOAS/LATM) 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample); 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AUDIO_NUM_CHANNELS, cChannels); 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AUDIO_SAMPLES_PER_SECOND, samplesPerSec); 

    // blockAlign, bytesPerSecond and independent samples were commented out previously 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AUDIO_BLOCK_ALIGNMENT, blockAlign); 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, bytesPerSecond); 
    hr = pMediaIn->lpVtbl->SetUINT32(pMediaIn, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); 


    //first 12 bytes: 
    //wPayloadType  = 0 (raw AAC) 
    //wAudioProfileLevelIndication  = 0x29 (AAC Profile, Level 2) 
    //wStructType  = 0 
    // The last two bytes of MF_MT_USER_DATA contain the value of AudioSpecificConfig(), as defined by MPEG - 4. 
    // 00010 0100 0010 000 
    //AudioSpecificConfig.audioObjectType = 2 (AAC LC) (5 bits) 
    //AudioSpecificConfig.samplingFrequencyIndex = 4 (4 bits) (44100hz) 
    //AudioSpecificConfig.channelConfiguration = 2 (4 bits) 
    //GASpecificConfig.frameLengthFlag = 0 (1 bit) 
    //GASpecificConfig.dependsOnCoreCoder = 0 (1 bit) 
    //GASpecificConfig.extensionFlag = 0 (1 bit) 
    UINT8 audioSpecificConfig[] = { 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10 }; 
    hr = pMediaIn->lpVtbl->SetBlob(pMediaIn, &MF_MT_USER_DATA, audioSpecificConfig, 14); 


    /* Create pMediaOut */ 

    // Create the empty media type. 
    hr = MFCreateMediaType(&pMediaOut); 

    // Set attributes on the type. 
    hr = pMediaOut->lpVtbl->SetGUID(pMediaOut, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); 
    hr = pMediaOut->lpVtbl->SetGUID(pMediaOut, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); 
    hr = pMediaOut->lpVtbl->SetUINT32(pMediaOut, &MF_MT_AUDIO_NUM_CHANNELS, cChannels); 
    hr = pMediaOut->lpVtbl->SetUINT32(pMediaOut, &MF_MT_AUDIO_SAMPLES_PER_SECOND, samplesPerSec); 
    hr = pMediaOut->lpVtbl->SetUINT32(pMediaOut, &MF_MT_AUDIO_BLOCK_ALIGNMENT, blockAlign); 
    hr = pMediaOut->lpVtbl->SetUINT32(pMediaOut, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, bytesPerSecond); 
    hr = pMediaOut->lpVtbl->SetUINT32(pMediaOut, &MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample); 
    hr = pMediaOut->lpVtbl->SetUINT32(pMediaOut, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); 

    // Figure out streamcounts and ID's 
    DWORD inputStreamCount = 0; 
    DWORD outputStreamCount = 0; 

    hr = pDecoder->lpVtbl->GetStreamCount(pDecoder, &inputStreamCount, &outputStreamCount); // both StreamCounts == 1 

    DWORD dwInputID[1] = { 0 }; //hardcoded 
    DWORD dwOutputID[1] = { 0 }; //hardcoded 

    hr = pDecoder->lpVtbl->GetStreamIDs(pDecoder, inputStreamCount, dwInputID, outputStreamCount, dwOutputID); 
    if (FAILED(hr)) { 
     if (hr == E_NOTIMPL) { 
      // This is expected and quite ok. 
     } 
    } 

    dwInputStreamID = dwInputID[0]; 
    dwOutputStreamID = dwOutputID[0]; 

    // configure decoder for the two audio types 
    hr = pDecoder->lpVtbl->SetInputType(pDecoder, dwInputStreamID, pMediaIn, 0); 
    dwFlags = 0; 
    hr = pDecoder->lpVtbl->SetOutputType(pDecoder, dwOutputStreamID, pMediaOut, dwFlags); 

    /*one time setup is now done.*/ 

    // simulate sending in the first couple of chunks that I can get while trying to decode audio 

    // Reading this from file, again this is just read from a file in this example, in my real application I get the data sent to me in audio frame chunks. 
    // For example the first "chunk" of data is: 
    // 47fc 0000 b090 8003 0020 2066 0001 9800 0de1 2000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 001c 

    errno_t err; 
    FILE *file = NULL; 
    fopen_s(&file, "input.txt", "rb"); 

    unsigned char line[10000]; //big enough 
#define NR_OF_INPUTS 14 
    //       0 1 2 3 4 5 6 7 8 9 10 11 12 13 
    int sizes[NR_OF_INPUTS] = { 42, 42, 42, 42, 42, 340, 708, 503, 477, 493, 499, 448, 640, 511}; // lengths of the data 

    int i, j; 
    for (i = 0; i < NR_OF_INPUTS; i++) { 
     fread(line, sizeof(char), sizes[i], file); 

     printf("Input chunk number: %d\n", i); 
     for (j = 0; j < sizes[i]; j++) { 
      printf(" %02x", line[j]); 
     } 
     printf("\n\n"); 

     chunk_handler(line, sizes[i]); 
    } 

    fclose(file); 

    return 0; 
} 

int chunk_handler(unsigned char* pBuf, unsigned short length) { 

    const UINT SamplesPerSecond = 44100; 
    const UINT ChannelCount = 2; 
    const UINT SampleCount = length * ChannelCount; 
    const UINT BitsPerSample = 16; 
    const UINT BufferLength = BitsPerSample/8 * ChannelCount * length; 
    const LONGLONG sampleDuration = (long long)length * (long long)10000000/SamplesPerSecond; // in hns (hecto nano second?) 0.000 000 1. (Duration of the sample, in 100-nanosecond units., see IMFSample) 

    HRESULT hr = S_OK; 
    DWORD dwFlags = 0; 

    /* Setup for processInput */ 

    IMFSample *pSample = NULL; 
    IMFMediaBuffer *pInputBuffer = NULL; 
    hr = MFCreateMemoryBuffer(
     length, // Amount of memory to allocate, in bytes. 
     &pInputBuffer 
    ); 
    BYTE *pData = NULL; 

    hr = pInputBuffer->lpVtbl->Lock(pInputBuffer, &pData, NULL, NULL); 
    memcpy_s(pData, length, pBuf, length); 
    hr = pInputBuffer->lpVtbl->SetCurrentLength(pInputBuffer, length); 
    hr = pInputBuffer->lpVtbl->Unlock(pInputBuffer); 


    hr = MFCreateSample(&pSample); 
    hr = pSample->lpVtbl->AddBuffer(pSample, pInputBuffer); 
    //hr = pSample->lpVtbl->SetUINT32(pSample, &MFSampleExtension_Discontinuity, TRUE); 


    /* Setup for processOutput */ 
#define SAMPLES_PER_BUFFER 1 
    MFT_OUTPUT_DATA_BUFFER pOutputSamples[SAMPLES_PER_BUFFER]; 
    MFT_OUTPUT_STREAM_INFO streamInfo = { 0,0,0 }; 
    MFT_OUTPUT_STREAM_INFO *pStreamInfo = &streamInfo; 
    DWORD pdwStatus = 0; 

    hr = pDecoder->lpVtbl->GetOutputStreamInfo(pDecoder, dwOutputStreamID, pStreamInfo); 
    IMFSample *pOutSample = NULL; 
    DWORD minimumSizeOfBuffer = pStreamInfo->cbSize; 
    IMFMediaBuffer *pOutputBuffer = NULL; 

    // code checking for if MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLE and such, Turns out client (me) ne4ed to provide sample so lets do that 

    // Create the media buffer. 
    hr = MFCreateMemoryBuffer(
     minimumSizeOfBuffer, // Amount of memory to allocate, in bytes. 
     &pOutputBuffer 
    ); 
    hr = MFCreateSample(&pOutSample); 
    hr = pOutSample->lpVtbl->AddBuffer(pOutSample, pOutputBuffer); 

    pOutputSamples[0].pSample = pOutSample; 
    pOutputSamples[0].dwStreamID = dwOutputStreamID; 
    pOutputSamples[0].dwStatus = 0; 
    pOutputSamples[0].pEvents = NULL; 

    //INPUT 
    hr = pDecoder->lpVtbl->ProcessInput(pDecoder, dwInputStreamID, pSample, dwFlags); 
    if (FAILED(hr)) { 
     if (hr == MF_E_NOTACCEPTING) { 
      printf("Input cannot take more data\n"); 
     } 
     printf("error in ProcessInput\n"); 
    } 

    //OUTPUT 
    hr = pDecoder->lpVtbl->ProcessOutput(pDecoder, 
     dwFlags, 
     SAMPLES_PER_BUFFER, 
     pOutputSamples, 
     &pdwStatus 
    ); 
    if (FAILED(hr)) { 
     if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { 
      // this is ok, just need to make more calls to ProcessInput 
      printf("ProcessOutput needs more input\n"); 
     } 
     else { 
      printf("error in ProcessOutput\n"); 
     } 
    } 
    return 0; 
} 

В «file.txt» ссылки в коде должны содержать следующие вставленный в шестнадцатеричном:

47FC0000B090800300202066000198000DE120000000000000000000000000000000000000000000001C47FC0000B090800300202066000198000DE120000000000000000000000000000000000000000000001C47FC0000B090800300202066000198000DE120000000000000000000000000000000000000000000001C47FC0000B090800300202066000198000DE120000000000000000000000000000000000000000000001C47FC0000B090800300202066200198800DE120000000000000000000000000000000000000000000001C47FC0000B090800300FF4A214DE73987D722230566AD966E80B72A99797BFFB7978EB3DB9E248875BA38E42B7924EF58A2CCC578931AE67157BF6E7E3DC51B70265C888DA8CB0074753F9F0F3EF9B0F70CD8D5B2363C3B9CE1275DE0E4E7313C6F88FC611D87A932D4263BDFB8C74B5E9052DD5046AF66EA3AB55F9E2186ABCC5A72A3664F1CA21CC678AC24CBECD3797D7C2C50B335556E7DF5E51E5BECBEA1337CA71ACB7ACFD9EDABE47139CB0695F8D575EAB0E461BB5336ED00E2F0F5F381CAD2E9E2C0750FAE43460E9B372CCD016EE6E5547FF4F89EBACF3BE2EA21D7E9038E190CA4D46DB54633FCB9331E830DC6AFB7A1325F0E79DD1C6D886320F8C728DAA34AD00CA999CC089702E7CD7FD8EDEB1FEFFAB63F8D9E798CD483BE697B314BF749F17967FE9F46688D45D8D6B926300840223B9AD2B7291B288518835BB2629B61D79EAB5760D16FBEA3B909D4E7F56747FC0000B090800300FFFFB4216BD505EE8504B0D098342810840D0AF6CCCD71DEADAD6EB2F7117B85CAE255CC5C39130EF0EA7A7F7565275CB6CCBB9E70843BA4847444976535677F95480D0AEC0D0A63F40F1BF7B645AB70307D0262A388BBB2DE0F90E12FF5B46A2EAEB1C8E85C50061833EF9324731B4F7D29580BE0FA0DFAB6AA78341FF25422B0A7039F64C34BA063763E54D489805ADE242371C3C865F17360ADFD3956E6A6AC18D8463879AC4FA70D0ADAC9C5E146F5BB6541F8ACB2EEA53D1EF35EB0ED715F7C4B9A1A072908A66CE92A76328E43010B3820EC9E255C388BC5DE3E02D1393EA9FC70CD44555DE9F6E419C20F804F0361AC702CFFBDD6DEC4BBF6C7736AA1F207CFFC9934E9DBF039FE469D1B2B50B4507E8F6326BA9BD42B71A1A7AE74D23FF1F89CDAF27D614D3C2F8AD767004AC2421E11D8B86B058DEF88EB9A9C8E8C35CF980D0A56664CF27385181987F7878D06AB6F7E46200764841CB0820195C383613579C8836BA8622C06DF3889D200773EDC28AF89E3656DEE0699E66DDB9E7070EFB96BB024F2B4155A9E7806649A8C00A383586956581A0602015141282C140B100CF358BE372EEF5B65E51ACDEB2EDC4A9ADAD00D10420408761E859304BCD8828E72EEEC4AD4219560E77946692F3C51EA9BE12AC6431DFF674CF94931D357B6EF90E912A3B9ED135C6D620EBF7D887A38CC78E67B543838ABA936E67848A2744AF716CB8955C1CE9FB4784271584E49DE019496B654C6B413D74AA09ACFDF68233F39F176931E10A093B0C47961BC72F87C31FC3EA92BF55438EB90345122D1DE3BA14653C459A53C0E5CA3D8ED1097DDD3D5DB39C645D5E07396C76131C03B329A3C98E65A19E63380B51105F21089088038309AE0E4A17C6D6D827D5D85FF804805BAFC4441580F7FE5872EC3DD9C9C00312022F67A4D40AF900D0A1A5427DA204E113C93931E9A0209F7CD2303102E9F674A3B2B706E47FC0000B090800300FFEA210BD5159E8F6982B1602C703386BC713BE1AA54E75B0BA9092E29726E03838C74AADE6D55F03227C9F0F84F90159F2C64D517A77D6F1D69258146F8A3397C3BBA296084B027A9E6581390F1A00E4A3A26E67944B2F09DDEF851344D3BF2DA8A8B11C1C00750A7B34A310D04481F02AE190D0A41F83BD088CE2ED2BE9FE1819099C7A22D5C6738C32DE20F2201D6A603A2082DA21D6A677E2E471044B72C64C6085C734BD1C8D9E1287E93A588C4BAFB075E0D0A3751BC5ED4009F7F7E2500A8394D0B3D0D0A18F9CA85996BB1651362C72A739DE23A9ECDCF6CE771C523B42CB0A698213E554967559681AB800574D36050440CA4D00E48AA71748E65F5CAF6BAF7B01A64803C453ED2093582B6236DDE26AB2B2BC500002A129D1A56FA19400000E22952C4AE3BA298876484D89D4A832819C4D733AF5E6BADCACAE37CA17624B936E2A77A0914FB393C13DB11C2EF9C7E039F0718E7FFA578FDD875ADE3B4F3FAB20CF08AC721C4182E60E5A2D4DBCDA1810F88D64ADDA7CAD3981ABD3AD8E114BD505EBD8D5D7CBC9967899697B38D411ABAE11B391718EE9BCFAB917196FCC2B910B9170351CBAEB97577CD6F1D3215B0E72EAC739176AEAD6009AEBF56B882BE32319DFDFD33D5F28BA0706BA273601740829B8BADCE4537BD6BEF9BE0F9D2CBE60884F9225109718E47FC0000B090800300FFCF210BD51DB18561A4C0D9683033CD5F8EB5EB55ABDC64ADD244B26A26489960D9D84969A878658210307F2D01CE29359116C0739E92EA87B35B0D0AD5F223F143BE0D5D6EB2B69CCACFDECB8C36B5D9B771E03295998B9A62498D887106EC5E918E0C30076F5ECE6403391363A62CB44CBB6EFFD74CAC0CF90D0A2ADDC490E2306145701D85B1A9CA12C258CB7D81532D99FA8DF3C7A1894357950D0A0C0B7CBDB8D297200CFAAD4AEBC92BBDEE087AA9BFF6A49C2B7A7BC66900EBD78F859330033EB9C009C649B8A0E99E774E3ACC0C01DED63CC2247BB5A3C857D2D50D73D92C5BD345ECB6E9A6FEC7000D0AC2F870CEA2AB20BE4057C9EF9922083AA2ED64350DB514A84A0405E3CE51B6FAE53316CBFA2C87B393C5CDAEFB9561FB12DEC4C75F3C69C876464D094EC255825E57DF5AED77158BAEE979A9AA4BBCE372507AA149F8A2108A682471F2BD48D3DDDA49E896AFEA79BBCBCB96E00759FB9E77B110866D32F8C3061C4655E056BF8FD5F0417D1BF296F735F0D682437F67D9BCC05D6E8BD6E725050C41133E9D9D3E76280444FC260D435C631302720B6EA53BE9E7B890405D4564310F7F2C48027535A15DF807777F1EEF7F57DC0BDBBB398004C1CC5D159991BDAB0373926719A000006A1C47FC0000B090800300FFDE210BD515B290C2A0C1944C741819E4E755755C632A537335ADAD2EF5544B5481F1B472C55D552D4982F5FF89A5E18B3853B70D0A6380EF43AED06FBE5510F067C8E66CC6E0568C614076560EDDA09A3150EC4091D6FFEC2D78A38EF6FD5D52D0DC9F2BD2F3DC2DF9FA413F130355403920A91E9D2FA1FBAF09A7C239059DF6D3A72B24E8B96340288C68DEB4D9D44E9D2DAB0D3F8BBF15CDA44D549DCF8345F55DC594A21615BD6128E17D700240980B9DE7FC2456E7B7D5A0999AAD8EEEFF8B970E78B5BC34559F98FBA90D9C28BE444F0D0A8DEC59EB7D38104926B66CAC98E8B6DD3E69A2BA899B77D4C002DAC600A5734B62A006A1886E511063F09E93ADF3800B8E1CEBC528B8630900AE86759E7D1F08DF9DE47E57E93EC05714FDAAC43FCF03E57A551D29094162A8506AA31021E738E784DB8DDF350E667536B3875554BD5609E7C846792B5B0D0AA9DCCACFB143A6AB0B087917695136C22505859DDFB9E2CF3FC73FBDBEE77C1E853B74A0C023755C2BBA329D4C1D0298AC33342083E328F7F6663D5403C12943925C1007AAD0789F0E429D909DE53DA00D0ADEE57C77A966388A04C096FE3D08E41189037D5C2F32D71C015B46F31DF3F1D6855556F7A9339D0D0ADB788178227218CEB505E03BB5C7EEAD6A0BC63CFF7E9F4F00DD1C47FC0000B090800300FFE6210BD50D9E936181B0A0AC270B1102C451019A943352D95553994D5EEEEA5EB55448342299BD823F916D8AE11EB398B2D5CEB34CFAD3B2818D3F9E30884B0D0AEC3A05147354117537040109F46A27CD52806C4279C1C3E9FD9F6620C3ABF2AD8702767FBE226C934BDCD0E2BBD40E4003136CB1A3CCFD951FB2D8E9DE5415B55384B798B48C32469B56B54506917A7627332D8C4FD7A85897697186EBFCEBBE26D3C6D94D107198D32BAC82FCD0B081BFF7B43C4D8CF9786BE3221B39DB69080052494AF6E6A310BB6D8A50A45AD99DC00D0AAD604E4169612A8E75F96CB437EBE93645816D58F03BF46FEA654056FBABAE703A4899000C90F7F748200D39BD4FF897B19092B0BA000066B80E8357461289899CAF12055C66FEBE9E118E572C4494A438208A0F45632A1022503349AC6F8BE32B19399249BBBA4EB46DAA258D847BADAF69EADE38B19AA09DBD707825ABFE12D1E74C88B545354477A140A7CF3E83A47350CCA0796ED91F102C2378BD91B2A8820D9C0430C8096CC6C007279AF9984B6EAAC420D41DC51656027437981BC26ADA054E2EC7F2E24AF461733B014002A18EEFB2635C38700D0A89F872EACE26AF3B019F86B15383BFC72075F52EBE1F0CE3BFF5E3AE75AE38C4CA402304400714037E466C2802534AF14B0600101370D000705BE2E047FC0000B090800300FFB6212BD4ED9E936182D0A08CB04353DEC47192B753BE0975256A5945A507ED211FBFABFBDFD8B7E5E14B401438D2ED27B9D8E7E30651A8224007FF029525ACBEC13E7B2D6503DC54CAA43A1E35D7D264D0DB50F3789F04142A8902C1D6E0ED0080C561CD098EA1EDED08A04A8EBA2993001374E57D54528315752B83C7116C3725458CB05078123B8D8F3CB6E0976FB8F0A914A051B66CE31EDF5153AD9A011948859002F1A81CA6529E33155B64EAE03D2599AB5A501F05A72EAB90002CC2FA2BAE2E929CC7659A8099E80D6B9E79CA3C6E40B8FC25B18C6D689E819DBB335A7405E539405ECEAA41395B6D315146F14C910D40EC95B768B86204D44640B5A806AAF52AC2DDD423CC4B4E108F5844E6235D051E16A18131548023200C44065F1F6B5E5DEB2F2B75BD5D59755ABBA55CB04027445D19A4858A1C48F732E11169DB549AEC4BE6E3910C01EB3DBF85B3585D7E4DCAD92DFBBCEF54298CE02321D79BA0DAB0010D88105387DFFF664000066AC6CCFABF22F7401899A064D249404E84C90B989B5405C6FB534842FA37DAAE4679C9B902EBA4675EEE5DADF46E00251781D8F6DC5D6BCE23F1FC2194128B1316D08805038047FC0000B090800300FFFF72214DDEFFFFFF3336A9B1A2D1C81B54A1DA62A80B8F112FA2FF1FF13779A9C4DDF41DBF58B878CF6840F504F3FED85D1608DE4BDA7D0748C2711E387AFD2C656A7C078531B2A9B2D5A7F07E8671F9E7E41B3ED4F031EE923A47C8FF0D0A94305B24B1CEEA67EC5A3A74EA9B6F7285B3C68E0FB587FE1A30DBFBD5170532508F2D095022535C81BAF3C8068A2E476984FA49121FB15851DE70AA3EDAC7A4F285AC068F1F39BC124BAB7BCBEDB59A0D0A7EAB05AEE759E63F48C64EEAB770833C3352FBCE1E417534B457F411155A5694BBA5D190B8C934CE6B5DF88DAB9777303994614BDDA9A50CBC15E0AFEC1F3DA00DEBBC25304658E57ACDCCFE743CCF2D97096C43ABBA3EFDA47676B38B3C7E308D54B45A3B8D8470BF98EFCED3C9D5A375EE4566E39C6807A0072BA6F9F19E8B25EFEA994AFFE67886B80DAFE0FBF9A26768E3D4EA63974BA55CB83B15CBBDD95E3D3007C2009000009AA31113136E40D46506CD162A80AF9893DB1AFDFFECABE78BE1BB807B20B5E81EF71CC44F05FBA36F78B60957374E4DA34C8A7A9236A3EF391BC15CD9ED7957AB2422E89444BCBAE7B93F9D6E23D8FA2DDEE93FAE64FB7FB824389C1F8096FA407C88C3081FE7CB3FEBCE03728C752131676EA6B105B4681D75368D4F245EE81EACF386076278C95924087B56FC0E2AD55F77A6A44B28A9B25AF286BEBD27226A18C2E2BA296FD959452A32E9231ACF2CEE5C050478175B83696AFAE0118C5984F3F724A329DCE25230C9ABA45FA9EADB6E64C57E9609F22B4D3E8651E60DDF127A6010A3320BA3D0BFA22D921572043923A011330D0A003A5A67F67D3F2FB39FFDFF0D0ACF6763F88F838C001F3CFD9D523FCDFB3B02F19000007047FC0000B090800300FFF2216BD4FDBE8D0E620840EC8BC78BDFD139EED7968BC6B495922D9438B20F89CE72499D90F50FD31ABA4B912523B81ABD5BC3F1AE5F9FF34E75F97E68E4876E1AE381C96FE987C9F366AB724F3C634CA9AA4A1E27758C5D5EA32DF47634CE4B8EAC1DA6522172C6BEF6B78B6C21A968325B87FA4B8C75DFC9AF7E3AD024A6D45DF651B19D99133869232C0CA24BEF0DA6CA2133CC0277D02C0FBD2104C9A58C22A45E6E0520C1A55DEE48AA9B600D0AEA6BEE37AE66ACB8DDE4E53C23D36D4448C397749D19F2B1E68428D0A7C57EB91A4860B12C4D69769DF1D4C69CD4D04F9D72934AB58E51072C4B09925BD7DA02259693C4C0FC25218F6A78216AA094DB7AA3619D6F9E696E7B25510006A6DC24FD5BDB1348F57C63CAB3DF759729524CEF7E40014C5637D7AE61000322198D20A41142EC4C45431504650433AAD667339FAB5F7DC6B22D2AB8D456EEA5B63493B898F6DF0F70DD916C86A6D462BB14C15C776CF8EDA49868E510773CC69988D806E1870859E0B344AB8F1B6C3BFE417BF7E9884F2128F5F4DC3B63E1238E6312D76F2E8E576057340BD2E2A4ADD6484457609AA80209CD4DBE126F9A509DD011A9FA7DBD617DCF84B948BB7B616CEFDBE094B829D525FBCA7B2582A52421BAA94AC8A8A667836D98C5D5711A92FFE8B8F97433278764D5D5D597F7BE5013C0CD605C1C47FC0000B090800300FFC2210BD50DBA0D618431602A200B04C40656A92FD4DF152AAAEB591245A242AAED06E8F0672C5946157169B9AB6ACB4F1866BA4137814BE13F05A2411098969DCFF61E40B4BE944463971C375920B2BEBF3A52F0E2D1869C9A888FA900465D2C74FC76F45CA4CE0D0A140D0A695E04899CC9250D0A8F80C42290A86140C5B248EC8EB7392B6E14215BF0C9CA0341490623A1391B0D914C92E7395009A2E15134A7125C2557891339CE05826194D5D4EDAC6B192FF34B8600071E6E14E38CD3852EEEB194F2D963C817DF43D0C0E0FA9128E525AF7A10B9257719C014437538E585FC4A8F51E58128CCBE659EF01E420D0A1A6AFDDE784FA351F1AFD5009DF4FB669871E7BA8C8A2CD84E5DC355583B2A7A9F0FD2DE041D1BA072F00292D30563A2D4802108215EDB8E3F4D6F52AEB76D622D5A45CBCCAE01AC8707447199D2B8193647757C0014E4BC4E8DD9D251E0755086332FE1E122E318533919E1171A85F17DEC4B7F30EA40005ECF1322EF9705A2DADB354EF0D71653C09BA5771CF866F6B4692BFB53A20D0A36ED3BD63B5397E1AB1C76A6066610535CEC5857AA165F8A3BDE3AFE62C14540A8AFF1CAFD7351D7638E0D0AFE577D1B1753015C98CF3AD1588056C07EF11C47FC0000B090800300FFFF14210BD51DD612C2A238A04A1032F86DAF9E39F6BEEF61256A2492AE5A492E507266D8A485B1C91050CF618CD9D24CE9422880B92E969794BD6EE21043A9B997E8E5D02CAD01D5EDFCD8B871220B37D4CE28394314B723411472F6DA23E15CA10D66D7147D38C0B31AF672573349490915B6D97078FB5216D535437AFA64A678C4507414C17AE5E54217F0928AE120AA4785CF3F2AFE23CE722FEC6DAF8231ECE7B282285F116A70137C711FA2C90995AE22233874438CA69F0827AC2318B4DB7DD3825F4DCD72EFCA13BEECA7B33B500C24F86B032995348674CDE93D20D28DC69B44836A2268C6383600AD36D5EC1C7BEC2C0513E4629551BA966ADF93A8F5685BEEAF417384CBA8556AA4C9C797361D1FF6F65CAF91AA2A7180000D0AECFCF8A27CB9FCBB33CA6E75A45F9A5D5566D68ED32A7169E09938465DC13D5FF9F6F1C635A8AF3F648535B98D4154A08C4C15080982A2032FE3337AED5ED399CD5E5D719A8BAB9BE2173A6034F9A257E49449860F1F3234D1E7A7C1FA3154C6FC7C53088642EC3B6454AAE6AFB85BA6A3437CBE2624C9CDC9D46A9C00CAC1300557BF14621033ED6CCE4F846AB973EBF9F216D31DFC2A6205E3B65BF0EC84AFBF58E701778C6E78EF8004EE98EBEF8ADEFF856C00089D7AAD2B65E220AFE016A1473108E0CE9461F75AEAE24B9753B810A8C348A9870D7373F8FB3AFEE07C3521BFCCF7E51132B76548165BFAB62A73300FBF40003847FC0000B090800300FFFF1F210BD51DC6890761C0E84A281819D5E7377DB9F3795855CBA5DDB24BB9217C503B377F9A2BEC89E1CFC791C41158ED857519F6B98E872BBEA9B614500C6FCF7E468CB64F31AE089CDE696E45B29D9F3874F083E36F6AA0CA5F849622858B8F4153CB0721ABACB0FCF4B0A209E092CB70A10D0AC689F786783E85E022E8E02D4CC2AC1AE0984E701926788007936A163026CEC02DA74C159B3AB81003236120A2630E9E85980966AF95D712FAEBCA35EF9F4918972FF646A17B757FB28F2A67007C26B281C925832AE31703971AC6C931F10CD6DACABB61D49A8BF071B4947D952A33789A89A54C5757C1DF155B58C62BE42982A928E8ACE39C75DA8B0D2F0B518C7D975D846EC28236543C505AFB3D7ECA81A80000673F2EBE8DECEDFDFACAD8AB7AE33B43B2F05E722499D77A4D223A2DF7DC42437AC0B03D271F05379CE739CEA7B4B1A82C210D894C8452889828103BDB59BBBEF3BF699372A389556E1BB6AE495E3DBCE02863569A20106734826201CEDD6DBF328E8EA8E13833AFA5CE678A43ECACAE056F438204DE3F666ACC594CF22AC0A0238671CB13CA31BBEF5D1E38EC8CEFA372BA8EF29CB1EA825590EEC95BE0AB98BC4DFBFA60C7DFD18CA5FD6F1D94832B9D4A2F46EB40E777B2C321FC8BE45BBD477B3BFE94D7BFABB61DDDE62B2F679F007BB8ED7ACFD9D5C7D935F1E9E3FE9F1800AFEDF1FFAFE5F672FF3DE2FE50E7B83AFA400004B8275F20987F35768CCDAEE5D92358534EF57847FC0000B090800300FFE9210BD525A68D6181D098B4180B0E02C451308C20679BA6FCFBD73E655EF6B8B2692A4B092F554152C8CC9205E29FA1F9D772C440C559DA53E5DFD1398ACB4BE64512620F63F0F92B20EEC15947AB0E2032125AE3D054070D0A7FF21BED4335F82519E41E12FF8F0051C5B625EFCA1005A8AEBEFF8DE407E4DB9655E7ECB95ED8C7CB496524916480007916D9278CC3EBC697721DFF0D0869C9A008D1326C2993079D09DCB1D3D0AB84EF3ED249260EDBB1F2C37F7F6D7A3BBB6E69EF7291A667BAAAD6B918D4A92544E23A89B38AA35E781A4BEA47FAEFD482A873DD4D7CE903BB5C9B7826170537DD2C9D293450B2E49701CCE49E9CFE1DDF8D98C4700B9808559CD6F7BE9E000D01A4B1F4FA8B8787C3FCF282FAD6CCDC960542EB9CF77D5D75DC63F7AF27A51920A741D9A156250D0A115402408880CEA5CBBF9DEFCDE71CF3347189C52AEB8CB2BE302116B6FAA464C548A09BF3AC27F9AC0093C55F0004D671C4A53924BB758CF48C9F302A31E1B0E340339630896052D4E6D2C418E38203E952003C4B7F9635A743DE4D2C284D206EA7E25CEB9AAAD095F1306F11D7F2FE5323ABBE05EFBE031D2D467BF711A847074702B60B910C639FB30BC600066000DF8F6856EEE57D3C2B35BDCEBBFAD20365E9598E8854AB6361A0790B5FE6DB3F2DA27493AE106C01C0 

Файл ввода также здесь: http://filebin.ca/3DACc6lkf882/input.txt

Edit 2:

Вот пример из MFTrace с некоторыми дополнительными следами положить там:

23816,3D70 10:43:31.09829 CKernel32ExportDetours::OutputDebugStringA @ ----------------------------------ProcessInput---------------------------------- 
23816,3D70 10:43:31.09832 CMFTransformDetours::ProcessInput @00000229F1932698 Stream ID 0, Sample @00000229F19D2160, Time 0ms, Duration 0ms, Buffers 1, Size 640B, 
23816,3D70 10:43:31.09832 CMFTransformDetours::ProcessMessage @00000229F1932698 Message type=0x10000000 MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, param=00000000 
23816,3D70 10:43:31.09832 CKernel32ExportDetours::OutputDebugStringA @ GetOutputStatus says MFT_OUTPUT_STATUS_SAMPLE_READY 
23816,3D70 10:43:31.09833 CKernel32ExportDetours::OutputDebugStringA @ GetInputStatus says does NOT accept data 
23816,3D70 10:43:31.09834 CKernel32ExportDetours::OutputDebugStringA @ ----------------------------------ProcessOutput---------------------------------- 
23816,3D70 10:43:31.09834 CMFTransformDetours::ProcessMessage @00000229F1932698 Message type=0x10000000 MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, param=00000000 
23816,3D70 10:43:31.09835 CMFTransformDetours::ProcessOutput @00000229F1932698 failed hr=0xC00D6D72 MF_E_TRANSFORM_NEED_MORE_INPUT 
23816,3D70 10:43:31.09835 CKernel32ExportDetours::OutputDebugStringA @ ProcessOutput needs more input 
23816,3D70 10:43:31.09836 CKernel32ExportDetours::OutputDebugStringA @ GetInputStatus says MFT_INPUT_STATUS_ACCEPT_DATA 
+1

Что такое декодер? Они также должны быть записаны в спецификацию, если они вводят недопустимое состояние, а затем преобразование в целом. То есть у вас может быть глючный декодер. – Ben

+0

Используйте правильные языковые теги! Это C++, а не C. – Olaf

+5

@ Олаф, на чем вы основываете это на C++? Это чисто C. –

ответ

2

Как уже упоминалось в комментариях, потратив немного времени на ваш код, я смог воспроизвести описанное вами поведение. Однако это также верно, когда я использовал произвольные файлы для ввода. По общему признанию, я был удивлен, увидев, что декодер сообщил о состоянии MFT_OUTPUT_STATUS_SAMPLE_READY. Поэтому я согласен с Бен в отношении действительных данных AAC.

Вместо анализа проб вручную, возможно, вы могли бы просто использовать IMFSourceReader предоставить образцы для вас, который будет выглядеть примерно следующим образом:

проверки ошибок опущено для краткости

HRESULT configure_reader(IMFSourceReader *reader, IMFMediaType **resultingMediaType) 
{ 
    HRESULT hr = S_OK; 
    IMFMediaType *pcmMediaType = NULL; 
    IMFMediaType *partialType = NULL; 

    // Create a partial media type that specifies uncompressed PCM audio. 
    hr = MFCreateMediaType(&partialType); 
    hr = partialType->lpVtbl->SetGUID(partialType, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); 
    hr = partialType->lpVtbl->SetGUID(partialType, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); 

    // Set this type on the source reader. The source reader will load the necessary decoder. 
    hr = reader->lpVtbl->SetCurrentMediaType(reader, 
              (DWORD) MF_SOURCE_READER_FIRST_AUDIO_STREAM, 
              NULL, 
              partialType); 

    // Get the complete uncompressed format. 
    hr = reader->lpVtbl->GetCurrentMediaType(reader, 
              (DWORD) MF_SOURCE_READER_FIRST_AUDIO_STREAM, 
              &pcmMediaType); 

    // Ensure the stream is selected. 
    hr = reader->lpVtbl->SetStreamSelection(reader, 
              (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 
              TRUE); 

    if (resultingMediaType) 
    { 
     *resultingMediaType = pcmMediaType; 
     (*resultingMediaType)->lpVtbl->AddRef(*resultingMediaType); 
    } 

    (void) pcmMediaType->lpVtbl->Release(pcmMediaType); 
    (void) partialType->lpVtbl->Release(partialType); 

    return hr; 
} 

// . . . . . . . . . . . . . . . . . . . . . . 

void process_aac_audio() 
{ 
    HRESULT hr = S_OK; 
    IMFSourceReader *reader = NULL; 
    hr = MFCreateSourceReaderFromURL(L"input.aac", 
            NULL, 
            &reader); 

    IMFMediaType *pcm_media_type = NULL; 
    hr = configure_reader(reader, &pcm_media_type); 
    assert(pcm_media_type); 

    DWORD total_bytes = 0; 
    DWORD buffer_length = 0; 
    BYTE *audioData = NULL; 

    IMFSample *sample = NULL; 
    IMFMediaBuffer *mediaBuffer = NULL; 

    while (1) 
    { 
     DWORD dwFlags = 0; 
     hr = reader->lpVtbl->ReadSample(reader, 
             (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 
             0, 
             NULL, 
             &dwFlags, 
             NULL, 
             &sample); 

     if (FAILED(hr)) { break; } 
     if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) 
     { 
      printf("Type change \n"); 
      // TODO: 
     } 

     if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM) 
     { 
      printf("End of input file. \n"); 
      break; 
     } 

     if (sample == NULL) 
     { 
      printf("No sample \n"); 
      continue; 
     } 

     hr = sample->lpVtbl->ConvertToContiguousBuffer(sample, &mediaBuffer); 
     hr = mediaBuffer->lpVtbl->Lock(mediaBuffer, &audioData, NULL, &buffer_length); 
     // TODO: process buffer 
     hr = mediaBuffer->lpVtbl->Unlock(mediaBuffer); 
     audioData = NULL; 

     total_bytes += buffer_length; // <-- update running total 
     (void) sample->lpVtbl->Release(sample); 
     (void) mediaBuffer->lpVtbl->Release(mediaBuffer); 
    } 

    if (sample) 
     (void) sample->lpVtbl->Release(sample); 

    if (mediaBuffer) 
     (void) mediaBuffer->lpVtbl->Release(mediaBuffer); 
} 

В в этом случае декодер был загружен и использовался для того, чтобы вы напрямую доставляли образцы PCM. Файл, который вы предоставили (input.txt), не удался, однако другие достоверные файлы aac работали нормально.

Возможно, вы имеете дело с потоком, а не с файлом. В этой ситуации, создать источник с кодом, подобным следующем:

HRESULT create_media_source(IMFByteStream *byteStream, IMFMediaSource **ppSource) 
{ 
    MF_OBJECT_TYPE objectType = MF_OBJECT_INVALID; 
    IMFSourceResolver* sourceResolver = NULL; 
    IUnknown* source = NULL; 

    HRESULT hr = MFCreateSourceResolver(&sourceResolver); 
    hr = sourceResolver->lpVtbl->CreateObjectFromByteStream(sourceResolver, 
                  byteStream, 
                  NULL, // URL 
                  MF_RESOLUTION_MEDIASOURCE, 
                  NULL, // IPropertyStore 
                  &objectType, 
                  &source); 

    // get the IMFMediaSource interface from the media source. 
    hr = source->lpVtbl->QueryInterface(source, &IID_IMFMediaSource, ppSource); 
    (void) sourceResolver->lpVtbl->Release(sourceResolver); 
    (void) source->lpVtbl->Release(source); 
    return hr; 
} 

Однако, обратите внимание, что CreateObjectFromByteStream нужен способ, чтобы определить тип содержимого. Вы можете либо реализовать IMFAttributes [конкретно GetAllocatedString] в вашем байт-потоке, либо передать URL-адрес

+0

Спасибо @Jeff! Хорошо из вас, чтобы проверить с произвольными данными. Я получил тот же результат. Таким образом, кажется, что GetOutputStatus нельзя доверять этому экземпляру. Даже с проверкой ошибок 'hr' никогда не было ничего, кроме' S_OK' с неинициализированными данными. Поэтому, я думаю, я не могу доверять MF, чтобы сказать мне, есть ли у меня какие-либо проблемы в моих входных данных. @Ben может быть прав в отношении ошибок AAC. Трудно сравнивать данные с другими источниками, так как мне нужно будет найти правильные данные AAC LATM и иметь возможность извлекать интересные биты из файла (например, удалить заголовки файлов). –

+0

Источник не является файлом, но я мог бы писать входы, которые я получаю в потоке. Попробуй. Но почему поток лучше в этом случае? Меньше шансов на то, что я что-то сделаю неправильно? Или есть другие неотъемлемые преимущества в использовании потока или SourceReader? –

+0

Отмечено как принятый ответ, так как вы можете показать, что 'GetOutputStatus' создает' MFT_OUTPUT_STATUS_SAMPLE_READY' даже для явно ошибочного ввода и, следовательно, ему не следует доверять (по крайней мере, в этом случае), и проблема очень хорошо может быть моими входными данными. –

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

  • Нет связанных вопросов^_^