Alexandre Lision | 8af73cb | 2013-12-10 14:11:20 -0500 | [diff] [blame] | 1 | //------------------------------------------------------------------------------
|
| 2 | // File: AMVideo.cpp
|
| 3 | //
|
| 4 | // Desc: DirectShow base classes - implements helper functions for
|
| 5 | // bitmap formats.
|
| 6 | //
|
| 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
| 8 | //------------------------------------------------------------------------------
|
| 9 |
|
| 10 | #include <pjmedia-videodev/config.h>
|
| 11 |
|
| 12 | #if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
|
| 13 |
|
| 14 | #include <streams.h>
|
| 15 | #include <limits.h>
|
| 16 |
|
| 17 | // These are bit field masks for true colour devices
|
| 18 |
|
| 19 | const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F};
|
| 20 | const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F};
|
| 21 | const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF};
|
| 22 |
|
| 23 | // This maps bitmap subtypes into a bits per pixel value and also a
|
| 24 | // name. unicode and ansi versions are stored because we have to
|
| 25 | // return a pointer to a static string.
|
| 26 | const struct {
|
| 27 | const GUID *pSubtype;
|
| 28 | WORD BitCount;
|
| 29 | CHAR *pName;
|
| 30 | WCHAR *wszName;
|
| 31 | } BitCountMap[] = { &MEDIASUBTYPE_RGB1, 1, "RGB Monochrome", L"RGB Monochrome",
|
| 32 | &MEDIASUBTYPE_RGB4, 4, "RGB VGA", L"RGB VGA",
|
| 33 | &MEDIASUBTYPE_RGB8, 8, "RGB 8", L"RGB 8",
|
| 34 | &MEDIASUBTYPE_RGB565, 16, "RGB 565 (16 bit)", L"RGB 565 (16 bit)",
|
| 35 | &MEDIASUBTYPE_RGB555, 16, "RGB 555 (16 bit)", L"RGB 555 (16 bit)",
|
| 36 | &MEDIASUBTYPE_RGB24, 24, "RGB 24", L"RGB 24",
|
| 37 | &MEDIASUBTYPE_RGB32, 32, "RGB 32", L"RGB 32",
|
| 38 | &MEDIASUBTYPE_ARGB32, 32, "ARGB 32", L"ARGB 32",
|
| 39 | &MEDIASUBTYPE_Overlay, 0, "Overlay", L"Overlay",
|
| 40 | &GUID_NULL, 0, "UNKNOWN", L"UNKNOWN"
|
| 41 | };
|
| 42 |
|
| 43 | // Return the size of the bitmap as defined by this header
|
| 44 |
|
| 45 | STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader)
|
| 46 | {
|
| 47 | return DIBSIZE(*pHeader);
|
| 48 | }
|
| 49 |
|
| 50 |
|
| 51 | // This is called if the header has a 16 bit colour depth and needs to work
|
| 52 | // out the detailed type from the bit fields (either RGB 565 or RGB 555)
|
| 53 |
|
| 54 | STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader)
|
| 55 | {
|
| 56 | BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader;
|
| 57 | ASSERT(pbmiHeader->biBitCount == 16);
|
| 58 |
|
| 59 | // If its BI_RGB then it's RGB 555 by default
|
| 60 |
|
| 61 | if (pbmiHeader->biCompression == BI_RGB) {
|
| 62 | return MEDIASUBTYPE_RGB555;
|
| 63 | }
|
| 64 |
|
| 65 | // Compare the bit fields with RGB 555
|
| 66 |
|
| 67 | DWORD *pMask = (DWORD *) pbmInfo->bmiColors;
|
| 68 | if (pMask[0] == bits555[0]) {
|
| 69 | if (pMask[1] == bits555[1]) {
|
| 70 | if (pMask[2] == bits555[2]) {
|
| 71 | return MEDIASUBTYPE_RGB555;
|
| 72 | }
|
| 73 | }
|
| 74 | }
|
| 75 |
|
| 76 | // Compare the bit fields with RGB 565
|
| 77 |
|
| 78 | pMask = (DWORD *) pbmInfo->bmiColors;
|
| 79 | if (pMask[0] == bits565[0]) {
|
| 80 | if (pMask[1] == bits565[1]) {
|
| 81 | if (pMask[2] == bits565[2]) {
|
| 82 | return MEDIASUBTYPE_RGB565;
|
| 83 | }
|
| 84 | }
|
| 85 | }
|
| 86 | return GUID_NULL;
|
| 87 | }
|
| 88 |
|
| 89 |
|
| 90 | // Given a BITMAPINFOHEADER structure this returns the GUID sub type that is
|
| 91 | // used to describe it in format negotiations. For example a video codec fills
|
| 92 | // in the format block with a VIDEOINFO structure, it also fills in the major
|
| 93 | // type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit
|
| 94 | // count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8
|
| 95 |
|
| 96 | STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader)
|
| 97 | {
|
| 98 | ASSERT(pbmiHeader);
|
| 99 |
|
| 100 | // If it's not RGB then create a GUID from the compression type
|
| 101 |
|
| 102 | if (pbmiHeader->biCompression != BI_RGB) {
|
| 103 | if (pbmiHeader->biCompression != BI_BITFIELDS) {
|
| 104 | FOURCCMap FourCCMap(pbmiHeader->biCompression);
|
| 105 | return (const GUID) FourCCMap;
|
| 106 | }
|
| 107 | }
|
| 108 |
|
| 109 | // Map the RGB DIB bit depth to a image GUID
|
| 110 |
|
| 111 | switch(pbmiHeader->biBitCount) {
|
| 112 | case 1 : return MEDIASUBTYPE_RGB1;
|
| 113 | case 4 : return MEDIASUBTYPE_RGB4;
|
| 114 | case 8 : return MEDIASUBTYPE_RGB8;
|
| 115 | case 16 : return GetTrueColorType(pbmiHeader);
|
| 116 | case 24 : return MEDIASUBTYPE_RGB24;
|
| 117 | case 32 : return MEDIASUBTYPE_RGB32;
|
| 118 | }
|
| 119 | return GUID_NULL;
|
| 120 | }
|
| 121 |
|
| 122 |
|
| 123 | // Given a video bitmap subtype we return the number of bits per pixel it uses
|
| 124 | // We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the
|
| 125 | // GUID subtype is not found in the table we return an invalid USHRT_MAX
|
| 126 |
|
| 127 | STDAPI_(WORD) GetBitCount(const GUID *pSubtype)
|
| 128 | {
|
| 129 | ASSERT(pSubtype);
|
| 130 | const GUID *pMediaSubtype;
|
| 131 | INT iPosition = 0;
|
| 132 |
|
| 133 | // Scan the mapping list seeing if the source GUID matches any known
|
| 134 | // bitmap subtypes, the list is terminated by a GUID_NULL entry
|
| 135 |
|
| 136 | while (TRUE) {
|
| 137 | pMediaSubtype = BitCountMap[iPosition].pSubtype;
|
| 138 | if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) {
|
| 139 | return USHRT_MAX;
|
| 140 | }
|
| 141 | if (IsEqualGUID(*pMediaSubtype,*pSubtype)) {
|
| 142 | return BitCountMap[iPosition].BitCount;
|
| 143 | }
|
| 144 | iPosition++;
|
| 145 | }
|
| 146 | }
|
| 147 |
|
| 148 |
|
| 149 | // Given a bitmap subtype we return a description name that can be used for
|
| 150 | // debug purposes. In a retail build this function still returns the names
|
| 151 | // If the subtype isn't found in the lookup table we return string UNKNOWN
|
| 152 |
|
| 153 | int LocateSubtype(const GUID *pSubtype)
|
| 154 | {
|
| 155 | ASSERT(pSubtype);
|
| 156 | const GUID *pMediaSubtype;
|
| 157 | INT iPosition = 0;
|
| 158 |
|
| 159 | // Scan the mapping list seeing if the source GUID matches any known
|
| 160 | // bitmap subtypes, the list is terminated by a GUID_NULL entry
|
| 161 |
|
| 162 | while (TRUE) {
|
| 163 | pMediaSubtype = BitCountMap[iPosition].pSubtype;
|
| 164 | if (IsEqualGUID(*pMediaSubtype,*pSubtype) ||
|
| 165 | IsEqualGUID(*pMediaSubtype,GUID_NULL)
|
| 166 | )
|
| 167 | {
|
| 168 | break;
|
| 169 | }
|
| 170 |
|
| 171 | iPosition++;
|
| 172 | }
|
| 173 |
|
| 174 | return iPosition;
|
| 175 | }
|
| 176 |
|
| 177 |
|
| 178 |
|
| 179 | STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype)
|
| 180 | {
|
| 181 | return BitCountMap[LocateSubtype(pSubtype)].wszName;
|
| 182 | }
|
| 183 |
|
| 184 | STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype)
|
| 185 | {
|
| 186 | return BitCountMap[LocateSubtype(pSubtype)].pName;
|
| 187 | }
|
| 188 |
|
| 189 | #ifndef GetSubtypeName
|
| 190 | #error wxutil.h should have defined GetSubtypeName
|
| 191 | #endif
|
| 192 | #undef GetSubtypeName
|
| 193 |
|
| 194 | // this is here for people that linked to it directly; most people
|
| 195 | // would use the header file that picks the A or W version.
|
| 196 | STDAPI_(CHAR *) GetSubtypeName(const GUID *pSubtype)
|
| 197 | {
|
| 198 | return GetSubtypeNameA(pSubtype);
|
| 199 | }
|
| 200 |
|
| 201 |
|
| 202 | // The mechanism for describing a bitmap format is with the BITMAPINFOHEADER
|
| 203 | // This is really messy to deal with because it invariably has fields that
|
| 204 | // follow it holding bit fields, palettes and the rest. This function gives
|
| 205 | // the number of bytes required to hold a VIDEOINFO that represents it. This
|
| 206 | // count includes the prefix information (like the rcSource rectangle) the
|
| 207 | // BITMAPINFOHEADER field, and any other colour information on the end.
|
| 208 | //
|
| 209 | // WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make
|
| 210 | // sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't
|
| 211 | // right at the start of the VIDEOINFO (there are a number of other fields),
|
| 212 | //
|
| 213 | // CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER));
|
| 214 | //
|
| 215 |
|
| 216 | STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader)
|
| 217 | {
|
| 218 | // Everyone has this to start with this
|
| 219 | LONG Size = SIZE_PREHEADER + pHeader->biSize;
|
| 220 |
|
| 221 | ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER));
|
| 222 |
|
| 223 | // Does this format use a palette, if the number of colours actually used
|
| 224 | // is zero then it is set to the maximum that are allowed for that colour
|
| 225 | // depth (an example is 256 for eight bits). Truecolour formats may also
|
| 226 | // pass a palette with them in which case the used count is non zero
|
| 227 |
|
| 228 | // This would scare me.
|
| 229 | ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0);
|
| 230 |
|
| 231 | if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) {
|
| 232 | LONG Entries = (DWORD) 1 << pHeader->biBitCount;
|
| 233 | if (pHeader->biClrUsed) {
|
| 234 | Entries = pHeader->biClrUsed;
|
| 235 | }
|
| 236 | Size += Entries * sizeof(RGBQUAD);
|
| 237 | }
|
| 238 |
|
| 239 | // Truecolour formats may have a BI_BITFIELDS specifier for compression
|
| 240 | // type which means that room for three DWORDs should be allocated that
|
| 241 | // specify where in each pixel the RGB colour components may be found
|
| 242 |
|
| 243 | if (pHeader->biCompression == BI_BITFIELDS) {
|
| 244 | Size += SIZE_MASKS;
|
| 245 | }
|
| 246 |
|
| 247 | // A BITMAPINFO for a palettised image may also contain a palette map that
|
| 248 | // provides the information to map from a source palette to a destination
|
| 249 | // palette during a BitBlt for example, because this information is only
|
| 250 | // ever processed during drawing you don't normally store the palette map
|
| 251 | // nor have any way of knowing if it is present in the data structure
|
| 252 |
|
| 253 | return Size;
|
| 254 | }
|
| 255 |
|
| 256 |
|
| 257 | // Returns TRUE if the VIDEOINFO contains a palette
|
| 258 |
|
| 259 | STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo)
|
| 260 | {
|
| 261 | if (PALETTISED(pVideoInfo) == FALSE) {
|
| 262 | if (pVideoInfo->bmiHeader.biClrUsed == 0) {
|
| 263 | return FALSE;
|
| 264 | }
|
| 265 | }
|
| 266 | return TRUE;
|
| 267 | }
|
| 268 |
|
| 269 |
|
| 270 | // Return a pointer to the first entry in a palette
|
| 271 |
|
| 272 | STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo)
|
| 273 | {
|
| 274 | if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
|
| 275 | return TRUECOLOR(pVideoInfo)->bmiColors;
|
| 276 | }
|
| 277 | return COLORS(pVideoInfo);
|
| 278 | }
|
| 279 |
|
| 280 | #endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
|