FLICSource.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:17k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "flicsource.h"
  23. #include "......DSUtilDSUtil.h"
  24. #ifdef REGISTER_FILTER
  25. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  26. {
  27. {&MEDIATYPE_Video, &MEDIASUBTYPE_RGB32},
  28. };
  29. const AMOVIESETUP_PIN sudOpPin[] =
  30. {
  31. {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
  32. };
  33. const AMOVIESETUP_FILTER sudFilter[] =
  34. {
  35. {&__uuidof(CFLICSource), L"FLICSource", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin}
  36. };
  37. CFactoryTemplate g_Templates[] =
  38. {
  39. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CFLICSource>, NULL, &sudFilter[0]}
  40. };
  41. int g_cTemplates = countof(g_Templates);
  42. STDAPI DllRegisterServer()
  43. {
  44. SetRegKeyValue(
  45. _T("Media Type\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"), 
  46. _T("0"), _T("4,2,,11AF")); 
  47. SetRegKeyValue(
  48. _T("Media Type\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"), 
  49. _T("1"), _T("4,2,,12AF"));
  50. SetRegKeyValue(
  51. _T("Media Type\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"), 
  52. _T("Source Filter"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
  53. SetRegKeyValue(
  54. _T("Media Type\Extensions"), _T(".fli"), 
  55. _T("Source Filter"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
  56. SetRegKeyValue(
  57. _T("Media Type\Extensions"), _T(".flc"), 
  58. _T("Source Filter"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
  59. return AMovieDllRegisterServer2(TRUE);
  60. }
  61. STDAPI DllUnregisterServer()
  62. {
  63. DeleteRegKey(_T("Media Type\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{17DB5CF6-39BB-4d5b-B0AA-BEBA44673AD4}"));
  64. DeleteRegKey(_T("Media Type\Extensions"), _T(".fli"));
  65. DeleteRegKey(_T("Media Type\Extensions"), _T(".flc"));
  66. return AMovieDllRegisterServer2(FALSE);
  67. }
  68. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  69. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  70. {
  71.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  72. }
  73. #endif
  74. //
  75. // CFLICSource
  76. //
  77. CFLICSource::CFLICSource(LPUNKNOWN lpunk, HRESULT* phr)
  78. : CSource(NAME("CFLICSource"), lpunk, __uuidof(this))
  79. {
  80. }
  81. CFLICSource::~CFLICSource()
  82. {
  83. }
  84. STDMETHODIMP CFLICSource::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  85. {
  86.     CheckPointer(ppv, E_POINTER);
  87. return 
  88. QI(IFileSourceFilter)
  89. QI(IAMFilterMiscFlags)
  90. __super::NonDelegatingQueryInterface(riid, ppv);
  91. }
  92. // IFileSourceFilter
  93. STDMETHODIMP CFLICSource::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE* pmt) 
  94. {
  95. if(GetPinCount() > 0)
  96. return VFW_E_ALREADY_CONNECTED;
  97. HRESULT hr = S_OK;
  98. if(!(new CFLICStream(pszFileName, this, &hr)))
  99. return E_OUTOFMEMORY;
  100. if(FAILED(hr))
  101. return hr;
  102. m_fn = pszFileName;
  103. return S_OK;
  104. }
  105. STDMETHODIMP CFLICSource::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt)
  106. {
  107. if(!ppszFileName) return E_POINTER;
  108. if(!(*ppszFileName = (LPOLESTR)CoTaskMemAlloc((m_fn.GetLength()+1)*sizeof(WCHAR))))
  109. return E_OUTOFMEMORY;
  110. wcscpy(*ppszFileName, m_fn);
  111. return S_OK;
  112. }
  113. // IAMFilterMiscFlags
  114. ULONG CFLICSource::GetMiscFlags()
  115. {
  116. return AM_FILTER_MISC_FLAGS_IS_SOURCE;
  117. }
  118. // CFLICStream
  119. CFLICStream::CFLICStream(const WCHAR* wfn, CFLICSource* pParent, HRESULT* phr) 
  120. : CSourceStream(NAME("FLICStream"), phr, pParent, L"Output")
  121. , CSourceSeeking(NAME("FLICStream"), (IPin*)this, phr, &m_cSharedState)
  122. , m_bDiscontinuity(FALSE), m_bFlushing(FALSE)
  123. {
  124. CAutoLock cAutoLock(&m_cSharedState);
  125. CString fn(wfn);
  126. if(!m_flic.Open(fn, CFile::modeRead|CFile::shareDenyWrite))
  127. {
  128. if(phr) *phr = E_FAIL;
  129. return;
  130. }
  131. if(m_flic.Read(&m_hdr, sizeof(m_hdr)) != sizeof(m_hdr)
  132. || (m_hdr.id != 0xaf11 && m_hdr.id != 0xaf12)
  133. || m_hdr.bpp != 8)
  134. {
  135. if(phr) *phr = E_FAIL;
  136. return;
  137. }
  138. m_AvgTimePerFrame = (m_hdr.id == 0xaf11)
  139. ? 10000000i64 * max(m_hdr.ticks, 1) / 70
  140. : 10000000i64 * max(m_hdr.ticks, 1) / 1000;
  141. // not tested (lack of test files)
  142. {
  143. __int64 pos = m_flic.GetPosition();
  144. FLIC_PREFIX fp;
  145. if(m_flic.Read(&fp, sizeof(fp)) != sizeof(fp) || fp.id != 0xf100) 
  146. m_flic.Seek(pos, CFile::begin);
  147. else
  148. m_flic.Seek(pos + fp.size, CFile::begin);
  149. }
  150. do
  151. {
  152. FLIC_FRAME_ENTRY ffe;
  153. if(m_flic.Read(&ffe.hdr, sizeof(ffe.hdr)) != sizeof(ffe.hdr) || ffe.hdr.id != 0xf1fa) 
  154. break;
  155. ffe.pos = m_flic.GetPosition();
  156. ffe.fKeyframe = (m_frames.GetCount() == 0);
  157. int chunk = 0;
  158. while(chunk < ffe.hdr.chunks)
  159. {
  160. FLIC_CHUNK fc;
  161. if(m_flic.Read(&fc, sizeof(fc)) != sizeof(fc))
  162. break;
  163. /*
  164. switch(fc.type)
  165. {
  166. case FLIC_COLOR: _colorchunk(); break;
  167. case FLIC_256_COLOR: _color256chunk(); break;
  168. case FLIC_BRUN: _brunchunk(); break;
  169. case FLIC_LC: _lcchunk(); break;
  170. case FLIC_DELTA: _deltachunk(); break;
  171. case FLIC_BLACK: _blackchunk(); break;
  172. case FLIC_COPY: _copychunk(); break;
  173. case FLIC_MINI: break;
  174. default: break;
  175. }
  176. */
  177. ffe.fKeyframe = 
  178. (/*fc.type == FLIC_256_COLOR
  179. || fc.type == FLIC_64_COLOR
  180. ||*/ fc.type == FLIC_BRUN 
  181. || fc.type == FLIC_BLACK 
  182. || fc.type == FLIC_COPY);
  183. __int64 pos = m_flic.GetPosition() + fc.size - sizeof(fc);
  184. if(m_flic.Seek(pos, CFile::begin) != pos)
  185. break;
  186. chunk++;
  187. }
  188. if(chunk < ffe.hdr.chunks)
  189. break;
  190. __int64 pos = ffe.pos + ffe.hdr.size - sizeof(ffe.hdr);
  191. if(m_flic.Seek(pos, CFile::begin) != pos)
  192. break;
  193. m_frames.Add(ffe);
  194. }
  195. while(1);
  196. m_nLastFrameNum = -1;
  197. memset(m_pPalette, 0, sizeof(m_pPalette));
  198. if(!m_pFrameBuffer.Allocate(m_hdr.x*m_hdr.y*32>>3))
  199. {
  200. if(phr) *phr = E_OUTOFMEMORY;
  201. return;
  202. }
  203. m_rtDuration = m_rtStop = m_AvgTimePerFrame*m_frames.GetCount();
  204. if(phr) *phr = m_rtDuration > 0 ? S_OK : E_FAIL;
  205. }
  206. CFLICStream::~CFLICStream()
  207. {
  208. CAutoLock cAutoLock(&m_cSharedState);
  209. }
  210. STDMETHODIMP CFLICStream::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  211. {
  212.     CheckPointer(ppv, E_POINTER);
  213. return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv) //GetInterface((IMediaSeeking*)this, ppv)
  214. : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
  215. }
  216. void CFLICStream::UpdateFromSeek()
  217. {
  218. if(ThreadExists())
  219. {
  220. // next time around the loop, the worker thread will
  221. // pick up the position change.
  222. // We need to flush all the existing data - we must do that here
  223. // as our thread will probably be blocked in GetBuffer otherwise
  224.     
  225. m_bFlushing = TRUE;
  226. DeliverBeginFlush();
  227. // make sure we have stopped pushing
  228. Stop();
  229. // complete the flush
  230. DeliverEndFlush();
  231.         m_bFlushing = FALSE;
  232. // restart
  233. Run();
  234. }
  235. }
  236. HRESULT CFLICStream::SetRate(double dRate)
  237. {
  238. if(dRate <= 0)
  239. return E_INVALIDARG;
  240. {
  241. CAutoLock lock(CSourceSeeking::m_pLock);
  242. m_dRateSeeking = dRate;
  243. }
  244. UpdateFromSeek();
  245. return S_OK;
  246. }
  247. HRESULT CFLICStream::OnThreadStartPlay()
  248. {
  249.     m_bDiscontinuity = TRUE;
  250.     return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
  251. }
  252. HRESULT CFLICStream::ChangeStart()
  253. {
  254.     {
  255.         CAutoLock lock(CSourceSeeking::m_pLock);
  256. m_rtSampleTime = 0;
  257. m_rtPosition = m_rtStart;
  258.     }
  259.     UpdateFromSeek();
  260.     return S_OK;
  261. }
  262. HRESULT CFLICStream::ChangeStop()
  263. {
  264.     {
  265.         CAutoLock lock(CSourceSeeking::m_pLock);
  266.         if(m_rtPosition < m_rtStop)
  267. return S_OK;
  268.     }
  269.     // We're already past the new stop time -- better flush the graph.
  270.     UpdateFromSeek();
  271.     return S_OK;
  272. }
  273. HRESULT CFLICStream::OnThreadCreate()
  274. {
  275.     CAutoLock cAutoLockShared(&m_cSharedState);
  276.     m_rtSampleTime = 0;
  277.     m_rtPosition = m_rtStart;
  278.     return CSourceStream::OnThreadCreate();
  279. }
  280. HRESULT CFLICStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
  281. {
  282. //    CAutoLock cAutoLock(m_pFilter->pStateLock());
  283.     ASSERT(pAlloc);
  284.     ASSERT(pProperties);
  285.     HRESULT hr = NOERROR;
  286. pProperties->cBuffers = 1;
  287. pProperties->cbBuffer = m_hdr.x*m_hdr.y*32>>3;
  288.     ALLOCATOR_PROPERTIES Actual;
  289.     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
  290.     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
  291.     ASSERT(Actual.cBuffers == pProperties->cBuffers);
  292.     return NOERROR;
  293. }
  294. HRESULT CFLICStream::FillBuffer(IMediaSample* pSample)
  295. {
  296. HRESULT hr;
  297. {
  298. CAutoLock cAutoLockShared(&m_cSharedState);
  299.         if(m_rtPosition >= m_rtStop)
  300. return S_FALSE;
  301. BYTE* pDataIn = m_pFrameBuffer;
  302. BYTE* pDataOut = NULL;
  303. if(!pDataIn || FAILED(hr = pSample->GetPointer(&pDataOut)) || !pDataOut)
  304. return S_FALSE;
  305. AM_MEDIA_TYPE* pmt;
  306. if(SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt)
  307. {
  308. CMediaType mt(*pmt);
  309. SetMediaType(&mt);
  310. DeleteMediaType(pmt);
  311. }
  312. int w, h, bpp;
  313. if(m_mt.formattype == FORMAT_VideoInfo)
  314. {
  315. w = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biWidth;
  316. h = abs(((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biHeight);
  317. bpp = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biBitCount;
  318. }
  319. else if(m_mt.formattype == FORMAT_VideoInfo2)
  320. {
  321. w = ((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biWidth;
  322. h = abs(((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biHeight);
  323. bpp = ((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biBitCount;
  324. }
  325. else
  326. {
  327. return S_FALSE;
  328. }
  329. int pitchIn = m_hdr.x;
  330. int pitchOut = w*bpp>>3;
  331. int nFrame = m_rtPosition / m_AvgTimePerFrame; // (int)(1.0 * m_rtPosition / m_AvgTimePerFrame + 0.5);
  332. {
  333. SeekToNearestKeyFrame(nFrame);
  334. while(m_nLastFrameNum < nFrame && !m_bFlushing)
  335. ExtractFrame(++m_nLastFrameNum);
  336. for(int y = 0, p = min(pitchIn, pitchOut); 
  337. y < h; 
  338. y++, pDataIn += pitchIn, pDataOut += pitchOut)
  339. {
  340. BYTE* src = pDataIn;
  341. BYTE* end = src + p;
  342. DWORD* dst = (DWORD*)pDataOut;
  343. while(src < end) *dst++ = m_pPalette[*src++];
  344. }
  345. }
  346. pSample->SetActualDataLength(pitchOut*h);
  347. REFERENCE_TIME rtStart, rtStop;
  348.         // The sample times are modified by the current rate.
  349.         rtStart = static_cast<REFERENCE_TIME>(m_rtSampleTime / m_dRateSeeking);
  350.         rtStop  = rtStart + static_cast<int>(m_AvgTimePerFrame / m_dRateSeeking);
  351.         pSample->SetTime(&rtStart, &rtStop);
  352.         m_rtSampleTime += m_AvgTimePerFrame;
  353.         m_rtPosition += m_AvgTimePerFrame;
  354. }
  355. pSample->SetSyncPoint(TRUE);
  356. if(m_bDiscontinuity) 
  357.     {
  358. pSample->SetDiscontinuity(TRUE);
  359. m_bDiscontinuity = FALSE;
  360. }
  361. return S_OK;
  362. }
  363. HRESULT CFLICStream::GetMediaType(int iPosition, CMediaType* pmt)
  364. {
  365.     CAutoLock cAutoLock(m_pFilter->pStateLock());
  366.     if(iPosition < 0) return E_INVALIDARG;
  367.     if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
  368.     pmt->SetType(&MEDIATYPE_Video);
  369.     pmt->SetSubtype(&MEDIASUBTYPE_RGB32);
  370.     pmt->SetFormatType(&FORMAT_VideoInfo);
  371.     pmt->SetTemporalCompression(TRUE);
  372. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  373. memset(vih, 0, sizeof(VIDEOINFOHEADER));
  374. vih->AvgTimePerFrame = m_AvgTimePerFrame;
  375. vih->bmiHeader.biSize = sizeof(vih->bmiHeader);
  376. vih->bmiHeader.biWidth = m_hdr.x;
  377. vih->bmiHeader.biHeight = -m_hdr.y;
  378. vih->bmiHeader.biPlanes = 1;
  379. vih->bmiHeader.biBitCount = 32;
  380. vih->bmiHeader.biCompression = BI_RGB;
  381. vih->bmiHeader.biSizeImage = m_hdr.x*m_hdr.y*32>>3;
  382. pmt->SetSampleSize(vih->bmiHeader.biSizeImage);
  383.     return NOERROR;
  384. }
  385. HRESULT CFLICStream::CheckConnect(IPin* pPin)
  386. {
  387. return CSourceStream::CheckConnect(pPin);
  388. }
  389. HRESULT CFLICStream::CheckMediaType(const CMediaType* pmt)
  390. {
  391. if(pmt->majortype == MEDIATYPE_Video
  392. && pmt->subtype == MEDIASUBTYPE_RGB32
  393. && pmt->formattype == FORMAT_VideoInfo) return S_OK;
  394. return E_INVALIDARG;
  395. }
  396. STDMETHODIMP CFLICStream::Notify(IBaseFilter* pSender, Quality q)
  397. {
  398. return E_NOTIMPL;
  399. }
  400. ////////
  401. void CFLICStream::SeekToNearestKeyFrame(int nFrame)
  402. {
  403. if(m_nLastFrameNum == nFrame)
  404. return;
  405. if(m_nLastFrameNum > nFrame)
  406. m_nLastFrameNum = -1;
  407. for(int i = m_nLastFrameNum+1, j = min(m_frames.GetCount(), nFrame); i < j; i++)
  408. {
  409. FLIC_FRAME_ENTRY& ffe = m_frames[i];
  410. if(ffe.fKeyframe) 
  411. m_nLastFrameNum = i-1;
  412. }
  413. }
  414. void CFLICStream::ExtractFrame(int nFrame)
  415. {
  416. FLIC_FRAME_ENTRY& ffe = m_frames[nFrame];
  417. bool fNewPalette = false;
  418. bool fNewFrame = false;
  419. m_flic.Seek(ffe.pos, CFile::begin);
  420. int chunk = 0;
  421. while(chunk < ffe.hdr.chunks)
  422. {
  423. FLIC_CHUNK fc;
  424. if(m_flic.Read(&fc, sizeof(fc)) != sizeof(fc))
  425. break;
  426. __int64 next = m_flic.GetPosition() + fc.size - sizeof(fc);
  427. switch(fc.type)
  428. {
  429. case FLIC_64_COLOR: fNewPalette = _colorchunk(true); break;
  430. case FLIC_256_COLOR: fNewPalette = _colorchunk(false); break;
  431. case FLIC_BRUN: _brunchunk(); fNewFrame = true; break;
  432. case FLIC_LC: _lcchunk(); break;
  433. case FLIC_DELTA: _deltachunk(); break;
  434. case FLIC_BLACK: _blackchunk(); fNewFrame = true; break;
  435. case FLIC_COPY: _copychunk(); fNewFrame = true; break;
  436. case FLIC_MINI: break;
  437. default: break;
  438. }
  439. if(m_flic.Seek(next, CFile::begin) != next)
  440. break;
  441. chunk++;
  442. }
  443. if(chunk < ffe.hdr.chunks)
  444. ASSERT(0);
  445. ffe.fKeyframe = (fNewPalette && fNewFrame);
  446. }
  447. void CFLICStream::_blackchunk()
  448. {
  449. memset(m_pFrameBuffer, 0, m_hdr.x*m_hdr.y*32>>3);
  450. }
  451. void CFLICStream::_copychunk()
  452. {
  453. m_flic.Read(m_pFrameBuffer, m_hdr.x*m_hdr.y*32>>3);
  454. }
  455. bool CFLICStream::_colorchunk(bool f64)
  456. {
  457. int nColorsUpdated = 0;
  458. BYTE skip = 0;
  459. WORD packets;
  460. m_flic.Read(&packets, sizeof(packets));
  461. while(packets--)
  462. {
  463. BYTE skip2;
  464. m_flic.Read(&skip2, sizeof(skip2));
  465. skip += skip2;
  466. BYTE count;
  467. m_flic.Read(&count, sizeof(count));
  468. int len = (count == 0 ? (256-skip) : count);
  469. while(len-- > 0)
  470. {
  471. BYTE r, g, b;
  472. m_flic.Read(&r, sizeof(r));
  473. m_flic.Read(&g, sizeof(g));
  474. m_flic.Read(&b, sizeof(b));
  475. m_pPalette[skip++] = f64 
  476. ? ((r << 18)&0xff0000) | ((g << 10)&0xff00) | ((b << 2)&0xff)
  477. : ((r << 16)&0xff0000) | ((g << 8)&0xff00) | ((b << 0)&0xff);
  478. nColorsUpdated++;
  479. }
  480. }
  481. return(nColorsUpdated == 256);
  482. }
  483. void CFLICStream::_brunchunk()
  484. {
  485. BYTE* tmp = m_pFrameBuffer;
  486. int lines = m_hdr.y;
  487. while(lines--)
  488. {
  489. BYTE packets;
  490. m_flic.Read(&packets, sizeof(packets));
  491. BYTE* ptr = tmp;
  492. while(ptr < tmp + m_hdr.x)
  493. {
  494. signed char count;
  495. m_flic.Read(&count, sizeof(count));
  496. if(count >= 0)
  497. {
  498. BYTE c;
  499. m_flic.Read(&c, sizeof(c));
  500. memset(ptr, c, count);
  501. ptr += count;
  502. }
  503. else
  504. {
  505. m_flic.Read(ptr, -count);
  506. ptr += -count;
  507. }
  508. }
  509. tmp += m_hdr.x;
  510. }
  511. }
  512. void CFLICStream::_lcchunk()
  513. {
  514. WORD y;
  515. m_flic.Read(&y, sizeof(y));
  516. BYTE* tmp = &m_pFrameBuffer[y*m_hdr.x];
  517. WORD lines;
  518. m_flic.Read(&lines, sizeof(lines));
  519. while(lines--)
  520. {
  521. BYTE* ptr = tmp;
  522. BYTE packets;
  523. m_flic.Read(&packets, sizeof(packets));
  524. while(packets--)
  525. {
  526. BYTE skip;
  527. m_flic.Read(&skip, sizeof(skip));
  528. ptr += skip;
  529. signed char count;
  530. m_flic.Read(&count, sizeof(count));
  531. if(count >= 0)
  532. {
  533. m_flic.Read(ptr, count);
  534. ptr += count;
  535. }
  536. else
  537. {
  538. BYTE c;
  539. m_flic.Read(&c, sizeof(c));
  540. memset(ptr, c, -count);
  541. ptr += -count;
  542. }
  543. }
  544. tmp += m_hdr.x;
  545. }
  546. }
  547. void CFLICStream::_deltachunk()
  548. {
  549. BYTE* tmp = m_pFrameBuffer;
  550. WORD lines;
  551. m_flic.Read(&lines, sizeof(lines));
  552. while(lines--)
  553. {
  554. signed short packets;
  555. m_flic.Read(&packets, sizeof(packets));
  556. if(packets < 0)
  557. {
  558. if(packets&0x4000)
  559. {
  560. tmp += -packets * m_hdr.x;
  561. lines++;
  562. }
  563. else
  564. {
  565. signed char count;
  566. m_flic.Read(&count, sizeof(count));
  567. tmp[m_hdr.x-1] = (BYTE)packets;
  568. }
  569. }
  570. else
  571. {
  572. BYTE* ptr = tmp;
  573. while(packets--)
  574. {
  575. BYTE skip;
  576. m_flic.Read(&skip, sizeof(skip));
  577. ptr += skip;
  578. signed char count;
  579. m_flic.Read(&count, sizeof(count));
  580. if(count >= 0)
  581. {
  582. m_flic.Read(ptr, count << 1);
  583. ptr += count << 1;
  584. }
  585. else
  586. {
  587. WORD c;
  588. m_flic.Read(&c, sizeof(c));
  589. count = -count;
  590. while(count-- > 0)
  591. {
  592. *ptr++ = c>>8;
  593. *ptr++ = c&0xff;
  594. }
  595. }
  596. }
  597. tmp += m_hdr.x;
  598. }
  599. }
  600. }