00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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);
00089 }
00090
00091 #endif
00092
00093
00094
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
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
00148
00149 ULONG CFLICSource::GetMiscFlags()
00150 {
00151 return AM_FILTER_MISC_FLAGS_IS_SOURCE;
00152 }
00153
00154
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
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
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 ffe.fKeyframe =
00222 (
00223
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)
00268 : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
00269 }
00270
00271 void CFLICStream::UpdateFromSeek()
00272 {
00273 if(ThreadExists())
00274 {
00275
00276
00277
00278
00279
00280 m_bFlushing = TRUE;
00281
00282 DeliverBeginFlush();
00283
00284 Stop();
00285
00286 DeliverEndFlush();
00287
00288 m_bFlushing = FALSE;
00289
00290
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
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
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;
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
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 }