2011-06-07 18 views
0

我正在使用專門的網絡流式傳輸攝像機,並試圖將視頻流保存在文件中。此時代碼將視頻保存起來,但採用了一種褪色的RGB格式,它將顏色固定,然後使用VFW進行保存。我是否正確地做這件事,這應該創建與不匹配的顏色AVI或我在BITMAPINFOHEADER區域設置錯誤嗎?我錯誤地設置了用於保存C++ vfw文件的avi信息?

void PvSbProUISampleDlg::OnBnClickedSave() 
{ 
// TODO: Add your control notification handler code here 

CString StringValue; 
mMovieSave.GetWindowTextW(StringValue); 

if (StringValue == L"Save") 
{ 
    CString codecValue; 
    mMovieCodecSelected.GetWindowTextW(codecValue); 
    if (codecValue.IsEmpty()){ 
     MessageBox(L"Please select a codec before saving to file", 
        L"Select Codec!", 
        MB_OK | MB_ICONEXCLAMATION); 
     return; 
    } 

    CString fileNameValue; 
    mFileName.GetWindowTextW(fileNameValue); 
    if (fileNameValue.IsEmpty()){ 
     MessageBox(L"Please select a file location", 
        L"Select File!", 
        MB_OK | MB_ICONEXCLAMATION); 
     return; 
    } 


    if (!StartMovie()) 
     return; 

    mSavingMovie = true; 
    mMovieSave.SetWindowTextW(L"Saving"); 
} 
else 
{ 
    mVideoMutex.Lock(); 
    PvResult aResult = mVideoCompressor->Stop(); 
    mSavingMovie = false; 
    mVideoMutex.Unlock(); 
    if (!aResult.IsOK()) 
    { 
     MessageBox(mLocation, 
        L"Can't Stop Video Compressor!", 
        MB_OK | MB_ICONEXCLAMATION); 
     return; 
    } 

    mMovieSave.SetWindowTextW(L"Save"); 
} 

} 

我設置了視頻流併爲我的編解碼器選擇了未壓縮的AVI。我點擊「保存」按鈕,然後調用下面

bool PvSbProUISampleDlg::StartMovie() 
{ 
if (!mDevice.IsConnected()) 
{ 
    MessageBox(L"Need to connect to device", 
       L"Cannot start Video Compressor!", 
       MB_OK | MB_ICONEXCLAMATION); 
    return false; 
} 

if (!mPipeline.IsStarted()) 
{ 
    return false; 
} 

if (mSavingMovie) 
    return false; 

PvInt64 width; 
PvInt64 height; 
PvInt64 bitCount; 

if (!GetImageWidth(width).IsOK()) 
    return false; 

if (!GetImageHeight(height).IsOK()) 
    return false; 

if (!GetPixelBitCount(bitCount).IsOK()) 
    return false; 

// Start the movie compressor 
if (!mVideoCompressor->Start(mLocation, 
          width, 
          height, 
          bitCount/8, 
          59).IsOK()) 
{ 
    MessageBox(mLocation, 
       L"Cannot start Video Compressor!", 
       MB_OK | MB_ICONEXCLAMATION); 
    return false; 
} 

return true; 
} 

功能將視頻大小信息,然後調用實際壓縮開始

