123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License along
- // with this program; if not, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // RTVIDC.CPP
- //
- // History:
- // 11/13/95 JMI Started.
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // This class is designed to receive VIDC data in real time and decompress it
- // to a specific buffer or buffers on a channel basis.
- //
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // C Headers.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Blue Headers.
- //////////////////////////////////////////////////////////////////////////////
- #include "System.h"
- #include "bdebug.h"
- //////////////////////////////////////////////////////////////////////////////
- // Green Headers.
- //////////////////////////////////////////////////////////////////////////////
- #include "rttypes.h"
- #include "rtvidc.h"
- //////////////////////////////////////////////////////////////////////////////
- // Orange Headers.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Yellow Headers.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Module specific macros.
- //////////////////////////////////////////////////////////////////////////////
- // Types of chunks.
- #define VIDC_CHUNK_HEADER RT_FLAG_INIT
- #define VIDC_CHUNK_PALETTE RT_FLAG_USER1
- //////////////////////////////////////////////////////////////////////////////
- // Module specific typedefs.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Module specific (static) variables.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Construction/Destruction Functions.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Default constructor.
- //
- //////////////////////////////////////////////////////////////////////////////
- CRtVidc::CRtVidc()
- {
- Set();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Destructor.
- //
- //////////////////////////////////////////////////////////////////////////////
- CRtVidc::~CRtVidc()
- {
- Reset();
- }
- //////////////////////////////////////////////////////////////////////////////
- // Internal Functions.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets variables w/o regard to current values.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::Set(void)
- {
- m_pdispatch = NULL;
- for (short i = 0; i < MAX_VID_CHANNELS; i++)
- {
- m_avidchdrs[i].sNumFrames = 0;
- m_avidchdrs[i].pImage = NULL;
- m_avidchdrs[i].callbackHeader = NULL;
- m_avidchdrs[i].callbackBefore = NULL;
- m_avidchdrs[i].callbackAfter = NULL;
- m_avidchdrs[i].hic = NULL;
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Resets variables. Performs deallocation if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::Reset(void)
- {
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads a BITMAPINFO from the specified CNFile into the provided data.
- // Returns number of bytes read on success, negative on error.
- //
- //////////////////////////////////////////////////////////////////////////////
- long ReadBitmapInfo( BITMAPINFO* pbmi, CNFile* pfile)
- {
- // Remember current position.
- long lPos = pfile->Tell();
- // Write BITMAPINFO.
- pfile->Read(&pbmi->bmiHeader.biSize);
- pfile->Read(&pbmi->bmiHeader.biWidth);
- pfile->Read(&pbmi->bmiHeader.biHeight);
- pfile->Read(&pbmi->bmiHeader.biPlanes);
- pfile->Read(&pbmi->bmiHeader.biBitCount);
- pfile->Read(&pbmi->bmiHeader.biCompression);
- pfile->Read(&pbmi->bmiHeader.biSizeImage);
- pfile->Read(&pbmi->bmiHeader.biXPelsPerMeter);
- pfile->Read(&pbmi->bmiHeader.biYPelsPerMeter);
- pfile->Read(&pbmi->bmiHeader.biClrUsed);
- pfile->Read(&pbmi->bmiHeader.biClrImportant);
- // pfile->Read color info, if any.
- // Get number of bytes left.
- long lNumColors = pbmi->bmiHeader.biSize - sizeof(pbmi->bmiHeader);
- // Must be complete RGBQUADs.
- ASSERT(lNumColors % 4 == 0);
- // Convert to number of colors left.
- lNumColors /= 4L;
- for (long l = 0; l < lNumColors; l++)
- {
- pfile->Read(&pbmi->bmiColors[l].rgbBlue);
- pfile->Read(&pbmi->bmiColors[l].rgbGreen);
- pfile->Read(&pbmi->bmiColors[l].rgbRed);
- pfile->Read(&pbmi->bmiColors[l].rgbReserved);
- }
- return pfile->Tell() - lPos;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Decompresses a VIDC frame using the opened decompressor.
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short CRtVidc::DecompressFrame( PVIDC_RT_HDR pvidchdr, CNFile* pfile,
- ULONG ulFlags, PBMI pbmiIn, PBMI pbmiOut)
- {
- short sRes = 0; // Assume success.
- // Get data in compression native format.
- BMI bmiTempOut = *pbmiIn;
- bmiTempOut.bmiHeader.biCompression = BI_RGB;
- // Attempt to decompress . . .
- // if (ICDecompress( pvidchdr->hic, ulFlags,
- // (BITMAPINFOHEADER*)pbmiIn, pfile->GetMemory() + pfile->Tell(),
- // (BITMAPINFOHEADER*)pbmiOut, pvidchdr->pImage->pData)
- // == ICERR_OK)
- HBITMAP hbm = (HBITMAP)ICImageDecompress( pvidchdr->hic, 0L, (BITMAPINFO*)pbmiIn,
- pfile->GetMemory() + pfile->Tell(),
- (BITMAPINFO*)&bmiTempOut);
- if (hbm != NULL)
- {
- // Successfully decompressed.
- HDC hDC = GetDC(NULL);
- if (hDC != NULL)
- {
- pbmiOut->bmiHeader.biSize = sizeof(pbmiOut->bmiHeader);
- pbmiOut->bmiHeader.biSizeImage = 0;
- // Reformat.
- if (GetDIBits( hDC, hbm, 0, pvidchdr->pImage->lHeight,
- pvidchdr->pImage->pData, (BITMAPINFO*)&pbmiOut, DIB_RGB_COLORS) != FALSE)
- {
- // Success.
- }
- else
- {
- TRACE("DecompressFrame(): GetDIBits failed.\n");
- sRes = -3;
- }
- ReleaseDC(NULL, hDC);
- }
- else
- {
- TRACE("DecompressFrame(): GetDC failed.\n");
- sRes = -2;
- }
- // Destroy the bitmap.
- DeleteObject(hbm);
- }
- else
- {
- TRACE("DecompressFrame(): ICDecompress failed.\n");
- sRes = -1;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Use handler for RtVidc buffers.
- // Returns RET_FREE if done with data on return, RET_DONTFREE otherwise.
- //
- //////////////////////////////////////////////////////////////////////////////
- short CRtVidc::Use( UCHAR* puc, long lSize, USHORT usType, UCHAR ucFlags,
- long lTime)
- {
- short sRes = RET_FREE; // Always free.
- short sError = 0;
- ASSERT(usType == RT_TYPE_VIDC);
- ASSERT(puc != NULL);
- CNFile file;
- file.Open(puc, lSize, ENDIAN_LITTLE);
- // Read values common to all chunks.
- // Read vidc ID.
- USHORT usVidcId;
- file.Read (&usVidcId);
-
- // Make sure we're in range.
- ASSERT(usVidcId < MAX_VID_CHANNELS);
- // Get corresponding header.
- PVIDC_RT_HDR pvidchdr = &m_avidchdrs[usVidcId];
- // If this is a header chunk . . .
- if (ucFlags & VIDC_CHUNK_HEADER)
- {
- // Handle header chunk.
- file.Read(&pvidchdr->sNumFrames);
- file.Read(&pvidchdr->sWidth);
- file.Read(&pvidchdr->sHeight);
- file.Read(&pvidchdr->sDepth);
- file.Read(&pvidchdr->lMilliPerFrame);
- file.Read(&pvidchdr->sNoDelta);
- file.Read(&pvidchdr->sTransparent);
- file.Read(&pvidchdr->sX);
- file.Read(&pvidchdr->sY);
- file.Read(&pvidchdr->ulFCCHandler);
-
- // Verify we didn't read too much.
- ASSERT(file.Error() == FALSE);
- // Initialize frame counter.
- pvidchdr->sCurFrame = 0;
- pvidchdr->sColorsModified = FALSE;
- // Default to one frame's worth of lag before skipping frames.
- pvidchdr->lMaxLag = pvidchdr->lMilliPerFrame;
- // Attempt to open desired compressor/decompressor . . .
- // pvidchdr->hic = ICOpen(ICTYPE_VIDEO, pvidchdr->ulFCCHandler,
- // ICMODE_FASTDECOMPRESS);
- // If there is a callback for the header . . .
- if (pvidchdr->callbackHeader != NULL)
- {
- // Pass user all info.
- (*pvidchdr->callbackHeader)(this, pvidchdr);
- }
- }
- else
- {
- // If there is a callback for before decompression . . .
- if (pvidchdr->callbackBefore != NULL)
- {
- // Pass user all info.
- (*pvidchdr->callbackBefore)(this, pvidchdr);
- }
- // Decompress into image if supplied.
- if (pvidchdr->pImage != NULL)
- {
- ASSERT(pvidchdr->pImage->pData != NULL);
- ASSERT(pvidchdr->pImage->pPalette != NULL);
- ASSERT(pvidchdr->pImage->pPalette->pData != NULL);
- ULONG ulFlags = 0;
- if (ucFlags & RT_FLAG_TAG)
- {
- // Key frame.
- }
- else
- {
- ulFlags |= ICDECOMPRESS_NOTKEYFRAME;
- }
- // If we've exceeded the maximum lag . . .
- if (m_pdispatch->GetTime() - lTime > pvidchdr->lMaxLag)
- {
- ulFlags |= ICDECOMPRESS_HURRYUP;
- }
- BMI bmiIn;
- BMI bmiOut;
- ReadBitmapInfo((BITMAPINFO*)&bmiIn, &file);
- ReadBitmapInfo((BITMAPINFO*)&bmiOut, &file);
- // TEMP
- bmiOut.bmiHeader.biHeight = bmiIn.bmiHeader.biHeight;
- bmiOut.bmiHeader.biSizeImage = (pvidchdr->pImage->lPitch
- * bmiOut.bmiHeader.biHeight
- * bmiOut.bmiHeader.biBitCount)
- / 8;
- // END TEMP
- if (pvidchdr->hic == NULL)
- {
- pvidchdr->hic = ICLocate( ICTYPE_VIDEO, pvidchdr->ulFCCHandler,
- &bmiIn.bmiHeader,
- &bmiOut.bmiHeader,
- ICMODE_FASTDECOMPRESS);
- if (pvidchdr->hic != NULL)
- {
- // Success.
- }
- else
- {
- TRACE("Use(): Unable to locate decompressor.\n");
- }
- }
- // Test.
- ASSERT(ICDecompressQuery(pvidchdr->hic,
- (BITMAPINFO*)&bmiIn,
- (BITMAPINFO*)&bmiOut) == ICERR_OK);
- if (ICDecompressSetPalette(pvidchdr->hic, &bmiOut) == ICERR_OK)
- {
- // Success.
- }
- else
- {
- TRACE("Use(): Unable to set decompressor palette.\n");
- sError = 7;
- }
- // The rest of this chunk is regular old VIDC data!
- if (DecompressFrame(pvidchdr, &file, ulFlags, &bmiIn, &bmiOut) == 0)
- {
- // Successfully decompressed frames.
- if (ICDecompressGetPalette(pvidchdr->hic,
- (BITMAPINFOHEADER*)&bmiIn,
- (BITMAPINFOHEADER*)&bmiOut) == ICERR_OK)
- {
- if (ucFlags & VIDC_CHUNK_PALETTE)
- {
- ASSERT(pvidchdr->pImage->pData != NULL);
- ASSERT(pvidchdr->pImage->pPalette != NULL);
- ASSERT(pvidchdr->pImage->pPalette->pData != NULL);
- CPal pal;
- pal.ulType = PDIB;
- pal.ulSize = bmiOut.bmiHeader.biSize - sizeof(bmiOut.bmiHeader);
- pal.sPalEntrySize = sizeof(bmiOut.bmiColors[0]);
- pal.pData = (UCHAR*)bmiOut.bmiColors;
- // Attach the palette to an empty image.
- CImage imageEmpty;
- imageEmpty.ulSize = 0L;
- imageEmpty.ulType = BMP8;
- imageEmpty.pPalette = &pal;
-
- // If necessary . . .
- if (pal.ulType != pvidchdr->pImage->pPalette->ulType)
- {
- // Attempt to convert to user image type . . .
- if (imageEmpty.Convert(pvidchdr->pImage->ulType) == 0)
- {
- // Successfully converted.
- }
- else
- {
- TRACE("Use(): Failed to convert temp palette data to "
- "user format.\n");
- sError = 3;
- }
- }
- // Copy converted data that the user cares about.
- memcpy( pvidchdr->pImage->pPalette->pData,
- pal.pData + pvidchdr->pImage->pPalette->sStartIndex
- * pvidchdr->pImage->pPalette->sPalEntrySize,
- pvidchdr->pImage->pPalette->sNumEntries
- * pvidchdr->pImage->pPalette->sPalEntrySize);
- imageEmpty.pPalette = NULL;
- pvidchdr->sColorsModified = TRUE;
- }
- else
- {
- pvidchdr->sColorsModified = FALSE;
- }
- }
- else
- {
- TRACE("Use(): Unable to get palette from decompressor.\n");
- sError = 6;
- }
- // If there is a callback for after decompression . . .
- if (pvidchdr->callbackAfter != NULL)
- {
- // Pass user all info.
- (*pvidchdr->callbackAfter)(this, pvidchdr);
- }
-
- // Increment frame count.
- pvidchdr->sCurFrame++;
- }
- else
- {
- TRACE("Use(): VIDC decompression failed.\n");
- sError = 1;
- }
- }
- else
- {
- TRACE("Use(): Data with no associated image.\n");
- }
- // If this is the last chunk . . .
- if (ucFlags & RT_FLAG_LAST)
- {
- // If compressor was opened . . .
- if (pvidchdr->hic != NULL)
- {
- ICClose(pvidchdr->hic);
- pvidchdr->hic = NULL;
- }
- }
-
- // Verify we didn't read too much.
- ASSERT(file.Error() == FALSE);
- }
- file.Close();
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Callback dispatcher (calls the implied this version).
- // (static)
- //
- //////////////////////////////////////////////////////////////////////////////
- short CRtVidc::UseStatic( UCHAR* puc, long lSize, USHORT usType,
- UCHAR ucFlags, long lTime, long l_pRtVidc)
- {
- return ((CRtVidc*)l_pRtVidc)->Use(puc, lSize, usType, ucFlags, lTime);
- }
- //////////////////////////////////////////////////////////////////////////////
- // Methods.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Set dispatcher.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetDispatcher(CDispatch* pdispatch)
- {
- if (m_pdispatch != NULL)
- {
- m_pdispatch->SetDataHandler(RT_TYPE_VIDC, NULL);
- }
- m_pdispatch = pdispatch;
- if (m_pdispatch != NULL)
- {
- m_pdispatch->SetDataHandler(RT_TYPE_VIDC, UseStatic);
- m_pdispatch->SetUserVal(RT_TYPE_VIDC, (long)this);
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets callback(s) called on channel header receipt.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetCallbackHeader(RTVIDC_CALL callback)
- {
- for (short i = 0; i < MAX_VID_CHANNELS; i++)
- {
- SetCallbackHeader(callback, i);
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets callback(s) called on channel header receipt.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetCallbackHeader(RTVIDC_CALL callback, short sChannel)
- {
- m_avidchdrs[sChannel].callbackHeader = callback;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets callback(s) called before decompression.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetCallbackBefore(RTVIDC_CALL callback)
- {
- for (short i = 0; i < MAX_VID_CHANNELS; i++)
- {
- SetCallbackBefore(callback, i);
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets callback(s) called before decompression.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetCallbackBefore(RTVIDC_CALL callback, short sChannel)
- {
- m_avidchdrs[sChannel].callbackBefore = callback;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets callback(s) called after decompression.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetCallbackAfter(RTVIDC_CALL callback)
- {
- for (short i = 0; i < MAX_VID_CHANNELS; i++)
- {
- SetCallbackAfter(callback, i);
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets callback(s) called after decompression.
- //
- //////////////////////////////////////////////////////////////////////////////
- void CRtVidc::SetCallbackAfter(RTVIDC_CALL callback, short sChannel)
- {
- m_avidchdrs[sChannel].callbackAfter = callback;
- }
- //////////////////////////////////////////////////////////////////////////////
- // EOF
- //////////////////////////////////////////////////////////////////////////////
|