- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }