2015-02-10 67 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]; 
    } 
}