PvResult VideoCompressor::Start(const CString& aFileName, unsigned short aSizeX,  unsigned short aSizeY, unsigned short aBPP, double aFPS) 
{ 
IAVIFile *lAVIFile = NULL; 
IAVIStream *lAVIStream = NULL; 
IAVIStream *lAVICompressedStream = NULL; 
AVISTREAMINFO lAVISTREAMINFO; 
AVICOMPRESSOPTIONS lAVICOMPRESSOPTIONS; 

// Try to match the image format with the Video Compressor capabilities 
BITMAPINFO lTempBI; 
lTempBI.bmiHeader.biSize   = sizeof(BITMAPINFO); 
lTempBI.bmiHeader.biWidth   = aSizeX; 
lTempBI.bmiHeader.biHeight  = aSizeY; 
lTempBI.bmiHeader.biPlanes  = 1; 
lTempBI.bmiHeader.biBitCount  = aBPP * 8; 
lTempBI.bmiHeader.biCompression = BI_RGB; 
lTempBI.bmiHeader.biSizeImage  = aSizeX * aSizeY * aBPP; 
lTempBI.bmiHeader.biXPelsPerMeter = 1280; 
lTempBI.bmiHeader.biYPelsPerMeter = 720; 
lTempBI.bmiHeader.biClrUsed  = 0; 
lTempBI.bmiHeader.biClrImportant = 0; 
//lTempBI.bmiHeader. 

if((mCOMPVARS.hic != NULL) && // if not the "Full Frames (uncompressed)" 
    (ICCompressQuery(mCOMPVARS.hic, &lTempBI, NULL) != ICERR_OK)) 
{ 
    mLastVideoError = "Image format not accepted by compressor!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 

// Try to open the stream for writing 
if(mTempBuffer) 
    delete [] mTempBuffer; 

mTempBuffer = new unsigned char[ aSizeX * aSizeY * aBPP ]; 
if(mTempBuffer == NULL) 
{ 
    mLastVideoError = "Cannot allocate memory for a temporary buffer!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 

if(AVIFileOpen(&lAVIFile, aFileName, OF_CREATE | OF_WRITE, NULL) != 0) 
{ 
    mLastVideoError = "Cannot open movie file for writing!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 

// Fill out AVIStream information 
memset(&lAVISTREAMINFO, 0, sizeof(AVISTREAMINFO)); 
lAVISTREAMINFO.fccType    = streamtypeVIDEO; 
lAVISTREAMINFO.fccHandler   = mCOMPVARS.fccHandler; 
lAVISTREAMINFO.dwFlags    = 0; 
lAVISTREAMINFO.dwCaps    = 0; 
lAVISTREAMINFO.wPriority    = 0; 
lAVISTREAMINFO.wLanguage    = 0; 
lAVISTREAMINFO.dwScale    = 100; 
lAVISTREAMINFO.dwRate    = (unsigned long)(aFPS * 100.0); 
lAVISTREAMINFO.dwStart    = 0; 
lAVISTREAMINFO.dwLength    = 0; 
lAVISTREAMINFO.dwInitialFrames  = 0; 
lAVISTREAMINFO.dwQuality    = mCOMPVARS.lQ; 
lAVISTREAMINFO.dwSuggestedBufferSize = aSizeX * aSizeY * aBPP; 
lAVISTREAMINFO.dwSampleSize   = aSizeX * aSizeY * aBPP; 
SetRect(&lAVISTREAMINFO.rcFrame, 0, aSizeY, aSizeX, 0); 
// Convert to a wchar_t* 
char *orig = "Video Stream"; 
size_t origsize = strlen(orig) + 1; 
const size_t newsize = 64; 
size_t convertedChars = 0; 

mbstowcs_s(&convertedChars, lAVISTREAMINFO.szName, origsize, orig, _TRUNCATE); 

if(AVIFileCreateStream(lAVIFile, &lAVIStream, &lAVISTREAMINFO) != 0) 
{ 
    mLastVideoError = "Cannot create video stream!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 

BITMAPINFOHEADER lBIH; 
lBIH.biSize   = sizeof(BITMAPINFOHEADER); 
lBIH.biWidth   = aSizeX; 
lBIH.biHeight  = aSizeY; 
lBIH.biPlanes  = 1; 
lBIH.biBitCount  = aBPP * 8; 
lBIH.biCompression = BI_RGB; 
lBIH.biSizeImage  = aSizeX * aSizeY * aBPP; 
lBIH.biXPelsPerMeter = 1280; 
lBIH.biYPelsPerMeter = 720; 
lBIH.biClrUsed  = 0; 
lBIH.biClrImportant = 0; 

memset(&lAVICOMPRESSOPTIONS, 0, sizeof(AVICOMPRESSOPTIONS)); 
lAVICOMPRESSOPTIONS.fccType   = streamtypeVIDEO; 
lAVICOMPRESSOPTIONS.fccHandler  = mCOMPVARS.fccHandler; 
lAVICOMPRESSOPTIONS.dwKeyFrameEvery = 15; 
lAVICOMPRESSOPTIONS.dwQuality   = mCOMPVARS.lQ; 
lAVICOMPRESSOPTIONS.dwBytesPerSecond = 0; 
lAVICOMPRESSOPTIONS.dwFlags   = AVICOMPRESSF_KEYFRAMES; //| AVICOMPRESSF_VALID;//|AVICOMPRESSF_DATARATE; 
lAVICOMPRESSOPTIONS.lpFormat   = &lBIH; 
lAVICOMPRESSOPTIONS.cbFormat   = sizeof(lBIH); 
lAVICOMPRESSOPTIONS.lpParms   = 0; 
lAVICOMPRESSOPTIONS.cbParms   = 0; 
lAVICOMPRESSOPTIONS.dwInterleaveEvery = 0; 

HRESULT lR = AVIMakeCompressedStream(&lAVICompressedStream, lAVIStream, &lAVICOMPRESSOPTIONS, NULL); 
if(lR == AVIERR_NOCOMPRESSOR) 
{ 
    mLastVideoError = "Cannot find a suitable compressor!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 
else if(lR == AVIERR_MEMORY) 
{ 
    mLastVideoError = "Not enough memory to start the compressor!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 
else if(lR == AVIERR_UNSUPPORTED) 
{ 
    mLastVideoError = "Compression is not supported for this image buffer!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 

if(AVIStreamSetFormat(lAVICompressedStream, 0, &lBIH, sizeof(lBIH)) != 0) 
{ 
    mLastVideoError = "Cannot set stream format. It probably isn't supported by the Codec!"; 
    CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream); 
    return PvResult::Code::GENERIC_ERROR; 
} 

/////////////////// 

HRESULT hr; 
//IBaseFilter mux = Null; 
//IFileSinkFilter sink = null; 

// Guid x = new Guid(0xe436eb88, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); 

//ICaptureGraphBuilder2::SetOutputFileName( 



////////////////// 

// finishing up 
mAVIFile    = lAVIFile; 
mAVIStream   = lAVIStream; 
mAVICompressedStream = lAVICompressedStream; 

mSizeX  = aSizeX; 
mSizeY  = aSizeY; 
mBPP  = aBPP; 
mImageSize = aSizeX * aSizeY * aBPP; 

mLastSample = 0; 

mCompressing = true; 

return PvResult::Code::OK; 
} 

這個壓縮流

PvResult VideoCompressor::Compress(PvBuffer *aPvBuffer) 
{ 
if (!mCompressing) 
    return PvResult::Code::GENERIC_ERROR; 

ASSERT(mTempBuffer != NULL); 

long lSamplesWritten, lBytesWritten; 

int numberOfLines = 0; 

PvUInt8 * aBuffer = aPvBuffer->GetDataPointer(); 

for(unsigned short lLine = 0; lLine < mSizeY; lLine++) 
{ 
    numberOfLines = lLine; 
    unsigned char *lCurLine = (unsigned char *)aBuffer + (lLine   ) * mSizeX * mBPP; 
    unsigned char *lCurLineInv = mTempBuffer    + (mSizeY - lLine - 1) * mSizeX * mBPP; 
    ::memcpy(lCurLineInv, lCurLine, mSizeX * mBPP); 
} 

if(AVIStreamWrite(mAVICompressedStream, mLastSample, 1, mTempBuffer, mImageSize, 0, 
     &lSamplesWritten, &lBytesWritten) != 0 || 
    lSamplesWritten < 1 || 
    lBytesWritten < 1) 
{ 
    mLastVideoError = "Cannot compress image!"; 
    return PvResult::Code::GENERIC_ERROR; 

} 

mLastSample ++; 

return PvResult::Code::OK; 
} 
功能

這應該是這樣的: http://i13.photobucket.com/albums/a269/Masterg_/Untitled-16.png

這是它保存爲(減去傢伙): http://i13.photobucket.com/albums/a269/Masterg_/vlcsnap-2011-06-07-13h11m34s97.png

回答

0

MSDN我們:

語法

DWORD ICCompressQuery(
    hic, 
    lpbiInput, 
    lpbiOutput); 

參數

HIC:處理壓縮機。

lpbiInput:指向包含輸入格式的BITMAPINFO結構的指針

lpbiOutput:指向包含輸出格式的BITMAPINFO結構的指針。您可以將 指定爲零,此參數爲 指示任何輸出格式爲 都可以接受。

我可能是錯的,但在我看來,你試圖「強制」這種輸入格式,不考慮你作爲輸入傳遞的實際格式。如果您的輸入格式與「強制」格式不匹配,則必須預料會出現奇怪的結果。 如果您的實際輸入格式與壓縮機不兼容,您可以在壓縮機之前嘗試使用ColorSpace converter filter