2013-05-15 9 views
0
내가 PCM으로, (live555하는 RTP 라이브러리에서받은)는 HE-AAC 오디오 스트림을 변환하는 미디어 재단 변환을 사용하려고 해요

(재생할 waveOutXxx Win32 API를 통해). 그러나 현재는 미리 녹음 된 패킷을 처리하고 있습니다.IMFTransform :: ProcessOutput는 HE-AAC에 대한 MF_E_TRANSFORM_STREAM_CHANGE을 반환 -> PCM

IMFTransform::ProcessOutput으로 전화하면 MF_E_TRANSFORM_STREAM_CHANGE가 반환됩니다. _MFT_PROCESS_OUTPUT_STATUS에 대한 설명서에서 올바른 스트림 유형을 결정하고 IMFTransform::SetOutputType으로 다시 전화해야한다는 것을 나타냅니다.

그러나 SetOutputType에 대한 올바른 매개 변수를 결정할 수 없습니다. 참고로

, 스트림의 RTSP 설명 내 코드는

m=audio 0 RTP/AVP 97 
a=rtpmap:97 mpeg4-generic/16000/1 
a=fmtp:97 streamtype=5; profile-level-id=15; mode=AAC-hbr; config=1408; 
    sizeLength=13; indexLength=3; indexDeltaLength=3; profile=1; bitrate=32000; 

이다 (길이 죄송합니다, 간결 제거 오류 처리)

static IMFMediaType *s_inputMediaType; 
static IMFMediaType *s_outputMediaType; 
static IMFTransform *s_transform; 
static DWORD   s_outputSampleSize; 

static void InitMFT() 
{ 
    HRESULT res; 
    res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // probably should use threaded in production 
#if 0 
    res = MFCreateMediaType(&inputMediaType); 
    res = MFCreateMediaType(&outputMediaType); 

    res = inputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); 
    res = inputMediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); 
    res = inputMediaType->SetUINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 15); 
    res = inputMediaType->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 1); // Audio Data Transport Stream 

    res = outputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); 
    res = outputMediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); 
    res = outputMediaType->SetUINT32(MF_MT_SAMPLE_SIZE, 2); 
    res = outputMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, 2); 
    res = outputMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8 * 2); 
    res = outputMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 8000); 
    res = outputMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 8000 * 2 *2); 
#endif 
    CLSID *clsids = NULL; 
    UINT32 clsidCount=0; 

    MFT_REGISTER_TYPE_INFO inputType = {MFMediaType_Audio, MEDIASUBTYPE_MPEG_HEAAC}; // WAVE_FORMAT_MPEG_HEAAC can't be searched for 
    MFT_REGISTER_TYPE_INFO outputType = {MFMediaType_Audio, WAVE_FORMAT_PCM};   // MEDIASUBTYPE_PCM doesn't exist (but can be search for if created) 

    res = MFTEnum(MFT_CATEGORY_AUDIO_DECODER, 0, 
        &inputType, 
        NULL, /* &outputType, */ // search fails if outputType is not NULL 
        NULL, &clsids, &clsidCount); 

    ListTranscoders(clsids, clsidCount); 

    res = CoCreateInstance(clsids[0], NULL, CLSCTX_ALL, IID_PPV_ARGS(&s_transform)); 

    /* GetStreamCount and GetStreamIDs always return E_NOTIMPL */ 
    DWORD inputCount; 
    DWORD outputCount; 
    res = s_transform->GetStreamCount(&inputCount, &outputCount); 

    DWORD inputIDs[16]; 
    DWORD outputIDs[16]; 

    res = s_transform->GetStreamIDs(inputCount, inputIDs, 
            outputCount, outputIDs); 

    res = s_transform->GetInputAvailableType(0, 0, &s_inputMediaType); 
    res = s_transform->SetInputType(0, s_inputMediaType, 0); 

    res = s_transform->GetOutputAvailableType(0, 1, &s_outputMediaType); // 1 here is because PCM outputer is the second output offered in ListTranscoders 
    res = s_transform->SetOutputType(0, s_outputMediaType, 0); 

    MFT_OUTPUT_STREAM_INFO outputStreamInfo; 
    res = s_transform->GetOutputStreamInfo(0, &outputStreamInfo); 
    s_outputSampleSize = outputStreamInfo.cbSize; 

    GUID inputCodec; 
    GUID outputCodec; 

    res = s_inputMediaType ->GetGUID(MF_MT_SUBTYPE, &inputCodec); 
    res = s_outputMediaType->GetGUID(MF_MT_SUBTYPE, &outputCodec); 

    CoTaskMemFree(clsids); 
} 

/* 
http://msdn.microsoft.com/en-us/library/bb530106%28v=vs.85%29.aspx 
http://msdn.microsoft.com/en-us/library/bb530123%28v=vs.85%29.aspx 
*/ 

