Media Foundation MFTransform для преобразования MFSample из «MJPG» в «YUY2» или «RGB24» - PullRequest
0 голосов
/ 02 февраля 2012

Кто-нибудь знает, какой MFTransform я должен использовать для преобразования MFSP MJPG в YUY2 или RGB24?

Любой совет будет очень признателен. Спасибо

1 Ответ

2 голосов
/ 13 марта 2012

Поскольку число посещений этого поста было заметно, я собираюсь ответить на свой вопрос.

Хитрость заключается в том, чтобы перечислить все преобразования между MJPG и YUY2, поскольку, по-видимому, прямой трансформации нетмежду MJPG и RGB32.Чтобы преобразовать изображение между YUY2 и RBG32, используйте преобразователь цвета DSP: http://msdn.microsoft.com/en-us/library/windows/desktop/ff819079%28v=vs.85%29.aspx

. Я использую этот метод для выборки образцов с веб-камеры 1080p, а затем декодирования MJPG в YUY2, а затем декодирования YUY2 в RGB32 и загрузкиOpenGL RGB32 текстуру, а затем ее отображение.Это делается со скоростью 30 кадров в секунду с Core 2 Duo и Radeon HD5650.При выполнении вычисления с изображениями с помощью OpenCL (несколько сверток) оно уменьшается до 15 кадров в секунду.

Код для создания преобразования MJPG в YUY2:

MFT_REGISTER_TYPE_INFO inputFilter = { MFMediaType_Video, MFVideoFormat_MJPG };
MFT_REGISTER_TYPE_INFO outputFilter = { MFMediaType_Video, MFVideoFormat_YUY2 };
UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER;

HRESULT r = MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, unFlags, &inputFilter, &outputFilter, &ppActivate, &numDecodersMJPG);
if (FAILED(r)) throw gcnew Exception("");
if (numDecodersMJPG < 1) throw gcnew Exception("");

// Activate transform
IMFTransform *pMPEG4 = NULL;
r = ppActivate[0]->ActivateObject(__uuidof(IMFTransform), (void**)&pMPEG4);
if (FAILED(r)) throw gcnew Exception("No se pudo crear el decodificador MJPG.");

Следующая часть заключается в использованиидекодер для декодирования сжатого семпла (сначала из MJPG в YUY2, а затем из YUY2 в RGB32).Это объясняется в: http://msdn.microsoft.com/en-us/library/windows/desktop/aa965264%28v=vs.85%29.aspx

Или:

        MFT_OUTPUT_STREAM_INFO osi;

    HRESULT r = pDecoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
    if (FAILED(r)) throw gcnew Exception("");

    r = pDecoder->ProcessInput(0, sample, 0);
    if (FAILED(r)) throw gcnew Exception("");

    r = pDecoder->GetOutputStreamInfo(0, &osi);
    if (FAILED(r)) throw gcnew Exception("");

    DWORD status = 0;
    r = pDecoder->GetOutputStatus(&status);
    if (FAILED(r)) throw gcnew Exception("");
    if (status = MFT_OUTPUT_STATUS_SAMPLE_READY) {
    }

    // Use your own CreateSample function
    IMFSample *outputSample = CreateSample(osi.cbSize);

    DWORD outStatus = 0;
    MFT_OUTPUT_DATA_BUFFER odf;
    odf.dwStreamID = 0;
    odf.pSample = outputSample;
    odf.dwStatus = 0;
    odf.pEvents = NULL;
    r = pDecoder->ProcessOutput(0, 1, &odf, &outStatus);
    if (r != MF_E_TRANSFORM_NEED_MORE_INPUT && FAILED(r)) {
        outputSample->Release();
        throw gcnew Exception("");
    }

    r = pDecoder->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0);
    if (FAILED(r)) {
        outputSample->Release();
        throw gcnew Exception("");
    }

    r = pDecoder->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
    if (FAILED(r)) {
        outputSample->Release();
        throw gcnew Exception("");
    }

    return outputSample;
...