2015-02-10 61 views
1

我試圖將一個連續的緩衝區分成3個字節的通道(RGB)。這是我的工作流程acutal得到緩衝充滿圖像:RGB通道中分離連續緩衝區(IMFMediaBuffer)

  1. 設置一個源讀取(MFVideoFormat_RGB32)
  2. 接收視頻格式信息
  3. 閱讀第一圖像,並轉換爲連續的緩衝區...

除此之外,這裏是代碼:

HRESULT hr = S_OK; 
    IMFAttributes *attributes = NULL; 
    SafeRelease(&_sourcereader); 

    hr = MFCreateAttributes(&attributes, 1); 
    if (FAILED(hr)) { 
// TODO: set error 
return false; 
    } 

    hr = attributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, true); 
    if (FAILED(hr)) { 
    // TODO: set error 
    return false; 
    } 

    // conversion from qstring to const wchar* 
    const WCHAR* wfilename = filename.toStdWString().c_str(); 

    // create source reader from file with attributes 
    hr = MFCreateSourceReaderFromURL(wfilename, attributes, &_sourcereader); 
    if (FAILED(hr)) { 
     // TODO: set error 
     return false; 
    } 

    // configure sourcereader for progressive RGB32 frames 
    IMFMediaType *mediatype = NULL; 
    hr = MFCreateMediaType(&mediatype); 
    if (SUCCEEDED(hr)) 
    { 
    hr = mediatype->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); 
    } 

    if (SUCCEEDED(hr)) 
    { 
    hr = mediatype->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); 
    } 

    if (SUCCEEDED(hr)) 
    { 
    hr = _sourcereader->SetCurrentMediaType(
     (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 
     NULL, mediatype); 
    } 

    // Ensure the stream is selected. 
    if (SUCCEEDED(hr)) 
    { 
    hr = _sourcereader->SetStreamSelection(
     (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE); 
    } 

    if (FAILED(hr)) { 
    // TODO: Error log for failed configuration 
    std::cout << "(ConfigureSourceReader) Configuration failed" << std::endl; 
    return false; 
    } 
    //------------------------------------------------------------------ 
    //---------------------- Get Video Format Infos -------------------- 
    //------------------------------------------------------------------ 
    GUID subtype = { 0 }; 
    // Get the media type from the stream. 
    hr = _sourcereader->GetCurrentMediaType(
    (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, &mediatype); 

    // Make sure it is a video format. 
    hr = mediatype->GetGUID(MF_MT_SUBTYPE, &subtype); 
    if (subtype != MFVideoFormat_RGB32) 
    { 
    hr = E_UNEXPECTED; 
    // TODO: Error log message 
    SafeRelease(&mediatype); 
    return false; 
    } 

    //------------------------------------------------------------------ 
    // Get the width and height 
    UINT32 width = 0, height = 0; 
    hr = MFGetAttributeSize(mediatype, MF_MT_FRAME_SIZE, &width, &height); 
    if (FAILED(hr)) 
    { 
    // TODO: Error log message 
    SafeRelease(&mediatype); 
    return false; 
    } 
    //assign dimensions to VideoInfo 
    _videoinfo.imageHeight = height; _videoinfo.imageWidth = width; 
    //std::cout << "(GetVideoFormat) width: " << width << ", height: " << height << std::endl; 

    //------------------------------------------------------------------ 
    //get framerate 
    UINT32 framerate_num = 0, framerate_denom = 0; 
    hr = MFGetAttributeRatio(mediatype, MF_MT_FRAME_RATE, &framerate_num, &framerate_denom); 
    if (FAILED(hr)) 
    { 
    // TODO: Error log message 
    SafeRelease(&mediatype); 
    return false; 
    } 
    //set frame rate in struct 
    _videoinfo.fps = framerate_num/framerate_denom; // TODO: check for valid fps 24,25,30 ... 

    //------------------------------------------------------------------ 
    // Get length 
    LONGLONG length = 0; 
    PROPVARIANT var; 
    PropVariantInit(&var); 
    hr = _sourcereader->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, 
MF_PD_DURATION, 
&var 
); 
    if (SUCCEEDED(hr)) { 
    assert(var.vt == VT_UI8); 
    length = var.hVal.QuadPart; 
    } else { 
    // TODO : erro log msg 
    return false; 
    } 

    //Get total framenumber and length: save to info struct 
    _videoinfo.noofFrames = length/10000000 * this->getFrameRate(); // incl. conversion from nano sec to sec 
    _videoinfo.duration = length; 

    //------------------------------------------------------------------ 
    // Get the stride to find out if the bitmap is top-down or bottom-up. 
    LONG lStride = 0; 
    lStride = (LONG)MFGetAttributeUINT32(mediatype, MF_MT_DEFAULT_STRIDE, 1); 
    _videoinfo.stride = lStride; 
    _videoinfo.bTopDown = (lStride > 0); 
    //------------------------------------------------------------------ 

    SafeRelease(&mediatype); 
    // return true and flag if initialization went well 
    _bInitialized = true; 
    return true; 

我電話後一個函數來讀取一個單幀(在第一個時刻)。

HRESULT hr = S_OK; 
    IMFSample *pSample = NULL; 
    IMFMediaBuffer *buffer = NULL; 
    DWORD streamIndex, flags; 
    LONGLONG llTimeStamp; 
    // Read Sample (RGB32) 
    hr = _sourcereader->ReadSample (
    (DWORD) MF_SOURCE_READER_FIRST_VIDEO_STREAM, 
    0, 
    &streamIndex, 
    &flags, 
    &llTimeStamp, 
    &pSample); 
    if (FAILED (hr)) { 
    // TODO handle fail case 
    } 
    //convert sample data to buffer 
    hr = pSample->ConvertToContiguousBuffer(&buffer); 
    if (FAILED (hr)) { 
     // TODO handle fail case 
     }  

我知道,通過調用函數buffer->Lock(&pixels, NULL, &nPixels)我可以得到存儲在pixels的字節流。在我的情況下,我創建一個具有給定高度和寬度的自定義圖像(來自SourceReader; [first function])。從空的圖像我可以得到一個空的顏色矩陣,必須填寫以下功能:Color (byte red, byte green, byte blue)

我不知道如何將我的RGB32 BYTE數組拆分成單個通道來填充我的圖像?也許這是一個愚蠢的問題,但我是比較新的這方面...

回答

1

對於RGB32字節格式爲:

R =紅色 G =綠 B =藍 A =透明度

RGBARGBARGBA ...

一個非常簡單的提取通道的僞代碼示例如下所示。

for (int row = 0; row < height; row++) { 
    for (int col = 0; col < stride; col += 4) { 
     redBuf[rIndex++] = sample[row * stride + col]; 
     greenBuf[gIndex++] = sample[row * stride + col + 1]; 
     blueBuf[bIndex++] = sample[row * stride + col + 2]; 
     transparencyBuf[tIndex++] = sample[row * stride + col + 3]; 
    } 
}