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

多媒体编程

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "DSMSplitterFile.h"
  3. #include "......DSUtilDSUtil.h"
  4. #include "........includematroskamatroska.h"
  5. CDSMSplitterFile::CDSMSplitterFile(IAsyncReader* pReader, HRESULT& hr, IDSMResourceBagImpl& res, IDSMChapterBagImpl& chap) 
  6. : CBaseSplitterFile(pReader, hr)
  7. , m_rtFirst(0)
  8. , m_rtDuration(0)
  9. {
  10. if(FAILED(hr)) return;
  11. hr = Init(res, chap);
  12. }
  13. HRESULT CDSMSplitterFile::Init(IDSMResourceBagImpl& res, IDSMChapterBagImpl& chap)
  14. {
  15. Seek(0);
  16. if(BitRead(DSMSW_SIZE<<3) != DSMSW || BitRead(5) != DSMP_FILEINFO)
  17. return E_FAIL;
  18. Seek(0);
  19. m_mts.RemoveAll();
  20. m_rtFirst = m_rtDuration = 0;
  21. m_fim.RemoveAll();
  22. m_sim.RemoveAll();
  23. res.ResRemoveAll();
  24. chap.ChapRemoveAll();
  25. dsmp_t type;
  26. UINT64 len;
  27. int limit = 65536;
  28. // examine the beginning of the file ...
  29. while(Sync(type, len, 0))
  30. {
  31. __int64 pos = GetPos();
  32. if(type == DSMP_MEDIATYPE)
  33. {
  34. BYTE id;
  35. CMediaType mt;
  36. if(Read(len, id, mt)) m_mts[id] = mt;
  37. }
  38. else if(type == DSMP_SAMPLE)
  39. {
  40. Packet p;
  41. if(Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME)
  42. {
  43. m_rtFirst = p.rtStart;
  44. break;
  45. }
  46. }
  47. else if(type == DSMP_FILEINFO) {if((BYTE)BitRead(8) > DSMF_VERSION) return E_FAIL; Read(len-1, m_fim);}
  48. else if(type == DSMP_STREAMINFO) {Read(len-1, m_sim[(BYTE)BitRead(8)]);}
  49. else if(type == DSMP_SYNCPOINTS) {Read(len, m_sps);}
  50. else if(type == DSMP_RESOURCE) {Read(len, res);}
  51. else if(type == DSMP_CHAPTERS) {Read(len, chap);}
  52. Seek(pos + len);
  53. }
  54. if(type != DSMP_SAMPLE)
  55. return E_FAIL;
  56. // ... and the end 
  57. for(int i = 1, j = (int)((GetLength()+limit/2)/limit); i <= j; i++)
  58. {
  59. __int64 seekpos = max(0, (__int64)GetLength()-i*limit);
  60. Seek(seekpos);
  61. while(Sync(type, len, limit) && GetPos() < seekpos+limit)
  62. {
  63. __int64 pos = GetPos();
  64. if(type == DSMP_SAMPLE)
  65. {
  66. Packet p;
  67. if(Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME)
  68. {
  69. m_rtDuration = max(m_rtDuration, p.rtStop - m_rtFirst); // max isn't really needed, only for safety
  70. i = j;
  71. }
  72. }
  73. else if(type == DSMP_FILEINFO) {if((BYTE)BitRead(8) > DSMF_VERSION) return E_FAIL; Read(len-1, m_fim);}
  74. else if(type == DSMP_STREAMINFO) {Read(len-1, m_sim[(BYTE)BitRead(8)]);}
  75. else if(type == DSMP_SYNCPOINTS) {Read(len, m_sps);}
  76. else if(type == DSMP_RESOURCE) {Read(len, res);}
  77. else if(type == DSMP_CHAPTERS) {Read(len, chap);}
  78. Seek(pos + len);
  79. }
  80. }
  81. if(m_rtFirst < 0)
  82. {
  83. m_rtDuration += m_rtFirst;
  84. m_rtFirst = 0;
  85. }
  86. return m_mts.GetCount() > 0 ? S_OK : E_FAIL;
  87. }
  88. bool CDSMSplitterFile::Sync(dsmp_t& type, UINT64& len, __int64 limit)
  89. {
  90. UINT64 pos;
  91. return Sync(pos, type, len, limit);
  92. }
  93. bool CDSMSplitterFile::Sync(UINT64& syncpos, dsmp_t& type, UINT64& len, __int64 limit)
  94. {
  95. BitByteAlign();
  96. limit += DSMSW_SIZE;
  97. for(UINT64 id = 0; (id&((1ui64<<(DSMSW_SIZE<<3))-1)) != DSMSW; id = (id << 8) | (BYTE)BitRead(8))
  98. {
  99. if(limit-- <= 0 || GetPos() >= GetLength()-2)
  100. return(false);
  101. }
  102. syncpos = GetPos() - (DSMSW_SIZE<<3);
  103. type = (dsmp_t)BitRead(5);
  104. len = BitRead(((int)BitRead(3)+1)<<3);
  105. return(true);
  106. }
  107. bool CDSMSplitterFile::Read(__int64 len, BYTE& id, CMediaType& mt)
  108. {
  109. id = (BYTE)BitRead(8);
  110. ByteRead((BYTE*)&mt.majortype, sizeof(mt.majortype));
  111. ByteRead((BYTE*)&mt.subtype, sizeof(mt.subtype));
  112. mt.bFixedSizeSamples = (BOOL)BitRead(1);
  113. mt.bTemporalCompression = (BOOL)BitRead(1);
  114. mt.lSampleSize = (ULONG)BitRead(30);
  115. ByteRead((BYTE*)&mt.formattype, sizeof(mt.formattype));
  116. len -= 5 + sizeof(GUID)*3;
  117. ASSERT(len >= 0);
  118. if(len > 0) {mt.AllocFormatBuffer((LONG)len); ByteRead(mt.Format(), mt.FormatLength());}
  119. else mt.ResetFormatBuffer();
  120. return true;
  121. }
  122. bool CDSMSplitterFile::Read(__int64 len, Packet* p, bool fData)
  123. {
  124. if(!p) return false;
  125. p->TrackNumber = (DWORD)BitRead(8);
  126. p->bSyncPoint = (BOOL)BitRead(1);
  127. bool fSign = !!BitRead(1);
  128. int iTimeStamp = (int)BitRead(3);
  129. int iDuration = (int)BitRead(3);
  130. if(fSign && !iTimeStamp)
  131. {
  132. ASSERT(!iDuration);
  133. p->rtStart = Packet::INVALID_TIME;
  134. p->rtStop = Packet::INVALID_TIME + 1;
  135. }
  136. else
  137. {
  138. p->rtStart = (REFERENCE_TIME)BitRead(iTimeStamp<<3) * (fSign ? -1 : 1);
  139. p->rtStop = p->rtStart + BitRead(iDuration<<3);
  140. }
  141. if(fData)
  142. {
  143.         p->pData.SetSize((INT_PTR)len - (2 + iTimeStamp + iDuration));
  144. ByteRead(p->pData.GetData(), p->pData.GetSize());
  145. }
  146. return true;
  147. }
  148. bool CDSMSplitterFile::Read(__int64 len, CArray<SyncPoint>& sps)
  149. {
  150. SyncPoint sp = {0, 0};
  151. sps.RemoveAll();
  152. while(len > 0)
  153. {
  154. bool fSign = !!BitRead(1);
  155. int iTimeStamp = (int)BitRead(3);
  156. int iFilePos = (int)BitRead(3);
  157. BitRead(1); // reserved
  158. sp.rt += (REFERENCE_TIME)BitRead(iTimeStamp<<3) * (fSign ? -1 : 1);
  159. sp.fp += BitRead(iFilePos<<3);
  160. sps.Add(sp);
  161. len -= 1 + iTimeStamp + iFilePos;
  162. }
  163. if(len != 0)
  164. {
  165. sps.RemoveAll();
  166. return false;
  167. }
  168. // TODO: sort sps
  169. return true;
  170. }
  171. bool CDSMSplitterFile::Read(__int64 len, CStreamInfoMap& im)
  172. {
  173. while(len >= 5)
  174. {
  175. CStringA key;
  176. ByteRead((BYTE*)key.GetBufferSetLength(4), 4);
  177. len -= 4;
  178. len -= Read(len, im[key]);
  179. }
  180. return len == 0;
  181. }
  182. bool CDSMSplitterFile::Read(__int64 len, IDSMResourceBagImpl& res)
  183. {
  184. BYTE compression = (BYTE)BitRead(2);
  185. BYTE reserved = (BYTE)BitRead(6);
  186. len--;
  187. CDSMResource r;
  188. len -= Read(len, r.name);
  189. len -= Read(len, r.desc);
  190. len -= Read(len, r.mime);
  191. if(compression != 0) return false; // TODO
  192. r.data.SetSize(len);
  193. ByteRead(r.data.GetData(), r.data.GetSize());
  194. res += r;
  195. return true;
  196. }
  197. bool CDSMSplitterFile::Read(__int64 len, IDSMChapterBagImpl& chap)
  198. {
  199. CDSMChapter c(0, L"");
  200. while(len > 0)
  201. {
  202. bool fSign = !!BitRead(1);
  203. int iTimeStamp = (int)BitRead(3);
  204. BitRead(4); // reserved
  205. len--;
  206. c.rt += (REFERENCE_TIME)BitRead(iTimeStamp<<3) * (fSign ? -1 : 1);
  207. len -= iTimeStamp;
  208. len -= Read(len, c.name);
  209. chap += c;
  210. }
  211. chap.ChapSort();
  212. return len == 0;
  213. }
  214. __int64 CDSMSplitterFile::Read(__int64 len, CStringW& str)
  215. {
  216. char c;
  217. CStringA s;
  218. __int64 i = 0;
  219. while(i++ < len && (c = (char)BitRead(8)) != 0) s += c;
  220. str = UTF8To16(s);
  221. return i;
  222. }
  223. __int64 CDSMSplitterFile::FindSyncPoint(REFERENCE_TIME rt)
  224. {
  225. if(/*!m_sps.IsEmpty()*/ m_sps.GetCount() > 1)
  226. {
  227. int i = range_bsearch(m_sps, m_rtFirst + rt);
  228. return i >= 0 ? m_sps[i].fp : 0;
  229. }
  230. if(m_rtDuration <= 0 || rt <= m_rtFirst)
  231. return 0;
  232. // ok, do the hard way then
  233. dsmp_t type;
  234. UINT64 syncpos, len;
  235. // 1. find some boundaries close to rt's position (minpos, maxpos)
  236. __int64 minpos = 0, maxpos = GetLength();
  237. for(int i = 0; i < 10 && (maxpos - minpos) >= 1024*1024; i++)
  238. {
  239. Seek((minpos + maxpos) / 2);
  240. while(GetPos() < maxpos)
  241. {
  242. if(!Sync(syncpos, type, len))
  243. continue;
  244. __int64 pos = GetPos();
  245. if(type == DSMP_SAMPLE)
  246. {
  247. Packet p;
  248. if(Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME)
  249. {
  250. REFERENCE_TIME dt = (p.rtStart -= m_rtFirst) - rt;
  251. if(dt >= 0) maxpos = max((__int64)syncpos - 65536, minpos);
  252. else minpos = syncpos;
  253. break;
  254. }
  255. }
  256. Seek(pos + len);
  257. }
  258. }
  259. // 2. find the first packet just after rt (maxpos)
  260. Seek(minpos);
  261. while(GetPos() < GetLength())
  262. {
  263. if(!Sync(syncpos, type, len))
  264. continue;
  265. __int64 pos = GetPos();
  266. if(type == DSMP_SAMPLE)
  267. {
  268. Packet p;
  269. if(Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME)
  270. {
  271. REFERENCE_TIME dt = (p.rtStart -= m_rtFirst) - rt;
  272. if(dt >= 0) {maxpos = (__int64)syncpos; break;}
  273. }
  274. }
  275. Seek(pos + len);
  276. }
  277. // 3. iterate backwards from maxpos and find at least one syncpoint for every stream, except for subtitle streams
  278. CAtlMap<BYTE,BYTE> ids;
  279. {
  280. POSITION pos = m_mts.GetStartPosition();
  281. while(pos)
  282. {
  283. BYTE id;
  284. CMediaType mt;
  285. m_mts.GetNextAssoc(pos, id, mt);
  286. if(mt.majortype != MEDIATYPE_Text && mt.majortype != MEDIATYPE_Subtitle)
  287. ids[id] = 0;
  288. }
  289. }
  290. __int64 ret = maxpos;
  291. while(maxpos > 0 && !ids.IsEmpty())
  292. {
  293. minpos = max(0, maxpos - 65536);
  294. Seek(minpos);
  295. while(Sync(syncpos, type, len) && GetPos() < maxpos)
  296. {
  297. UINT64 pos = GetPos();
  298. if(type == DSMP_SAMPLE)
  299. {
  300. Packet p;
  301. if(Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME && p.bSyncPoint)
  302. {
  303. BYTE id = (BYTE)p.TrackNumber, tmp;
  304. if(ids.Lookup(id, tmp))
  305. {
  306. ids.RemoveKey((BYTE)p.TrackNumber);
  307. ret = min(ret, (__int64)syncpos);
  308. }
  309. }
  310. }
  311. Seek(pos + len);
  312. }
  313. maxpos = minpos;
  314. }
  315. return ret;
  316. }