FLICSource.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include "flicsource.h"
00024 #include "..\..\..\DSUtil\DSUtil.h"
00025 
00026 #ifdef REGISTER_FILTER
00027 
00028 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00029 {
00030         {&MEDIATYPE_Video, &MEDIASUBTYPE_RGB32},
00031 };
00032 
00033 const AMOVIESETUP_PIN sudOpPin[] =
00034 {
00035         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00036 };
00037 
00038 const AMOVIESETUP_FILTER sudFilter[] =
00039 {
00040         {&__uuidof(CFLICSource), L"FLICSource", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin}
00041 };
00042 
00043 CFactoryTemplate g_Templates[] =
00044 {
00045         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CFLICSource>, NULL, &sudFilter[0]}
00046 };
00047 
00048 int g_cTemplates = countof(g_Templates);
00049 
00050 STDAPI DllRegisterServer()
00051 {
00052         SetRegKeyValue(
00053                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"), 
00054                 _T("0"), _T("4,2,,11AF")); 
00055 
00056         SetRegKeyValue(
00057                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"), 
00058                 _T("1"), _T("4,2,,12AF"));
00059 
00060         SetRegKeyValue(
00061                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"), 
00062                 _T("Source Filter"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
00063 
00064         SetRegKeyValue(
00065                 _T("Media Type\\Extensions"), _T(".fli"), 
00066                 _T("Source Filter"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
00067 
00068         SetRegKeyValue(
00069                 _T("Media Type\\Extensions"), _T(".flc"), 
00070                 _T("Source Filter"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
00071 
00072         return AMovieDllRegisterServer2(TRUE);
00073 }
00074 
00075 STDAPI DllUnregisterServer()
00076 {
00077         DeleteRegKey(_T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
00078         DeleteRegKey(_T("Media Type\\Extensions"), _T(".fli"));
00079         DeleteRegKey(_T("Media Type\\Extensions"), _T(".flc"));
00080 
00081         return AMovieDllRegisterServer2(FALSE);
00082 }
00083 
00084 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00085 
00086 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00087 {
00088     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
00089 }
00090 
00091 #endif
00092 
00093 //
00094 // CFLICSource
00095 //
00096 
00097 CFLICSource::CFLICSource(LPUNKNOWN lpunk, HRESULT* phr)
00098         : CSource(NAME("CFLICSource"), lpunk, __uuidof(this))
00099 {
00100 }
00101 
00102 CFLICSource::~CFLICSource()
00103 {
00104 }
00105 
00106 STDMETHODIMP CFLICSource::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00107 {
00108     CheckPointer(ppv, E_POINTER);
00109 
00110         return 
00111                 QI(IFileSourceFilter)
00112                 QI(IAMFilterMiscFlags)
00113                 __super::NonDelegatingQueryInterface(riid, ppv);
00114 }
00115 
00116 // IFileSourceFilter
00117 
00118 STDMETHODIMP CFLICSource::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE* pmt) 
00119 {
00120         if(GetPinCount() > 0)
00121                 return VFW_E_ALREADY_CONNECTED;
00122 
00123         HRESULT hr = S_OK;
00124         if(!(new CFLICStream(pszFileName, this, &hr)))
00125                 return E_OUTOFMEMORY;
00126 
00127         if(FAILED(hr))
00128                 return hr;
00129 
00130         m_fn = pszFileName;
00131 
00132         return S_OK;
00133 }
00134 
00135 STDMETHODIMP CFLICSource::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt)
00136 {
00137         if(!ppszFileName) return E_POINTER;
00138         
00139         if(!(*ppszFileName = (LPOLESTR)CoTaskMemAlloc((m_fn.GetLength()+1)*sizeof(WCHAR))))
00140                 return E_OUTOFMEMORY;
00141 
00142         wcscpy(*ppszFileName, m_fn);
00143 
00144         return S_OK;
00145 }
00146 
00147 // IAMFilterMiscFlags
00148 
00149 ULONG CFLICSource::GetMiscFlags()
00150 {
00151         return AM_FILTER_MISC_FLAGS_IS_SOURCE;
00152 }
00153 
00154 // CFLICStream
00155 
00156 CFLICStream::CFLICStream(const WCHAR* wfn, CFLICSource* pParent, HRESULT* phr) 
00157         : CSourceStream(NAME("FLICStream"), phr, pParent, L"Output")
00158         , CSourceSeeking(NAME("FLICStream"), (IPin*)this, phr, &m_cSharedState)
00159         , m_bDiscontinuity(FALSE), m_bFlushing(FALSE)
00160 {
00161         CAutoLock cAutoLock(&m_cSharedState);
00162 
00163         CString fn(wfn);
00164 
00165         if(!m_flic.Open(fn, CFile::modeRead|CFile::shareDenyWrite))
00166         {
00167                 if(phr) *phr = E_FAIL;
00168                 return;
00169         }
00170 
00171         if(m_flic.Read(&m_hdr, sizeof(m_hdr)) != sizeof(m_hdr)
00172         || (m_hdr.id != 0xaf11 && m_hdr.id != 0xaf12)
00173         || m_hdr.bpp != 8)
00174         {
00175                 if(phr) *phr = E_FAIL;
00176                 return;
00177         }
00178 
00179         m_AvgTimePerFrame = (m_hdr.id == 0xaf11)
00180                 ? 10000000i64 * max(m_hdr.ticks, 1) / 70
00181                 : 10000000i64 * max(m_hdr.ticks, 1) / 1000;
00182 
00183         // not tested (lack of test files)
00184         {
00185                 __int64 pos = m_flic.GetPosition();
00186                 FLIC_PREFIX fp;
00187                 if(m_flic.Read(&fp, sizeof(fp)) != sizeof(fp) || fp.id != 0xf100) 
00188                         m_flic.Seek(pos, CFile::begin);
00189                 else
00190                         m_flic.Seek(pos + fp.size, CFile::begin);
00191         }
00192 
00193         do
00194         {
00195                 FLIC_FRAME_ENTRY ffe;
00196                 if(m_flic.Read(&ffe.hdr, sizeof(ffe.hdr)) != sizeof(ffe.hdr) || ffe.hdr.id != 0xf1fa) 
00197                         break;
00198                 ffe.pos = m_flic.GetPosition();
00199                 ffe.fKeyframe = (m_frames.GetCount() == 0);
00200 
00201                 int chunk = 0;
00202                 while(chunk < ffe.hdr.chunks)
00203                 {
00204                         FLIC_CHUNK fc;
00205                         if(m_flic.Read(&fc, sizeof(fc)) != sizeof(fc))
00206                                 break;
00207 /*
00208                         switch(fc.type)
00209                         {
00210                                 case FLIC_COLOR: _colorchunk(); break;
00211                                 case FLIC_256_COLOR: _color256chunk(); break;
00212                                 case FLIC_BRUN: _brunchunk(); break;
00213                                 case FLIC_LC: _lcchunk(); break;
00214                                 case FLIC_DELTA: _deltachunk(); break;
00215                                 case FLIC_BLACK: _blackchunk(); break;
00216                                 case FLIC_COPY: _copychunk(); break;
00217                                 case FLIC_MINI: break;
00218                                 default: break;
00219                         }
00220 */
00221                         ffe.fKeyframe = 
00222                                 (/*fc.type == FLIC_256_COLOR
00223                                 || fc.type == FLIC_64_COLOR
00224                                 ||*/ fc.type == FLIC_BRUN 
00225                                 || fc.type == FLIC_BLACK 
00226                                 || fc.type == FLIC_COPY);
00227 
00228                         __int64 pos = m_flic.GetPosition() + fc.size - sizeof(fc);
00229                         if(m_flic.Seek(pos, CFile::begin) != pos)
00230                                 break;
00231 
00232                         chunk++;
00233                 }
00234                 if(chunk < ffe.hdr.chunks)
00235                         break;
00236 
00237                 __int64 pos = ffe.pos + ffe.hdr.size - sizeof(ffe.hdr);
00238                 if(m_flic.Seek(pos, CFile::begin) != pos)
00239                         break;
00240 
00241                 m_frames.Add(ffe);
00242         }
00243         while(1);
00244 
00245         m_nLastFrameNum = -1;
00246         memset(m_pPalette, 0, sizeof(m_pPalette));
00247         if(!m_pFrameBuffer.Allocate(m_hdr.x*m_hdr.y*32>>3))
00248         {
00249                 if(phr) *phr = E_OUTOFMEMORY;
00250                 return;
00251         }
00252 
00253         m_rtDuration = m_rtStop = m_AvgTimePerFrame*m_frames.GetCount();
00254 
00255         if(phr) *phr = m_rtDuration > 0 ? S_OK : E_FAIL;
00256 }
00257 
00258 CFLICStream::~CFLICStream()
00259 {
00260         CAutoLock cAutoLock(&m_cSharedState);
00261 }
00262 
00263 STDMETHODIMP CFLICStream::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00264 {
00265     CheckPointer(ppv, E_POINTER);
00266 
00267         return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv) //GetInterface((IMediaSeeking*)this, ppv)
00268                 : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
00269 }
00270 
00271 void CFLICStream::UpdateFromSeek()
00272 {
00273         if(ThreadExists())
00274         {
00275                 // next time around the loop, the worker thread will
00276                 // pick up the position change.
00277                 // We need to flush all the existing data - we must do that here
00278                 // as our thread will probably be blocked in GetBuffer otherwise
00279             
00280                 m_bFlushing = TRUE;
00281 
00282                 DeliverBeginFlush();
00283                 // make sure we have stopped pushing
00284                 Stop();
00285                 // complete the flush
00286                 DeliverEndFlush();
00287 
00288         m_bFlushing = FALSE;
00289 
00290                 // restart
00291                 Run();
00292         }
00293 }
00294 
00295 HRESULT CFLICStream::SetRate(double dRate)
00296 {
00297         if(dRate <= 0)
00298                 return E_INVALIDARG;
00299 
00300         {
00301                 CAutoLock lock(CSourceSeeking::m_pLock);
00302                 m_dRateSeeking = dRate;
00303         }
00304 
00305         UpdateFromSeek();
00306 
00307         return S_OK;
00308 }
00309 
00310 HRESULT CFLICStream::OnThreadStartPlay()
00311 {
00312     m_bDiscontinuity = TRUE;
00313     return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
00314 }
00315 
00316 HRESULT CFLICStream::ChangeStart()
00317 {
00318     {
00319         CAutoLock lock(CSourceSeeking::m_pLock);
00320                 m_rtSampleTime = 0;
00321                 m_rtPosition = m_rtStart;
00322     }
00323 
00324     UpdateFromSeek();
00325 
00326     return S_OK;
00327 }
00328 
00329 HRESULT CFLICStream::ChangeStop()
00330 {
00331     {
00332         CAutoLock lock(CSourceSeeking::m_pLock);
00333         if(m_rtPosition < m_rtStop)
00334                         return S_OK;
00335     }
00336 
00337     // We're already past the new stop time -- better flush the graph.
00338     UpdateFromSeek();
00339 
00340     return S_OK;
00341 }
00342 
00343 HRESULT CFLICStream::OnThreadCreate()
00344 {
00345     CAutoLock cAutoLockShared(&m_cSharedState);
00346     m_rtSampleTime = 0;
00347     m_rtPosition = m_rtStart;
00348 
00349     return CSourceStream::OnThreadCreate();
00350 }
00351 
00352 HRESULT CFLICStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
00353 {
00354 //    CAutoLock cAutoLock(m_pFilter->pStateLock());
00355 
00356     ASSERT(pAlloc);
00357     ASSERT(pProperties);
00358 
00359     HRESULT hr = NOERROR;
00360 
00361         pProperties->cBuffers = 1;
00362         pProperties->cbBuffer = m_hdr.x*m_hdr.y*32>>3;
00363 
00364     ALLOCATOR_PROPERTIES Actual;
00365     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
00366 
00367     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
00368     ASSERT(Actual.cBuffers == pProperties->cBuffers);
00369 
00370     return NOERROR;
00371 }
00372 
00373 HRESULT CFLICStream::FillBuffer(IMediaSample* pSample)
00374 {
00375         HRESULT hr;
00376 
00377         {
00378                 CAutoLock cAutoLockShared(&m_cSharedState);
00379 
00380         if(m_rtPosition >= m_rtStop)
00381                         return S_FALSE;
00382 
00383                 BYTE* pDataIn = m_pFrameBuffer;
00384                 BYTE* pDataOut = NULL;
00385                 if(!pDataIn || FAILED(hr = pSample->GetPointer(&pDataOut)) || !pDataOut)
00386                         return S_FALSE;
00387 
00388                 AM_MEDIA_TYPE* pmt;
00389                 if(SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt)
00390                 {
00391                         CMediaType mt(*pmt);
00392                         SetMediaType(&mt);
00393 
00394                         DeleteMediaType(pmt);
00395                 }
00396 
00397                 int w, h, bpp;
00398                 if(m_mt.formattype == FORMAT_VideoInfo)
00399                 {
00400                         w = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biWidth;
00401                         h = abs(((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biHeight);
00402                         bpp = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biBitCount;
00403                 }
00404                 else if(m_mt.formattype == FORMAT_VideoInfo2)
00405                 {
00406                         w = ((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biWidth;
00407                         h = abs(((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biHeight);
00408                         bpp = ((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biBitCount;
00409                 }
00410                 else
00411                 {
00412                         return S_FALSE;
00413                 }
00414 
00415                 int pitchIn = m_hdr.x;
00416                 int pitchOut = w*bpp>>3;
00417 
00418                 int nFrame = m_rtPosition / m_AvgTimePerFrame; // (int)(1.0 * m_rtPosition / m_AvgTimePerFrame + 0.5);
00419 
00420                 {
00421                         SeekToNearestKeyFrame(nFrame);
00422 
00423                         while(m_nLastFrameNum < nFrame && !m_bFlushing)
00424                                 ExtractFrame(++m_nLastFrameNum);
00425 
00426                         for(int y = 0, p = min(pitchIn, pitchOut); 
00427                                 y < h; 
00428                                 y++, pDataIn += pitchIn, pDataOut += pitchOut)
00429                         {
00430                                 BYTE* src = pDataIn;
00431                                 BYTE* end = src + p;
00432                                 DWORD* dst = (DWORD*)pDataOut;
00433                                 while(src < end) *dst++ = m_pPalette[*src++];
00434                         }
00435                 }
00436 
00437                 pSample->SetActualDataLength(pitchOut*h);
00438 
00439                 REFERENCE_TIME rtStart, rtStop;
00440         // The sample times are modified by the current rate.
00441         rtStart = static_cast<REFERENCE_TIME>(m_rtSampleTime / m_dRateSeeking);
00442         rtStop  = rtStart + static_cast<int>(m_AvgTimePerFrame / m_dRateSeeking);
00443         pSample->SetTime(&rtStart, &rtStop);
00444 
00445         m_rtSampleTime += m_AvgTimePerFrame;
00446         m_rtPosition += m_AvgTimePerFrame;
00447         }
00448 
00449         pSample->SetSyncPoint(TRUE);
00450 
00451         if(m_bDiscontinuity) 
00452     {
00453                 pSample->SetDiscontinuity(TRUE);
00454                 m_bDiscontinuity = FALSE;
00455         }
00456 
00457         return S_OK;
00458 }
00459 
00460 HRESULT CFLICStream::GetMediaType(int iPosition, CMediaType* pmt)
00461 {
00462     CAutoLock cAutoLock(m_pFilter->pStateLock());
00463 
00464     if(iPosition < 0) return E_INVALIDARG;
00465     if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
00466 
00467     pmt->SetType(&MEDIATYPE_Video);
00468     pmt->SetSubtype(&MEDIASUBTYPE_RGB32);
00469     pmt->SetFormatType(&FORMAT_VideoInfo);
00470     pmt->SetTemporalCompression(TRUE);
00471 
00472         VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00473         memset(vih, 0, sizeof(VIDEOINFOHEADER));
00474         vih->AvgTimePerFrame = m_AvgTimePerFrame;
00475         vih->bmiHeader.biSize = sizeof(vih->bmiHeader);
00476         vih->bmiHeader.biWidth = m_hdr.x;
00477         vih->bmiHeader.biHeight = -m_hdr.y;
00478         vih->bmiHeader.biPlanes = 1;
00479         vih->bmiHeader.biBitCount = 32;
00480         vih->bmiHeader.biCompression = BI_RGB;
00481         vih->bmiHeader.biSizeImage = m_hdr.x*m_hdr.y*32>>3;
00482 
00483         pmt->SetSampleSize(vih->bmiHeader.biSizeImage);
00484 
00485     return NOERROR;
00486 }
00487 
00488 HRESULT CFLICStream::CheckConnect(IPin* pPin)
00489 {
00490         return CSourceStream::CheckConnect(pPin);
00491 }
00492 
00493 HRESULT CFLICStream::CheckMediaType(const CMediaType* pmt)
00494 {
00495         if(pmt->majortype == MEDIATYPE_Video
00496         && pmt->subtype == MEDIASUBTYPE_RGB32
00497         && pmt->formattype == FORMAT_VideoInfo) return S_OK;
00498 
00499         return E_INVALIDARG;
00500 }
00501 
00502 STDMETHODIMP CFLICStream::Notify(IBaseFilter* pSender, Quality q)
00503 {
00504         return E_NOTIMPL;
00505 }
00506 
00508 
00509 void CFLICStream::SeekToNearestKeyFrame(int nFrame)
00510 {
00511         if(m_nLastFrameNum == nFrame)
00512                 return;
00513 
00514         if(m_nLastFrameNum > nFrame)
00515                 m_nLastFrameNum = -1;
00516 
00517         for(int i = m_nLastFrameNum+1, j = min(m_frames.GetCount(), nFrame); i < j; i++)
00518         {
00519                 FLIC_FRAME_ENTRY& ffe = m_frames[i];
00520                 if(ffe.fKeyframe) 
00521                         m_nLastFrameNum = i-1;
00522         }
00523 }
00524 
00525 void CFLICStream::ExtractFrame(int nFrame)
00526 {
00527         FLIC_FRAME_ENTRY& ffe = m_frames[nFrame];
00528 
00529         bool fNewPalette = false;
00530         bool fNewFrame = false;
00531 
00532         m_flic.Seek(ffe.pos, CFile::begin);
00533 
00534         int chunk = 0;
00535         while(chunk < ffe.hdr.chunks)
00536         {
00537                 FLIC_CHUNK fc;
00538                 if(m_flic.Read(&fc, sizeof(fc)) != sizeof(fc))
00539                         break;
00540 
00541                 __int64 next = m_flic.GetPosition() + fc.size - sizeof(fc);
00542 
00543                 switch(fc.type)
00544                 {
00545                         case FLIC_64_COLOR: fNewPalette = _colorchunk(true); break;
00546                         case FLIC_256_COLOR: fNewPalette = _colorchunk(false); break;
00547                         case FLIC_BRUN: _brunchunk(); fNewFrame = true; break;
00548                         case FLIC_LC: _lcchunk(); break;
00549                         case FLIC_DELTA: _deltachunk(); break;
00550                         case FLIC_BLACK: _blackchunk(); fNewFrame = true; break;
00551                         case FLIC_COPY: _copychunk(); fNewFrame = true; break;
00552                         case FLIC_MINI: break;
00553                         default: break;
00554                 }
00555 
00556                 if(m_flic.Seek(next, CFile::begin) != next)
00557                         break;
00558 
00559                 chunk++;
00560         }
00561 
00562         if(chunk < ffe.hdr.chunks)
00563                 ASSERT(0);
00564 
00565         ffe.fKeyframe = (fNewPalette && fNewFrame);
00566 }
00567 
00568 void CFLICStream::_blackchunk()
00569 {
00570         memset(m_pFrameBuffer, 0, m_hdr.x*m_hdr.y*32>>3);
00571 }
00572 
00573 void CFLICStream::_copychunk()
00574 {
00575         m_flic.Read(m_pFrameBuffer, m_hdr.x*m_hdr.y*32>>3);
00576 }
00577 
00578 bool CFLICStream::_colorchunk(bool f64)
00579 {
00580         int nColorsUpdated = 0;
00581 
00582         BYTE skip = 0;
00583 
00584         WORD packets;
00585         m_flic.Read(&packets, sizeof(packets));
00586 
00587         while(packets--)
00588         {
00589                 BYTE skip2;
00590                 m_flic.Read(&skip2, sizeof(skip2));
00591                 skip += skip2;
00592 
00593                 BYTE count;
00594                 m_flic.Read(&count, sizeof(count));
00595 
00596                 int len = (count == 0 ? (256-skip) : count);
00597                 while(len-- > 0)
00598                 {
00599                         BYTE r, g, b;
00600                         m_flic.Read(&r, sizeof(r));
00601                         m_flic.Read(&g, sizeof(g));
00602                         m_flic.Read(&b, sizeof(b));
00603                         m_pPalette[skip++] = f64 
00604                                 ? ((r << 18)&0xff0000) | ((g << 10)&0xff00) | ((b << 2)&0xff)
00605                                 : ((r << 16)&0xff0000) | ((g << 8)&0xff00) | ((b << 0)&0xff);
00606                         nColorsUpdated++;
00607                 }
00608         }
00609 
00610         return(nColorsUpdated == 256);
00611 }
00612 
00613 void CFLICStream::_brunchunk()
00614 {
00615         BYTE* tmp = m_pFrameBuffer;
00616 
00617         int lines = m_hdr.y;
00618         while(lines--)
00619         {
00620                 BYTE packets;
00621                 m_flic.Read(&packets, sizeof(packets));
00622                 
00623                 BYTE* ptr = tmp;
00624 
00625                 while(ptr < tmp + m_hdr.x)
00626                 {
00627                         signed char count;
00628                         m_flic.Read(&count, sizeof(count));
00629 
00630                         if(count >= 0)
00631                         {
00632                                 BYTE c;
00633                                 m_flic.Read(&c, sizeof(c));
00634                                 memset(ptr, c, count);
00635                                 ptr += count;
00636                         }
00637                         else
00638                         {
00639                                 m_flic.Read(ptr, -count);
00640                                 ptr += -count;
00641                         }
00642                 }
00643 
00644                 tmp += m_hdr.x;
00645         }
00646 }
00647 
00648 void CFLICStream::_lcchunk()
00649 {
00650         WORD y;
00651         m_flic.Read(&y, sizeof(y));
00652 
00653         BYTE* tmp = &m_pFrameBuffer[y*m_hdr.x];
00654 
00655         WORD lines;
00656         m_flic.Read(&lines, sizeof(lines));
00657 
00658         while(lines--)
00659         {
00660                 BYTE* ptr = tmp;
00661 
00662                 BYTE packets;
00663                 m_flic.Read(&packets, sizeof(packets));
00664 
00665                 while(packets--)
00666                 {
00667                         BYTE skip;
00668                         m_flic.Read(&skip, sizeof(skip));
00669 
00670                         ptr += skip;
00671 
00672                         signed char count;
00673                         m_flic.Read(&count, sizeof(count));
00674 
00675                         if(count >= 0)
00676                         {
00677                                 m_flic.Read(ptr, count);
00678                                 ptr += count;
00679                         }
00680                         else
00681                         {
00682                                 BYTE c;
00683                                 m_flic.Read(&c, sizeof(c));
00684                                 memset(ptr, c, -count);
00685                                 ptr += -count;
00686                         }
00687                 }
00688 
00689                 tmp += m_hdr.x;
00690         }
00691 }
00692 
00693 void CFLICStream::_deltachunk()
00694 {
00695         BYTE* tmp = m_pFrameBuffer;
00696 
00697         WORD lines;
00698         m_flic.Read(&lines, sizeof(lines));
00699 
00700         while(lines--)
00701         {
00702                 signed short packets;
00703                 m_flic.Read(&packets, sizeof(packets));
00704 
00705                 if(packets < 0)
00706                 {
00707                         if(packets&0x4000)
00708                         {
00709                                 tmp += -packets * m_hdr.x;
00710                                 lines++;
00711                         }
00712                         else
00713                         {
00714                                 signed char count;
00715                                 m_flic.Read(&count, sizeof(count));
00716                                 tmp[m_hdr.x-1] = (BYTE)packets;
00717                         }
00718                 }
00719                 else
00720                 {
00721                         BYTE* ptr = tmp;
00722 
00723                         while(packets--)
00724                         {
00725                                 BYTE skip;
00726                                 m_flic.Read(&skip, sizeof(skip));
00727 
00728                                 ptr += skip;
00729 
00730                                 signed char count;
00731                                 m_flic.Read(&count, sizeof(count));
00732 
00733                                 if(count >= 0)
00734                                 {
00735                                         m_flic.Read(ptr, count << 1);
00736                                         ptr += count << 1;
00737                                 }
00738                                 else
00739                                 {
00740                                         WORD c;
00741                                         m_flic.Read(&c, sizeof(c));
00742                                         count = -count;
00743                                         while(count-- > 0)
00744                                         {
00745                                                 *ptr++ = c>>8;
00746                                                 *ptr++ = c&0xff;
00747                                         }
00748                                 }
00749                         }
00750 
00751                         tmp += m_hdr.x;
00752                 }
00753         }
00754 }

Generated on Tue Dec 13 14:47:25 2005 for guliverkli by  doxygen 1.4.5