MatroskaFile.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:27k
- /*
- * Copyright (C) 2003-2005 Gabest
- * http://www.gabest.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
- #include "stdafx.h"
- #include "MatroskaFile.h"
- #include "......DSUtilDSUtil.h"
- #include "......zlibzlib.h"
- #define DOCTYPE _T("matroska")
- #define DOCTYPEVERSION 2
- static void LOG(LPCTSTR fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- if(FILE* f = _tfopen(_T("c:\matroskasplitterlog.txt"), _T("at")))
- {
- fseek(f, 0, 2);
- _vftprintf(f, fmt, args);
- fclose(f);
- }
- va_end(args);
- }
- using namespace MatroskaReader;
- #define BeginChunk
- CheckPointer(pMN0, E_POINTER);
- CAutoPtr<CMatroskaNode> pMN = pMN0->Child();
- if(!pMN) return S_FALSE;
- do
- {
- switch(pMN->m_id)
- {
- #define EndChunk
- }
- }
- while(pMN->Next());
- return S_OK;
- static void bswap(BYTE* s, int len)
- {
- for(BYTE* d = s + len-1; s < d; s++, d--)
- *s ^= *d, *d ^= *s, *s ^= *d;
- }
- //
- // CMatroskaFile
- //
- CMatroskaFile::CMatroskaFile(IAsyncReader* pAsyncReader, HRESULT& hr)
- : CBaseSplitterFile(pAsyncReader, hr)
- , m_rtOffset(0)
- {
- if(FAILED(hr)) return;
- hr = Init();
- }
- HRESULT CMatroskaFile::Init()
- {
- DWORD dw;
- if(FAILED(Read(dw)) || dw != 0x1A45DFA3)
- return E_FAIL;
- CMatroskaNode Root(this);
- if(FAILED(Parse(&Root)))
- return E_FAIL;
- CAutoPtr<CMatroskaNode> pSegment, pCluster;
- if((pSegment = Root.Child(0x18538067))
- && (pCluster = pSegment->Child(0x1F43B675)))
- {
- Cluster c0;
- c0.ParseTimeCode(pCluster);
- m_rtOffset = m_segment.GetRefTime(c0.TimeCode);
- }
- return S_OK;
- }
- template <class T>
- HRESULT CMatroskaFile::Read(T& var)
- {
- HRESULT hr = Read((BYTE*)&var, sizeof(var));
- if(S_OK == hr) bswap((BYTE*)&var, sizeof(var));
- return hr;
- }
- HRESULT CMatroskaFile::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x1A45DFA3:
- m_ebml.Parse(pMN);
- if(m_ebml.DocType != DOCTYPE || m_ebml.DocTypeReadVersion > DOCTYPEVERSION)
- return E_FAIL;
- break;
- case 0x18538067: if(m_segment.SegmentInfo.SegmentUID.IsEmpty()) m_segment.ParseMinimal(pMN); break;
- EndChunk
- }
- //
- HRESULT EBML::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x4286: EBMLVersion.Parse(pMN); break;
- case 0x42F7: EBMLReadVersion.Parse(pMN); break;
- case 0x42F2: EBMLMaxIDLength.Parse(pMN); break;
- case 0x42F3: EBMLMaxSizeLength.Parse(pMN); break;
- case 0x4282: DocType.Parse(pMN); break;
- case 0x4287: DocTypeVersion.Parse(pMN); break;
- case 0x4285: DocTypeReadVersion.Parse(pMN); break;
- EndChunk
- }
- HRESULT Segment::Parse(CMatroskaNode* pMN0)
- {
- pos = pMN0->GetPos();
- BeginChunk
- case 0x1549A966: SegmentInfo.Parse(pMN); break;
- case 0x114D9B74: MetaSeekInfo.Parse(pMN); break;
- case 0x1654AE6B: Tracks.Parse(pMN); break;
- case 0x1F43B675: Clusters.Parse(pMN); break;
- case 0x1C53BB6B: Cues.Parse(pMN); break;
- case 0x1941A469: Attachments.Parse(pMN); break;
- case 0x1043A770: Chapters.Parse(pMN); break;
- // case 0x1254C367: Tags.Parse(pMN); break;
- EndChunk
- }
- HRESULT Segment::ParseMinimal(CMatroskaNode* pMN0)
- {
- CheckPointer(pMN0, E_POINTER);
- pos = pMN0->GetPos();
- len = pMN0->m_len;
- CAutoPtr<CMatroskaNode> pMN = pMN0->Child();
- if(!pMN) return S_FALSE;
- int n = 0;
- do
- {
- switch(pMN->m_id)
- {
- case 0x1549A966: SegmentInfo.Parse(pMN); n++; break;
- case 0x114D9B74: MetaSeekInfo.Parse(pMN); n++; break;
- case 0x1654AE6B: Tracks.Parse(pMN); n++; break;
- case 0x1C53BB6B: Cues.Parse(pMN); break;
- }
- }
- while(n < 3 && pMN->Next());
- while(QWORD pos = pMN->FindPos(0x114D9B74, pMN->GetPos()))
- {
- pMN->SeekTo(pos);
- pMN->Parse();
- if(pMN->m_id != 0x114D9B74) {ASSERT(0); break;}
- MetaSeekInfo.Parse(pMN);
- }
- if(n == 3)
- {
- if(Cues.IsEmpty() && (pMN = pMN0->Child(0x1C53BB6B, false)))
- {
- do {Cues.Parse(pMN);} while(pMN->Next(true));
- }
- if(Chapters.IsEmpty() && (pMN = pMN0->Child(0x1043A770, false)))
- {
- do {Chapters.Parse(pMN); /*BIG UGLY HACK:*/ break;} while(pMN->Next(true));
- }
- if(Attachments.IsEmpty() && (pMN = pMN0->Child(0x1941A469, false)))
- {
- do {Attachments.Parse(pMN); /*BIG UGLY HACK:*/ break;} while (pMN->Next(true));
- }
- }
- return S_OK;
- }
- UINT64 Segment::GetMasterTrack()
- {
- UINT64 TrackNumber = 0, AltTrackNumber = 0;
- POSITION pos1 = Tracks.GetHeadPosition();
- while(pos1 && TrackNumber == 0)
- {
- Track* pT = Tracks.GetNext(pos1);
-
- POSITION pos2 = pT->TrackEntries.GetHeadPosition();
- while(pos2 && TrackNumber == 0)
- {
- TrackEntry* pTE = pT->TrackEntries.GetNext(pos2);
- if(pTE->TrackType == TrackEntry::TypeVideo)
- {
- TrackNumber = pTE->TrackNumber;
- break;
- }
- else if(pTE->TrackType == TrackEntry::TypeAudio && AltTrackNumber == 0)
- {
- AltTrackNumber = pTE->TrackNumber;
- }
- }
- }
- if(TrackNumber == 0) TrackNumber = AltTrackNumber;
- if(TrackNumber == 0) TrackNumber = 1;
- return TrackNumber;
- }
- ChapterAtom* ChapterAtom::FindChapterAtom(UINT64 id)
- {
- if(ChapterUID == id)
- return(this);
- POSITION pos = ChapterAtoms.GetHeadPosition();
- while(pos)
- {
- ChapterAtom* ca = ChapterAtoms.GetNext(pos)->FindChapterAtom(id);
- if(ca) return ca;
- }
- return(NULL);
- }
- ChapterAtom* Segment::FindChapterAtom(UINT64 id, int nEditionEntry)
- {
- POSITION pos1 = Chapters.GetHeadPosition();
- while(pos1)
- {
- Chapter* c = Chapters.GetNext(pos1);
- POSITION pos2 = c->EditionEntries.GetHeadPosition();
- while(pos2)
- {
- EditionEntry* ee = c->EditionEntries.GetNext(pos2);
- if(nEditionEntry-- == 0)
- {
- return id == 0 ? ee : ee->FindChapterAtom(id);
- }
- }
- }
- return(NULL);
- }
- HRESULT Info::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x73A4: SegmentUID.Parse(pMN); break;
- case 0x7384: SegmentFilename.Parse(pMN); break;
- case 0x3CB923: PrevUID.Parse(pMN); break;
- case 0x3C83AB: PrevFilename.Parse(pMN); break;
- case 0x3EB923: NextUID.Parse(pMN); break;
- case 0x3E83BB: NextFilename.Parse(pMN); break;
- case 0x2AD7B1: TimeCodeScale.Parse(pMN); break;
- case 0x4489: Duration.Parse(pMN); break;
- case 0x4461: DateUTC.Parse(pMN); break;
- case 0x7BA9: Title.Parse(pMN); break;
- case 0x4D80: MuxingApp.Parse(pMN); break;
- case 0x5741: WritingApp.Parse(pMN); break;
- EndChunk
- }
- HRESULT Seek::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x4DBB: SeekHeads.Parse(pMN); break;
- EndChunk
- }
- HRESULT SeekHead::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x53AB: SeekID.Parse(pMN); break;
- case 0x53AC: SeekPosition.Parse(pMN); break;
- EndChunk
- }
- HRESULT Track::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xAE: TrackEntries.Parse(pMN); break;
- EndChunk
- }
- HRESULT TrackEntry::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xD7: TrackNumber.Parse(pMN); break;
- case 0x73C5: TrackUID.Parse(pMN); break;
- case 0x83: TrackType.Parse(pMN); break;
- case 0xB9: FlagEnabled.Parse(pMN); break;
- case 0x88: FlagDefault.Parse(pMN); break;
- case 0x9C: FlagLacing.Parse(pMN); break;
- case 0x6DE7: MinCache.Parse(pMN); break;
- case 0x6DF8: MaxCache.Parse(pMN); break;
- case 0x536E: Name.Parse(pMN); break;
- case 0x22B59C: Language.Parse(pMN); break;
- case 0x86: CodecID.Parse(pMN); break;
- case 0x63A2: CodecPrivate.Parse(pMN); break;
- case 0x258688: CodecName.Parse(pMN); break;
- case 0x3A9697: CodecSettings.Parse(pMN); break;
- case 0x3B4040: CodecInfoURL.Parse(pMN); break;
- case 0x26B240: CodecDownloadURL.Parse(pMN); break;
- case 0xAA: CodecDecodeAll.Parse(pMN); break;
- case 0x6FAB: TrackOverlay.Parse(pMN); break;
- case 0x23E383: case 0x2383E3: DefaultDuration.Parse(pMN); break;
- case 0x23314F: TrackTimecodeScale.Parse(pMN); break;
- case 0xE0: if(S_OK == v.Parse(pMN)) DescType |= DescVideo; break;
- case 0xE1: if(S_OK == a.Parse(pMN)) DescType |= DescAudio; break;
- case 0x6D80: ces.Parse(pMN); break;
- EndChunk
- }
- static int cesort(const void* a, const void* b)
- {
- UINT64 ce1 = ((ContentEncoding*)a)->ContentEncodingOrder;
- UINT64 ce2 = ((ContentEncoding*)b)->ContentEncodingOrder;
- return (int)ce1 - (int)ce2;
- }
- bool TrackEntry::Expand(CBinary& data, UINT64 Scope)
- {
- if(ces.ce.GetCount() == 0) return(true);
- CArray<ContentEncoding*> cearray;
- POSITION pos = ces.ce.GetHeadPosition();
- while(pos) cearray.Add(ces.ce.GetNext(pos));
- qsort(cearray.GetData(), cearray.GetCount(), sizeof(ContentEncoding*), cesort);
- for(int i = cearray.GetCount()-1; i >= 0; i--)
- {
- ContentEncoding* ce = cearray[i];
- if(!(ce->ContentEncodingScope & Scope))
- continue;
- if(ce->ContentEncodingType == ContentEncoding::Compression)
- {
- if(!data.Decompress(ce->cc))
- return(false);
- }
- else if(ce->ContentEncodingType == ContentEncoding::Encryption)
- {
- // TODO
- return(false);
- }
- }
- return(true);
- }
- HRESULT Video::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x9A: FlagInterlaced.Parse(pMN); break;
- case 0x53B8: StereoMode.Parse(pMN); break;
- case 0xB0: PixelWidth.Parse(pMN); break;
- case 0xBA: PixelHeight.Parse(pMN); break;
- case 0x54B0: DisplayWidth.Parse(pMN); break;
- case 0x54BA: DisplayHeight.Parse(pMN); break;
- case 0x54B2: DisplayUnit.Parse(pMN); break;
- case 0x54B3: AspectRatioType.Parse(pMN); break;
- case 0x2EB524: ColourSpace.Parse(pMN); break;
- case 0x2FB523: GammaValue.Parse(pMN); break;
- case 0x2383E3: FramePerSec.Parse(pMN); break;
- EndChunk
- }
- HRESULT Audio::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xB5: SamplingFrequency.Parse(pMN); break;
- case 0x78B5: OutputSamplingFrequency.Parse(pMN); break;
- case 0x9F: Channels.Parse(pMN); break;
- case 0x7D7B: ChannelPositions.Parse(pMN); break;
- case 0x6264: BitDepth.Parse(pMN); break;
- EndChunk
- }
- HRESULT ContentEncodings::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x6240: ce.Parse(pMN); break;
- EndChunk
- }
- HRESULT ContentEncoding::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x5031: ContentEncodingOrder.Parse(pMN); break;
- case 0x5032: ContentEncodingScope.Parse(pMN); break;
- case 0x5033: ContentEncodingType.Parse(pMN); break;
- case 0x5034: cc.Parse(pMN); break;
- case 0x5035: ce.Parse(pMN); break;
- EndChunk
- }
- HRESULT ContentCompression::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x4254: ContentCompAlgo.Parse(pMN); break;
- case 0x4255: ContentCompSettings.Parse(pMN); break;
- EndChunk
- }
- HRESULT ContentEncryption::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x47e1: ContentEncAlgo.Parse(pMN); break;
- case 0x47e2: ContentEncKeyID.Parse(pMN); break;
- case 0x47e3: ContentSignature.Parse(pMN); break;
- case 0x47e4: ContentSigKeyID.Parse(pMN); break;
- case 0x47e5: ContentSigAlgo.Parse(pMN); break;
- case 0x47e6: ContentSigHashAlgo.Parse(pMN); break;
- EndChunk
- }
- HRESULT Cluster::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xE7: TimeCode.Parse(pMN); break;
- case 0xA7: Position.Parse(pMN); break;
- case 0xAB: PrevSize.Parse(pMN); break;
- case 0xA0: BlockGroups.Parse(pMN, true); break;
- case 0xA3: SimpleBlocks.Parse(pMN, true); break;
- EndChunk
- }
- HRESULT Cluster::ParseTimeCode(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xE7: TimeCode.Parse(pMN); return S_OK;
- EndChunk
- }
- HRESULT BlockGroup::Parse(CMatroskaNode* pMN0, bool fFull)
- {
- BeginChunk
- case 0xA1: Block.Parse(pMN, fFull); break;
- case 0xA2: /* TODO: multiple virt blocks? */; break;
- case 0x9B: BlockDuration.Parse(pMN); break;
- case 0xFA: ReferencePriority.Parse(pMN); break;
- case 0xFB: ReferenceBlock.Parse(pMN); break;
- case 0xFD: ReferenceVirtual.Parse(pMN); break;
- case 0xA4: CodecState.Parse(pMN); break;
- case 0xE8: TimeSlices.Parse(pMN); break;
- EndChunk
- }
- HRESULT SimpleBlock::Parse(CMatroskaNode* pMN, bool fFull)
- {
- pMN->SeekTo(pMN->m_start);
- TrackNumber.Parse(pMN);
- CShort s; s.Parse(pMN); TimeCode.Set(s);
- Lacing.Parse(pMN);
-
- if(!fFull) return S_OK;
- CList<QWORD> lens;
- QWORD tlen = 0;
- QWORD FrameSize;
- BYTE FramesInLaceLessOne;
- switch((Lacing & 0x06) >> 1)
- {
- case 0:
- // No lacing
- lens.AddTail((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen));
- break;
- case 1:
- // Xiph lacing
- BYTE n;
- pMN->Read(n);
- while(n-- > 0)
- {
- BYTE b;
- QWORD len = 0;
- do {pMN->Read(b); len += b;} while(b == 0xff);
- lens.AddTail(len);
- tlen += len;
- }
- lens.AddTail((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen));
- break;
- case 2:
- // Fixed-size lacing
- pMN->Read(FramesInLaceLessOne);
- FramesInLaceLessOne++;
- FrameSize = ((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen)) / FramesInLaceLessOne;
- while(FramesInLaceLessOne-- > 0)
- lens.AddTail(FrameSize);
- break;
- case 3:
- // EBML lacing
- pMN->Read(FramesInLaceLessOne);
- CLength FirstFrameSize;
- FirstFrameSize.Parse(pMN);
- lens.AddTail(FirstFrameSize);
- FramesInLaceLessOne--;
- tlen = FirstFrameSize;
- CSignedLength DiffSize;
- FrameSize = FirstFrameSize;
- while(FramesInLaceLessOne--)
- {
- DiffSize.Parse(pMN);
- FrameSize += DiffSize;
- lens.AddTail(FrameSize);
- tlen += FrameSize;
- }
- lens.AddTail((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen));
- break;
- }
- POSITION pos = lens.GetHeadPosition();
- while(pos)
- {
- QWORD len = lens.GetNext(pos);
- CAutoPtr<CBinary> p(new CBinary());
- p->SetSize((INT_PTR)len);
- pMN->Read(p->GetData(), len);
- BlockData.AddTail(p);
- }
- return S_OK;
- }
- HRESULT TimeSlice::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xCC: LaceNumber.Parse(pMN); break;
- case 0xCD: FrameNumber.Parse(pMN); break;
- case 0xCE: Delay.Parse(pMN); break;
- case 0xCF: Duration.Parse(pMN); break;
- EndChunk
- }
- HRESULT Cue::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xBB: CuePoints.Parse(pMN); break;
- EndChunk
- }
- HRESULT CuePoint::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xB3: CueTime.Parse(pMN); break;
- case 0xB7: CueTrackPositions.Parse(pMN); break;
- EndChunk
- }
- HRESULT CueTrackPosition::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xF7: CueTrack.Parse(pMN); break;
- case 0xF1: CueClusterPosition.Parse(pMN); break;
- case 0x5387: CueBlockNumber.Parse(pMN); break;
- case 0xEA: CueCodecState.Parse(pMN); break;
- case 0xDB: CueReferences.Parse(pMN); break;
- EndChunk
- }
- HRESULT CueReference::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x96: CueRefTime.Parse(pMN); break;
- case 0x97: CueRefCluster.Parse(pMN); break;
- case 0x535F: CueRefNumber.Parse(pMN); break;
- case 0xEB: CueRefCodecState.Parse(pMN); break;
- EndChunk
- }
- HRESULT Attachment::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x61A7: AttachedFiles.Parse(pMN); break;
- EndChunk
- }
- HRESULT AttachedFile::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x467E: FileDescription.Parse(pMN); break;
- case 0x466E: FileName.Parse(pMN); break;
- case 0x4660: FileMimeType.Parse(pMN); break;
- case 0x465C: // binary
- FileDataLen = (INT_PTR)pMN->m_len;
- FileDataPos = pMN->m_start;
- break;
- case 0x46AE: FileUID.Parse(pMN); break;
- EndChunk
- }
- HRESULT Chapter::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x45B9: EditionEntries.Parse(pMN); break;
- EndChunk
- }
- HRESULT EditionEntry::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0xB6: ChapterAtoms.Parse(pMN); break;
- EndChunk
- }
- HRESULT ChapterAtom::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x73C4: ChapterUID.Parse(pMN); break;
- case 0x91: ChapterTimeStart.Parse(pMN); break;
- case 0x92: ChapterTimeEnd.Parse(pMN); break;
- // case 0x8F: // TODO
- case 0x80: ChapterDisplays.Parse(pMN); break;
- case 0xB6: ChapterAtoms.Parse(pMN); break;
- case 0x98: ChapterFlagHidden.Parse(pMN); break;
- case 0x4598: ChapterFlagEnabled.Parse(pMN); break;
- EndChunk
- }
- HRESULT ChapterDisplay::Parse(CMatroskaNode* pMN0)
- {
- BeginChunk
- case 0x85: ChapString.Parse(pMN); break;
- case 0x437C: ChapLanguage.Parse(pMN); break;
- case 0x437E: ChapCountry.Parse(pMN); break;
- EndChunk
- }
- //
- HRESULT CBinary::Parse(CMatroskaNode* pMN)
- {
- ASSERT(pMN->m_len <= INT_MAX);
- SetSize((INT_PTR)pMN->m_len);
- return pMN->Read(GetData(), pMN->m_len);
- }
- bool CBinary::Compress(ContentCompression& cc)
- {
- if(cc.ContentCompAlgo == ContentCompression::ZLIB)
- {
- int res;
- z_stream c_stream;
- c_stream.zalloc = (alloc_func)0;
- c_stream.zfree = (free_func)0;
- c_stream.opaque = (voidpf)0;
- if(Z_OK != (res = deflateInit(&c_stream, 9)))
- return(false);
- c_stream.next_in = GetData();
- c_stream.avail_in = GetSize();
- BYTE* dst = NULL;
- int n = 0;
- do
- {
- dst = (BYTE*)realloc(dst, ++n*10);
- c_stream.next_out = &dst[(n-1)*10];
- c_stream.avail_out = 10;
- if(Z_OK != (res = deflate(&c_stream, Z_FINISH)) && Z_STREAM_END != res)
- {
- free(dst);
- return(false);
- }
- }
- while(0 == c_stream.avail_out && Z_STREAM_END != res);
- deflateEnd(&c_stream);
- SetSize(c_stream.total_out);
- memcpy(GetData(), dst, GetSize());
- free(dst);
- return(true);
- }
- return(false);
- }
- bool CBinary::Decompress(ContentCompression& cc)
- {
- if(cc.ContentCompAlgo == ContentCompression::ZLIB)
- {
- int res;
- z_stream d_stream;
- d_stream.zalloc = (alloc_func)0;
- d_stream.zfree = (free_func)0;
- d_stream.opaque = (voidpf)0;
- if(Z_OK != (res = inflateInit(&d_stream)))
- return(false);
- d_stream.next_in = GetData();
- d_stream.avail_in = GetSize();
- BYTE* dst = NULL;
- int n = 0;
- do
- {
- dst = (unsigned char *)realloc(dst, ++n*1000);
- d_stream.next_out = &dst[(n-1)*1000];
- d_stream.avail_out = 1000;
- if(Z_OK != (res = inflate(&d_stream, Z_NO_FLUSH)) && Z_STREAM_END != res)
- {
- free(dst);
- return(false);
- }
- }
- while(0 == d_stream.avail_out && 0 != d_stream.avail_in && Z_STREAM_END != res);
- inflateEnd(&d_stream);
- SetSize(d_stream.total_out);
- memcpy(GetData(), dst, GetSize());
- free(dst);
- return(true);
- }
- else if(cc.ContentCompAlgo == ContentCompression::HDRSTRIP)
- {
- InsertAt(0, &cc.ContentCompSettings);
- }
- return(false);
- }
- HRESULT CANSI::Parse(CMatroskaNode* pMN)
- {
- Empty();
- QWORD len = pMN->m_len;
- CHAR c;
- while(len-- > 0 && SUCCEEDED(pMN->Read(c)))
- *this += c;
- return(len == -1 ? S_OK : E_FAIL);
- }
- HRESULT CUTF8::Parse(CMatroskaNode* pMN)
- {
- Empty();
- CAutoVectorPtr<BYTE> buff;
- if(!buff.Allocate((UINT)pMN->m_len + 1) || S_OK != pMN->Read(buff, pMN->m_len))
- return E_FAIL;
- buff[pMN->m_len] = 0;
- CStringW::operator = (UTF8To16((LPCSTR)(BYTE*)buff));
- return S_OK;
- }
- HRESULT CUInt::Parse(CMatroskaNode* pMN)
- {
- m_val = 0;
- for(int i = 0; i < (int)pMN->m_len; i++)
- {
- m_val <<= 8;
- HRESULT hr = pMN->Read(*(BYTE*)&m_val);
- if(FAILED(hr)) return hr;
- }
- m_fValid = true;
- return S_OK;
- }
- HRESULT CInt::Parse(CMatroskaNode* pMN)
- {
- m_val = 0;
- for(int i = 0; i < (int)pMN->m_len; i++)
- {
- HRESULT hr = pMN->Read(*((BYTE*)&m_val+7-i));
- if(FAILED(hr)) return hr;
- }
- m_val >>= (8-pMN->m_len)*8;
- m_fValid = true;
- return S_OK;
- }
- HRESULT CFloat::Parse(CMatroskaNode* pMN)
- {
- HRESULT hr = E_FAIL;
- m_val = 0;
- if(pMN->m_len == 4)
- {
- float val = 0;
- hr = pMN->Read(val);
- m_val = val;
- } else if(pMN->m_len == 8) {
- hr = pMN->Read(m_val);
- }
- if(SUCCEEDED(hr))
- m_fValid = true;
- return hr;
- }
- template<class T, class BASE>
- HRESULT CSimpleVar<T, BASE>::Parse(CMatroskaNode* pMN)
- {
- m_val = 0;
- m_fValid = true;
- return pMN->Read(m_val);
- }
- HRESULT CID::Parse(CMatroskaNode* pMN)
- {
- m_val = 0;
- BYTE b = 0;
- HRESULT hr = pMN->Read(b);
- if(FAILED(hr)) return hr;
- int nMoreBytes = 0;
- if((b&0x80) == 0x80) {m_val = b&0xff; nMoreBytes = 0;}
- else if((b&0xc0) == 0x40) {m_val = b&0x7f; nMoreBytes = 1;}
- else if((b&0xe0) == 0x20) {m_val = b&0x3f; nMoreBytes = 2;}
- else if((b&0xf0) == 0x10) {m_val = b&0x1f; nMoreBytes = 3;}
- else return E_FAIL;
- while(nMoreBytes-- > 0)
- {
- m_val <<= 8;
- hr = pMN->Read(*(BYTE*)&m_val);
- if(FAILED(hr)) return hr;
- }
- m_fValid = true;
- return S_OK;
- }
- HRESULT CLength::Parse(CMatroskaNode* pMN)
- {
- m_val = 0;
- BYTE b = 0;
- HRESULT hr = pMN->Read(b);
- if(FAILED(hr)) return hr;
- int nMoreBytes = 0, nMoreBytesTmp = 0;
- if((b&0x80) == 0x80) {m_val = b&0x7f; nMoreBytes = 0;}
- else if((b&0xc0) == 0x40) {m_val = b&0x3f; nMoreBytes = 1;}
- else if((b&0xe0) == 0x20) {m_val = b&0x1f; nMoreBytes = 2;}
- else if((b&0xf0) == 0x10) {m_val = b&0x0f; nMoreBytes = 3;}
- else if((b&0xf8) == 0x08) {m_val = b&0x07; nMoreBytes = 4;}
- else if((b&0xfc) == 0x04) {m_val = b&0x03; nMoreBytes = 5;}
- else if((b&0xfe) == 0x02) {m_val = b&0x01; nMoreBytes = 6;}
- else if((b&0xff) == 0x01) {m_val = b&0x00; nMoreBytes = 7;}
- else return E_FAIL;
- nMoreBytesTmp = nMoreBytes;
- QWORD UnknownSize = (1i64<<(7*(nMoreBytes+1)))-1;
- while(nMoreBytes-- > 0)
- {
- m_val <<= 8;
- hr = pMN->Read(*(BYTE*)&m_val);
- if(FAILED(hr)) return hr;
- }
- if(m_val == UnknownSize)
- {
- m_val = pMN->GetLength() - pMN->GetPos();
- TRACE(_T("CLength: Unspecified chunk size at %I64d (corrected to %I64d)n"), pMN->GetPos(), m_val);
- }
- if(m_fSigned)
- m_val -= (UnknownSize >> 1);
- m_fValid = true;
- return S_OK;
- }
- /*
- HRESULT CSignedLength::Parse(CMatroskaNode* pMN)
- {
- // HRESULT hr = __super::Parse(pMN);
- // if(FAILED(hr)) return hr;
- m_val = 0;
- BYTE b = 0;
- HRESULT hr = pMN->Read(b);
- if(FAILED(hr)) return hr;
- int nMoreBytes = 0, nMoreBytesTmp = 0;
- if((b&0x80) == 0x80) {m_val = b&0x7f; nMoreBytes = 0;}
- else if((b&0xc0) == 0x40) {m_val = b&0x3f; nMoreBytes = 1;}
- else if((b&0xe0) == 0x20) {m_val = b&0x1f; nMoreBytes = 2;}
- else if((b&0xf0) == 0x10) {m_val = b&0x0f; nMoreBytes = 3;}
- else if((b&0xf8) == 0x08) {m_val = b&0x07; nMoreBytes = 4;}
- else if((b&0xfc) == 0x04) {m_val = b&0x03; nMoreBytes = 5;}
- else if((b&0xfe) == 0x02) {m_val = b&0x01; nMoreBytes = 6;}
- else if((b&0xff) == 0x01) {m_val = b&0x00; nMoreBytes = 7;}
- else return E_FAIL;
- nMoreBytesTmp = nMoreBytes;
- QWORD UnknownSize = (1i64<<(7*(nMoreBytes+1)))-1;
- while(nMoreBytes-- > 0)
- {
- m_val <<= 8;
- hr = pMN->Read(*(BYTE*)&m_val);
- if(FAILED(hr)) return hr;
- }
- if(m_val == UnknownSize)
- {
- m_val = pMN->GetLength() - pMN->GetPos();
- TRACE(_T("CLength: Unspecified chunk size at %I64d (corrected to %I64d)n"), pMN->GetPos(), m_val);
- }
- m_val -= (UnknownSize >> 1);
- m_fValid = true;
- return S_OK;
- }
- */
- template<class T>
- HRESULT CNode<T>::Parse(CMatroskaNode* pMN)
- {
- CAutoPtr<T> p(new T());
- HRESULT hr = E_OUTOFMEMORY;
- if(!p || FAILED(hr = p->Parse(pMN))) return hr;
- AddTail(p);
- return S_OK;
- }
- HRESULT CBlockGroupNode::Parse(CMatroskaNode* pMN, bool fFull)
- {
- CAutoPtr<BlockGroup> p(new BlockGroup());
- HRESULT hr = E_OUTOFMEMORY;
- if(!p || FAILED(hr = p->Parse(pMN, fFull))) return hr;
- AddTail(p);
- return S_OK;
- }
- HRESULT CSimpleBlockNode::Parse(CMatroskaNode* pMN, bool fFull)
- {
- CAutoPtr<SimpleBlock> p(new SimpleBlock());
- HRESULT hr = E_OUTOFMEMORY;
- if(!p || FAILED(hr = p->Parse(pMN, fFull))) return hr;
- AddTail(p);
- return S_OK;
- }
- ///////////////////////////////
- CMatroskaNode::CMatroskaNode(CMatroskaFile* pMF)
- : m_pMF(pMF)
- , m_pParent(NULL)
- {
- ASSERT(m_pMF);
- m_start = m_filepos = 0;
- m_len.Set(m_pMF ? m_pMF->GetLength() : 0);
- }
- CMatroskaNode::CMatroskaNode(CMatroskaNode* pParent)
- : m_pMF(pParent->m_pMF)
- , m_pParent(pParent)
- {
- Parse();
- }
- HRESULT CMatroskaNode::Parse()
- {
- m_filepos = GetPos();
- if(FAILED(m_id.Parse(this)) || FAILED(m_len.Parse(this)))
- return E_FAIL;
- m_start = GetPos();
- return S_OK;
- }
- CAutoPtr<CMatroskaNode> CMatroskaNode::Child(DWORD id, bool fSearch)
- {
- if(m_len == 0) return CAutoPtr<CMatroskaNode>();
- SeekTo(m_start);
- CAutoPtr<CMatroskaNode> pMN(new CMatroskaNode(this));
- if(id && !pMN->Find(id, fSearch)) pMN.Free();
- return pMN;
- }
- bool CMatroskaNode::Next(bool fSame)
- {
- if(!m_pParent)
- return(false);
- CID id = m_id;
- while(m_start+m_len < m_pParent->m_start+m_pParent->m_len)
- {
- SeekTo(m_start+m_len);
- if(FAILED(Parse()))
- {
- if(!Resync())
- return(false);
- }
- if(!fSame || m_id == id)
- return(true);
- }
- return(false);
- }
- bool CMatroskaNode::Find(DWORD id, bool fSearch)
- {
- QWORD pos = m_pParent && m_pParent->m_id == 0x18538067 /*segment?*/
- ? FindPos(id)
- : 0;
- if(pos)
- {
- SeekTo(pos);
- Parse();
- }
- else if(fSearch)
- {
- while(m_id != id && Next());
- }
- return(m_id == id);
- }
- void CMatroskaNode::SeekTo(QWORD pos) {m_pMF->Seek(pos);}
- QWORD CMatroskaNode::GetPos() {return m_pMF->GetPos();}
- QWORD CMatroskaNode::GetLength() {return m_pMF->GetLength();}
- template <class T>
- HRESULT CMatroskaNode::Read(T& var) {return m_pMF->Read(var);}
- HRESULT CMatroskaNode::Read(BYTE* pData, QWORD len) {return m_pMF->Read(pData, len);}
- QWORD CMatroskaNode::FindPos(DWORD id, QWORD start)
- {
- Segment& sm = m_pMF->m_segment;
- POSITION pos = sm.MetaSeekInfo.GetHeadPosition();
- while(pos)
- {
- Seek* s = sm.MetaSeekInfo.GetNext(pos);
- POSITION pos2 = s->SeekHeads.GetHeadPosition();
- while(pos2)
- {
- SeekHead* sh = s->SeekHeads.GetNext(pos2);
- if(sh->SeekID == id && sh->SeekPosition+sm.pos >= start)
- return sh->SeekPosition+sm.pos;
- }
- }
- return 0;
- }
- CAutoPtr<CMatroskaNode> CMatroskaNode::Copy()
- {
- CAutoPtr<CMatroskaNode> pNewNode(new CMatroskaNode(m_pMF));
- pNewNode->m_pParent = m_pParent;
- pNewNode->m_id.Set(m_id);
- pNewNode->m_len.Set(m_len);
- pNewNode->m_filepos = m_filepos;
- pNewNode->m_start = m_start;
- return(pNewNode);
- }
- CAutoPtr<CMatroskaNode> CMatroskaNode::GetFirstBlock()
- {
- CAutoPtr<CMatroskaNode> pNode = Child();
- do {if(pNode->m_id == 0xA0 || pNode->m_id == 0xA3) return pNode;}
- while(pNode->Next());
- return CAutoPtr<CMatroskaNode>();
- }
- bool CMatroskaNode::NextBlock()
- {
- if(!m_pParent)
- return(false);
- CID id = m_id;
- while(m_start+m_len < m_pParent->m_start+m_pParent->m_len)
- {
- SeekTo(m_start+m_len);
- if(FAILED(Parse()))
- {
- if(!Resync())
- return(false);
- }
- if(m_id == 0xA0 || m_id == 0xA3)
- return(true);
- }
- return(false);
- }
- bool CMatroskaNode::Resync()
- {
- if(m_pParent->m_id == 0x18538067) /*segment?*/
- {
- SeekTo(m_filepos);
- for(BYTE b = 0; S_OK == Read(b); b = 0)
- {
- if((b&0xf0) != 0x10)
- continue;
- DWORD dw = b;
- Read((BYTE*)&dw+1, 3);
- bswap((BYTE*)&dw, 4);
- switch(dw)
- {
- case 0x1549A966: // SegmentInfo
- case 0x114D9B74: // MetaSeekInfo
- case 0x1654AE6B: // Tracks
- case 0x1F43B675: // Clusters
- case 0x1C53BB6B: // Cues
- case 0x1941A469: // Attachments
- case 0x1043A770: // Chapters
- case 0x1254C367: // Tags
- SeekTo(GetPos()-4);
- return(SUCCEEDED(Parse()));
- default:
- SeekTo(GetPos()-3);
- break;
- }
- }
- }
- return(false);
- }