March 04, 2009

error C3861: 'CoInitializeEx': identifier not found, even with argument-dependent lookup

You may get the following errors when trying to call CoInitializeEx(NULL, COINIT_MULTITHREADED).
 
error C2065: 'COINIT_MULTITHREADED' : undeclared identifier
error C3861: 'CoInitializeEx': identifier not found, even with argument-dependent lookup

The article in MSDN says "You must include the #define _WIN32_DCOM preprocessor directive at the beginning of your code to be able to use CoInitializeEx."

Look at the code snap in ObjBase.h:

#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM

WINOLEAPI  CoInitializeEx(IN LPVOID pvReserved, IN DWORD dwCoInit);
WINOLEAPI  CoGetCallerTID( LPDWORD lpdwTID );

#endif // DCOM

So, you need to follow the above rule if you want to call CoInitializeEx, of course you also need to include <objbase.h>.

Reference in MSDN:

March 01, 2009

Why is the media sample upside down after convert its buffer data from YUV to RGB?

Question
I converted the buffer of a media sample from YUY2 to RGB24 pixel by pixel, and then I got a upside-down image. What's wrong with it?

Answer
The definition of the biHeight field of BITMAPINFOHEADER depends the the biCompression field of BITMAPINFOHEADER.

If the bitmap is uncompressed RGB format, the positive biHeight value means the image is bottom-up image; if the bitmap is one of YUV formats such as YUY2, UYVY, and YV12, the image is top-down oriented and the sign of biHeight value must be ignored.

So, I need to do a vertical flip to get a correct image after convert buffer data from YUY2 to RGB24.

You can get more detail information in FOURCC.org: Bitmap Orientation and biHeight

February 21, 2009

FORMAT_VideoInfo v.s. FORMAT_VideoInfo2

If the media type is FORMAT_VideoInfo, it means the format buffer is a VIDEOINFOHEADER struct; if the media type is FORMAT_VideoInfo2, it means the format buffer is a VIDEOINFOHEADER2 struct. So, what's different between VIDEOINFOHEADER and VIDEOINFOHEADER2?

VIDEOINFOHEADER and VIDEOINFOHEADER2 are very different, VIDEOINFOHEADER2 is not just an entended struct of VIDEOINFOHEADER. This means you cannot cast a pointer of VIDEOINFOHEADER2 to a pointer of VIDEOINFOHEADER.

INCORRECT:

if(pmt->formattype == FORMAT_VideoInfo || pmt->formattype == FORMAT_VideoInfo2)
{
    VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
    // *** Wrong! ***
}

CORRECT:

if(pmt->formattype == FORMAT_VideoInfo)
{
    VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
    // Now you can use pVIH.
}
else if(pmt->formattype == FORMAT_VideoInfo2)
{
    VIDEOINFOHEADER2 *pVIH = (VIDEOINFOHEADER2*)pmt->pbFormat;
    // Now you can use pVIH.
}

Reference in MSDN:

February 17, 2009

How To: Toggle / Next Bookmark in Visual C++

Bookmarking is a very useful feature of Visual C++ when you are coding, but the keyboard short cuts of this function is hard to remember. In the menu, you can find the short cuts of toggle and next bookmark are "Ctrl + K Ctrl +K" and "Ctrl + K Ctrl + N" respectively, but why do I need to press so many keys  just for toggle or next bookmark?

You can do it more easily, just use the following short cuts:

Toggle Bookmark - Ctrl + F2

Next Bookmark - F2

Wow! It is very easy to use, isn't it? Enjoy bookmarking feature during your coding time.

I have tried it on Visual C++ 6 / 2003 / 2005 / 2008, it works fine.
(Note: The key mapping of Visual Studio is set to default "Visual C++".)

Reference in This Site:

February 12, 2009

How To: STL String Case-insensitive Compare

This article is talking about how to do a case-insensitive compare for STL string and wstring, there're 2 ways to reach the goal.

Method #1: C Run-time Library - _stricmp() and _wcsicmp()

#include <string>

using namespace std;

string strUpperCase = "ABC";
string strLowerCase = "abc";
if(_stricmp(strUpperCase.c_str(), strLowerCase.c_str()) == 0)
// For wstring, use _wcsicmp() instead.
{
  // Do something you need
}


Method #2: STL Algorithm - transform()

#include <cctype>
#include <string>
#include <algorithm>

using namespace std;

// I make a helper function to compare string
bool CompareCaseInsensitive(string strFirst, string strSecond)
{
  // Convert both strings to upper case by transfrom() before compare.
  transform(strFirst.begin(), strFirst.end(), strFirst.begin(), toupper);
  transform(strSecond.begin(), strSecond.end(), strSecond.begin(), toupper);
  if(strFirst == strSecond) return true; else return false;
}

string strUpperCase = "ABC";
string strLowerCase = "abc";
if(CompareCaseInsensitive(strUpperCase, strLowerCase))
{
  // Do something you need
}


Reference in This Site:
How to convert STL string / wstring to upper / lower case?

Reference in MSDN:
_stricmp, _wcsicmp, _mbsicmp, _stricmp_l, _wcsicmp_l, _mbsicmp_l

January 19, 2009

More explanation of CoInitialize() and CoUninitialize()

In this article, I'll not talk about how it works about the COM's apartment model, but the coding practice.

CoInitializeEx() provides the same functionality as CoInitialize() except it provides a parameter to specify the thread's apartment model. So, MSDN recommands us to call CoInitializeEx() instead of CoInitialize().

For using CoInitializeEx(), we also need to follow the same rules as CoInitialize(), I mentioned in the previous article.

The following examples explain how to use CoInitializeEx() and CoUninitialize():

Example #1: CoInitializeEx() will return S_FALSE if the COM library was loaded.

void main()
{
  HRESULT hr = E_FAIL;

  // The first call
  hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // hr = S_OK

  // The second call
  hr = CoInitialize(NULL); // hr = S_FALSE, CoInitialize(NULL) = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)

  // ... skip ...

  // For the second call
  CoUninitialize();

  // For the first call
  CoUninitialize(); // COM library will be unloaded
}

Example #2: CoInitializeEx() will return RPC_E_CHANGED_MODE if a previous call to CoInitializeEx() specified a different apartment model

void main()
{
  HRESULT hr = E_FAIL;

  // The first call
  hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // hr = S_OK

  // The second call
  hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); // hr = RPC_E_CHANGED_MODE, the thread's apartment model is still the single thread apartment.

  // ... skip ...

  // NOTE: We do not need to call CoUninitialize() if the corresponding call made by CoInitializeEx() returns error.

  // For the first call
  CoUninitialize(); // COM library will be unloaded
}

January 18, 2009

A clear explanation of CoInitialize() and CoUninitialize()

As you know, when you are using DirectShow or the other COM-based components, the first thing you have to do is calling CoInitialize() to initialize the COM library.

Furthermore, there are several rules you should follow. Now, I will give you a clear explanation here.

Rule #1: For each thread, you have to call CoInitialize() before you call any of the COM library funtions except CoGetMalloc() and the memory allocation functions.

Rule #2: For each successful call made by CoInitialize(), you have to call CoUninitialize() to free the COM library.

Rule #3: Do not call CoInitialize() or CoUninitialize() from the DllMain() function.

Rule #4: The first thread in the application that calls CoInitialize() must be the last thread to call CoUninitialize().


Reference in MSDN:
CoInitialize