void ProcessData(const void* inputData, DWORD inputSize, 
         void* outputData, DWORD &outputSize) 
{ 
    HRESULT   res; 
    IMFSample  *pSample; 
    IMFMediaBuffer *pBuffer; 
    BYTE *pData = NULL; 

    /**** Create an input sample buffer, from the supplied data ****/ 
    res = MFCreateSample(&pSample); 
    res = MFCreateMemoryBuffer(inputSize, &pBuffer); 
    res = pBuffer->Lock(&pData, NULL, NULL); 
    memcpy_s(pData, inputSize, inputData, inputSize); 
    res = pBuffer->SetCurrentLength(inputSize); 
    res = pBuffer->Unlock(); 
    res = pSample->AddBuffer(pBuffer); 

    /**** Create output buffer ****/ 
    IMFSample  *pOutputSample; 
    IMFMediaBuffer *pOutputBuffer; 

    res = MFCreateSample(&pOutputSample); 
    res = MFCreateMemoryBuffer(s_outputSampleSize, &pOutputBuffer); 
    res = pOutputSample->AddBuffer(pOutputBuffer); 

    MFT_OUTPUT_DATA_BUFFER outputDataBuffer; // can be an array 
    outputDataBuffer.dwStreamID=0; 
    outputDataBuffer.pSample=pOutputSample; 
    outputDataBuffer.dwStatus=0; 
    outputDataBuffer.pEvents = NULL; 

    DWORD outputStatus=0; 

    /*** Process the data, and get it back ****/ 
    res = s_transform->ProcessInput(0, pSample, 0); 
    res = s_transform->ProcessOutput(MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER, 
            1, &outputDataBuffer, &outputStatus); 


    if (res==MF_E_TRANSFORM_STREAM_CHANGE) 
    { 
     // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815%28v=vs.85%29.aspx 
     // indicates that the output always changes 
     // but not how to handle it 

     /* GetStreamCount and GetStreamIDs always return E_NOTIMPL */ 

     DWORD inputCount; 
     DWORD outputCount; 
     res = s_transform->GetStreamCount(&inputCount, &outputCount); 

     DWORD inputIDs[16]; 
     DWORD outputIDs[16]; 

     res = s_transform->GetStreamIDs(inputCount, inputIDs, 
             outputCount, outputIDs); 

     res = s_transform->GetInputAvailableType(0, 0, &s_inputMediaType); 
     res = s_transform->SetInputType(0, s_inputMediaType, 0); 

     res = s_transform->GetOutputAvailableType(0, 1, &s_outputMediaType); // 1 here is because PCM outputer is the second output offered 
     res = s_transform->SetOutputType(0, s_outputMediaType, 0); 
    } 

    /**** Extract converted audio from the sample ****/ 
    DWORD dwNumOutputBuffers, i; 
    res = outputDataBuffer.pSample->GetBufferCount(&dwNumOutputBuffers); 

    for(i=0; i<dwNumOutputBuffers; i++) 
    { 
     IMFMediaBuffer *outputBuffer; 
     res = outputDataBuffer.pSample->GetBufferByIndex(i, &outputBuffer); 
     BYTE *outData; 
     DWORD outDataLen = 0; 

     res = outputBuffer->Lock(&outData, NULL, &outDataLen); 

     memcpy(outputBuffer, outData, outDataLen); 

     res = outputBuffer->Unlock(); 
    } 

    /* TODO: Release any neccessery references */ 
} 
+0

'MF_E_TRANSFORM_STREAM_CHANGE'을 얻은 후에'SetInputType'을하지 말아야한다고 가정합니다. MSDN은 당신이 그것을해야한다고 제안하지 않습니다. 대신 입력 미디어 유형을 이미 설정하고 내부 MFT 상태를 그대로 유지 한 상태에서 사용 가능한 것으로 알리는 출력 유형을 확인하십시오. 샘플링 속도 나 채널 수를 바꿔야하므로 출력을 변경하길 원합니다. –

답변

0

나는 매우 비슷한 일을 해요 맡은 일. 당신은, 그렇지 않으면 다음 processinput는 당신에게 당신은 또한 디코더를 플러시합니다

MF_E_TRANSFORM_TYPE_NOT_SET을 줄 것이다, Set를 출력 유형을 수행해야합니다 그렇지 않으면 다음 프로세스 입력 MF_E_NOTACCEPTING를 반환합니다. 코드에서 근무, 내가 테스트를 위해이 줄

res = s_transform->GetOutputAvailableType(0, 1, &s_outputMediaType); // 1 here is because PCM outputer is the second output offered 
    GUID outputCodec; 
    res = s_outputMediaType->GetGUID(MF_MT_SUBTYPE, &outputCodec); 
    if (outputCodec == MFAudioFormat_PCM){ 
     printf("\nDecoder Output is expecting pcm format");     
     res = s_transform->SetOutputType(0, s_outputMediaType, 0);//setting the type again 

    } 
    if (outputCodec == MFAudioFormat_Float){ 
     printf("\nDecoder Output is expecting float pcm format"); 
    } 
    s_transform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH,NULL);   

    return res;//no output coming get another input to process. 

후 추가 설정 입력 방식의 고해상도를 제거하여 작동하도록있어, 내가 좋은 파일에 소스 리더에서 온 샘플을 사용하고 있었다. 'quiet'를 포함하는 일부 패킷은 짧고 모두 0 일 수 있으므로 많은 패킷을 재생해야합니다.

또한 따라서 url http://msdn.microsoft.com/en-us/library/windows/desktop/ff485864%28v=vs.85%29.aspx은 출력을 구성하는 방법을 올바르게 지정합니다. 그것은 매우 유용합니다.

당신은 출력를 포맷하는 방법을 입력 매체 유형에 대한 특성 (MF_MT_AUDIO_BITS_PER_SAMPLE)의 일부는 디코더에게 통지 밀접하게 http://msdn.microsoft.com/en-us/library/windows/desktop/dd742784%28v=vs.85%29.aspx 수 읽기. 원하는 입출력을보다 완벽하게 지정할 수 있으면 스트림 변경을 피할 수 있습니다. 첫 번째 샘플은 대신 MF_E_TRANSFORM_NEED_MORE_INPUT 일 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 그러나 더 이상 해당 코드를 사용하지 않습니다. 이 지역에 머물러있는 다음 사람에게 유용 할 수 있습니다. – CSM