📄 mjpeg2bmp.cpp
字号:
#include "StdAfx.h"
#include "Mjpeg2bmp.h"
#include <initguid.h>
#include <imgguids.h>
CMjpeg2bmp::CMjpeg2bmp(void)
{
}
CMjpeg2bmp::~CMjpeg2bmp(void)
{
}
//#include "camtest2.h" // Only needed for ZONE_ constants
enum CodecType {eDecoder, eEncoder};
#define NAMEVALENTRY(x) { (LONG)(x), TEXT(#x) }
struct NameValuePair {
LONG pValue;
TCHAR *szName;
};
//void info (const TCHAR* tszFormat, ...);
IImagingFactory *pImagingFactory = NULL;
//----------------------------------------------------------------------
// InitDisplayFrame
//
HRESULT CMjpeg2bmp::InitDisplayFrame (LPCWSTR pszExt)
{
HRESULT hr;
BOOL fFound = FALSE;
// Get length of search extension
int nLen = pszExt ? lstrlen (pszExt) : 0;
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
//printf ("CoInitializeEx failed, hr: 0x%08x\r\n", hr);
return 1;
}
hr = CoCreateInstance(CLSID_ImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IImagingFactory,
(void**) &pImagingFactory);
if (FAILED(hr))
return hr;
//
// Query current installed codecs
//
ImageCodecInfo *pCodecInfo;
UINT uCnt = 0;
hr = pImagingFactory->GetInstalledDecoders (&uCnt, &pCodecInfo);
if (SUCCEEDED(hr))
{
//printf ("Detected %d decoders\r\n", uCnt);
for (UINT i = 0; i < uCnt; i++)
{
if (nLen &&
(_wcsnicmp(pCodecInfo[i].FormatDescription, pszExt, nLen) == 0))
fFound = TRUE;
//printf ("Name >%S<\r\n", pCodecInfo[i].CodecName);
//printf ("Desc >%S<\r\n", pCodecInfo[i].FormatDescription);
//printf ("\r\n");
}
CoTaskMemFree ((PVOID)pCodecInfo);
}
// See if we were supposed to find specific support and didn't find it
if (!hr && nLen && !fFound)
{
pImagingFactory->Release();
hr = ERROR_NOT_SUPPORTED;
}
return hr;
}
//----------------------------------------------------------------------
// Frees the imaging library
//
HRESULT CMjpeg2bmp::ReleaseDisplayFrame ()
{
HRESULT hr = 0;
if (pImagingFactory)
{
pImagingFactory->Release();
pImagingFactory = NULL;
}
return hr;
}
BYTE MJPG2JPGHdr[440] = {
// JPEG file header
0xff,0xd8, // SOI
0xff,0xe0, // APP0
0x00,0x10, // APP0 Hdr size
0x4a,0x46,0x49,0x46,0x00, // ID string
0x01,0x01, // Version
0x00, // Bits per type
0x00, 0x00, // X density
0x00, 0x00, // Y density
0x00, // X Thumbnail size
0x00, // Y Thumbnail size
/* JPEG DHT Segment for YCrCb omitted from MJPG data */
0xFF,0xC4,0x01,0xA2,
0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,
0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,
0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,
0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,
0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,
0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,
0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A,
0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,
0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
0xF9,0xFA
};
//----------------------------------------------------------------------
// DisplayFrame
//
HRESULT CMjpeg2bmp::DisplayFrame (PBYTE pData, DWORD dwPreBuff, DWORD dwSize, HDC hdc, RECT *pRect)
{
HRESULT hr;
IImageSink *pImageSink = NULL;
IImage *pImage = NULL;
IImageDecoder *pImageDecoder = NULL;
IImageEncoder *pImageEncoder = NULL;
IBitmapImage *pBitmapImage = NULL;
IStream *pStream = NULL;
ImageInfo ii;
if (pImagingFactory == NULL)
return E_NOINTERFACE;
if (*pData == 0)
return 0;
#if 1
// Slow way copies the data to a seperate heap allocation. This seems to be needed for the
// CreateStreamOnHGlobal method because that method looks at the heap block header to determine
// the size of the data.
// Data is in big endian format
int MjpegHdrSize = *(pData+4);
MjpegHdrSize = MjpegHdrSize << 8;
MjpegHdrSize += *(pData+5)+4;
if (MjpegHdrSize > 100)
return -2;
LPBYTE pLocal = (LPBYTE)LocalAlloc (LPTR, dwSize+512);
if (!pLocal)
return -1;
memcpy (pLocal, MJPG2JPGHdr, sizeof (MJPG2JPGHdr));
memcpy (pLocal + sizeof (MJPG2JPGHdr), pData + MjpegHdrSize, dwSize - MjpegHdrSize);
// Create the stream
hr = CreateStreamOnHGlobal(pLocal, TRUE, &pStream);
#else
// The nice way would be to just have a buffer converted into a stream but its
// late and I don't have the time. Exercise left to the reader...
// Add JPEG header to MJPEG frame data. We need to also remove the MJPEG info at the start of the frame
// Data is in big endian format
int MjpegHdrSize = *(pData+4);
MjpegHdrSize = MjpegHdrSize << 8;
MjpegHdrSize += *(pData+5)+4;
PBYTE pPreBuff = pData + MjpegHdrSize - sizeof (MJPG2JPGHdr);
memcpy (pPreBuff, MJPG2JPGHdr, sizeof (MJPG2JPGHdr));
// Create the stream
hr = CreateStreamOnHGlobal(pPreBuff, TRUE, &pStream);
#endif
__try
{
if (FAILED(hr))
{
//printf ("CreateStreamOnHGlobal failed, hr: 0x%08x\r\n", hr);
goto finish;
}
// Get the decoder. The system chooses the proper decoder
// from the format of the data in the buffer.
if (FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))
{
//printf ("CreateImageDecoder failed, hr: 0x%08x\r\n", hr);
goto finish;
}
// Query image info
if (FAILED(hr = pImageDecoder->GetImageInfo(&ii)))
{
//printf ("GetImageInfo failed, hr: 0x%08x\r\n", hr);
goto finish;
}
// Create bitmap of the same size
if (FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
{
//printf ("CreateNewBitmap failed, hr = 0x%08x\r\n", hr);
goto finish;
}
// Get the "sink" which is needed by the decoder so it can write the data to the bitmap
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
{
//printf ("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\r\n", hr);
goto finish;
}
// Finally, start the conversion
if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL)))
{
//printf ("BeginDecode into Bitmap Image failed, hr = 0x%08d\r\n", hr);
goto finish;
}
// Loop as necessary
while (E_PENDING == (hr = pImageDecoder->Decode()))
Sleep(10);
// Clean up
hr = pImageDecoder->EndDecode(hr);
if (FAILED(hr))
{
//printf ("Decoding failed, hr = 0x%08x\r\n", hr);
goto finish;
}
//
// We have a bitmap at this point. Get Image interface and draw
//
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
{
printf ("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\r\n", hr);
goto finish;
}
hr = pImage->Draw (hdc, pRect, NULL);
if (pImage)
pImage->Release();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//DEBUGMSG (ZONE_ERROR, (DTAG TEXT ("Exception decoding image \r\n")));
//printf ("Exception decoding image \r\n");
}
if (pImageSink)
pImageSink->Release();
pImageSink = NULL;
finish:
pImage = NULL; // This is already deleted above, but just to make sure...
if (pBitmapImage)
pBitmapImage->Release();
pBitmapImage = NULL;
if (pStream)
pStream->Release();
pStream = NULL;
if (pImageSink)
pImageSink->Release();
pImageSink = NULL;
if (pImageDecoder)
pImageDecoder->Release();
pImageDecoder = NULL;
if (pImageEncoder)
pImageEncoder->Release();
pImageEncoder = NULL;
// LocalFree (pLocal); Seems to be released by the ImageDecoder object
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -