/* * (C) 2003-2006 Gabest * (C) 2006-2013 see Authors.txt * * This file is part of MPC-HC. * * MPC-HC 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 3 of the License, or * (at your option) any later version. * * MPC-HC 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 this program. If not, see . * */ #include "stdafx.h" #include "BaseSplitterFileEx.h" #include #include "../../../DSUtil/DSUtil.h" #include "../../../DSUtil/GolombBuffer.h" #include "../../../DSUtil/AudioParser.h" #include #include "moreuuids.h" // // CBaseSplitterFileEx // CBaseSplitterFileEx::CBaseSplitterFileEx(IAsyncReader* pReader, HRESULT& hr, int cachelen, bool fRandomAccess, bool fStreaming) : CBaseSplitterFile(pReader, hr, cachelen, fRandomAccess, fStreaming) , m_tslen(0) , m_rtPTSOffset(0) { } CBaseSplitterFileEx::~CBaseSplitterFileEx() { } // bool CBaseSplitterFileEx::NextMpegStartCode(BYTE& code, __int64 len) { BitByteAlign(); DWORD dw = (DWORD) - 1; do { if (len-- == 0 || !GetRemaining()) { return false; } dw = (dw << 8) | (BYTE)BitRead(8); } while ((dw & 0xffffff00) != 0x00000100); code = (BYTE)(dw & 0xff); return true; } // #define MARKER \ if (BitRead(1) != 1) \ { \ ASSERT(0); \ return false; \ } bool CBaseSplitterFileEx::Read(pshdr& h) { memset(&h, 0, sizeof(h)); BYTE b = (BYTE)BitRead(8, true); if ((b & 0xf1) == 0x21) { h.type = mpeg1; EXECUTE_ASSERT(BitRead(4) == 2); h.scr = 0; h.scr |= BitRead(3) << 30; MARKER; // 32..30 h.scr |= BitRead(15) << 15; MARKER; // 29..15 h.scr |= BitRead(15); MARKER; MARKER; // 14..0 h.bitrate = BitRead(22); MARKER; } else if ((b & 0xc4) == 0x44) { h.type = mpeg2; EXECUTE_ASSERT(BitRead(2) == 1); h.scr = 0; h.scr |= BitRead(3) << 30; MARKER; // 32..30 h.scr |= BitRead(15) << 15; MARKER; // 29..15 h.scr |= BitRead(15); MARKER; // 14..0 h.scr = (h.scr * 300 + BitRead(9)) * 10 / 27; MARKER; h.bitrate = BitRead(22); MARKER; MARKER; BitRead(5); // reserved UINT64 stuffing = BitRead(3); while (stuffing-- > 0) { EXECUTE_ASSERT(BitRead(8) == 0xff); } } else { return false; } h.bitrate *= 400; return true; } bool CBaseSplitterFileEx::Read(pssyshdr& h) { memset(&h, 0, sizeof(h)); WORD len = (WORD)BitRead(16); MARKER; h.rate_bound = (DWORD)BitRead(22); MARKER; h.audio_bound = (BYTE)BitRead(6); h.fixed_rate = !!BitRead(1); h.csps = !!BitRead(1); h.sys_audio_loc_flag = !!BitRead(1); h.sys_video_loc_flag = !!BitRead(1); MARKER; h.video_bound = (BYTE)BitRead(5); EXECUTE_ASSERT((BitRead(8) & 0x7f) == 0x7f); // reserved (should be 0xff, but not in reality) for (len -= 6; len > 3; len -= 3) { // TODO: also store these, somewhere, if needed UINT64 stream_id = BitRead(8); UNREFERENCED_PARAMETER(stream_id); EXECUTE_ASSERT(BitRead(2) == 3); UINT64 p_std_buff_size_bound = (BitRead(1) ? 1024 : 128) * BitRead(13); UNREFERENCED_PARAMETER(p_std_buff_size_bound); } return true; } bool CBaseSplitterFileEx::Read(peshdr& h, BYTE code) { memset(&h, 0, sizeof(h)); if (!(code >= 0xbd && code < 0xf0 || code == 0xfd)) { // 0xfd => blu-ray (.m2ts) return false; } h.len = (WORD)BitRead(16); if (code == 0xbe || code == 0xbf) { return true; } // mpeg1 stuffing (ff ff .. , max 16x) for (int i = 0; i < 16 && BitRead(8, true) == 0xff; i++) { BitRead(8); if (h.len) { h.len--; } } h.type = (BYTE)BitRead(2, true) == mpeg2 ? mpeg2 : mpeg1; if (h.type == mpeg1) { BYTE b = (BYTE)BitRead(2); if (b == 1) { h.std_buff_size = (BitRead(1) ? 1024 : 128) * BitRead(13); if (h.len) { h.len -= 2; } b = (BYTE)BitRead(2); } if (b == 0) { h.fpts = (BYTE)BitRead(1); h.fdts = (BYTE)BitRead(1); } } else if (h.type == mpeg2) { EXECUTE_ASSERT(BitRead(2) == mpeg2); h.scrambling = (BYTE)BitRead(2); h.priority = (BYTE)BitRead(1); h.alignment = (BYTE)BitRead(1); h.copyright = (BYTE)BitRead(1); h.original = (BYTE)BitRead(1); h.fpts = (BYTE)BitRead(1); h.fdts = (BYTE)BitRead(1); h.escr = (BYTE)BitRead(1); h.esrate = (BYTE)BitRead(1); h.dsmtrickmode = (BYTE)BitRead(1); h.morecopyright = (BYTE)BitRead(1); h.crc = (BYTE)BitRead(1); h.extension = (BYTE)BitRead(1); h.hdrlen = (BYTE)BitRead(8); } else { if (h.len) while (h.len-- > 0) { BitRead(8); } return false; } if (h.fpts) { if (h.type == mpeg2) { BYTE b = (BYTE)BitRead(4); if (!(h.fdts && b == 3 || !h.fdts && b == 2)) { TRACE(_T("[PES header parser] Warning: Invalid PTS marker\n")); } } h.pts = 0; h.pts |= BitRead(3) << 30; MARKER; // 32..30 h.pts |= BitRead(15) << 15; MARKER; // 29..15 h.pts |= BitRead(15); MARKER; // 14..0 h.pts = 10000 * h.pts / 90 + m_rtPTSOffset; } if (h.fdts) { if ((BYTE)BitRead(4) != 1) { TRACE(_T("[PES header parser] Warning: Invalid DTS marker\n")); } h.dts = 0; h.dts |= BitRead(3) << 30; MARKER; // 32..30 h.dts |= BitRead(15) << 15; MARKER; // 29..15 h.dts |= BitRead(15); MARKER; // 14..0 h.dts = 10000 * h.dts / 90 + m_rtPTSOffset; } // skip to the end of header if (h.type == mpeg1) { if (!h.fpts && !h.fdts && BitRead(4) != 0xf) { /*ASSERT(0);*/ return false; } if (h.len) { h.len--; if (h.pts) { h.len -= 4; } if (h.dts) { h.len -= 5; } } } if (h.type == mpeg2) { if (h.len) { h.len -= 3 + h.hdrlen; } int left = h.hdrlen; if (h.fpts) { left -= 5; } if (h.fdts) { left -= 5; } if (h.extension) { /* PES extension */ BYTE pes_ext = (BYTE)BitRead(8); left--; BYTE skip = (pes_ext >> 4) & 0xb; skip += skip & 0x9; if (pes_ext & 0x40 || skip > left) { TRACE(_T("pes_ext %X is invalid\n"), pes_ext); pes_ext = skip = 0; } for (int i = 0; i < skip; i++) { BitRead(8); } left -= skip; if (pes_ext & 0x01) { /* PES extension 2 */ BYTE ext2_len = (BYTE)BitRead(8); left--; if ((ext2_len & 0x7f) > 0) { BYTE id_ext = (BYTE)BitRead(8); if ((id_ext & 0x80) == 0) { h.id_ext = id_ext; } left--; } } } while (left-- > 0) { BitRead(8); } } return true; } bool CBaseSplitterFileEx::Read(seqhdr& h, int len, CMediaType* pmt) { __int64 endpos = GetPos() + len; // - sequence header length BYTE id = 0; while (GetPos() < endpos && id != 0xb3) { if (!NextMpegStartCode(id, len)) { return false; } } if (id != 0xb3) { return false; } __int64 shpos = GetPos() - 4; h.width = (WORD)BitRead(12); h.height = (WORD)BitRead(12); h.ar = BitRead(4); static int ifps[16] = {0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000, 0, 0, 0, 0, 0, 0, 0}; h.ifps = ifps[BitRead(4)]; h.bitrate = (DWORD)BitRead(18); MARKER; h.vbv = (DWORD)BitRead(10); h.constrained = BitRead(1); h.fiqm = BitRead(1); if (h.fiqm) for (int i = 0; i < _countof(h.iqm); i++) { h.iqm[i] = (BYTE)BitRead(8); } h.fniqm = BitRead(1); if (h.fniqm) for (int i = 0; i < _countof(h.niqm); i++) { h.niqm[i] = (BYTE)BitRead(8); } __int64 shlen = GetPos() - shpos; static float ar[] = { 1.0000f, 1.0000f, 0.6735f, 0.7031f, 0.7615f, 0.8055f, 0.8437f, 0.8935f, 0.9157f, 0.9815f, 1.0255f, 1.0695f, 1.0950f, 1.1575f, 1.2015f, 1.0000f }; h.arx = (int)((float)h.width / ar[h.ar] + 0.5); h.ary = h.height; mpeg_t type = mpeg1; __int64 shextpos = 0, shextlen = 0; if (NextMpegStartCode(id, 8) && id == 0xb5) { // sequence header ext shextpos = GetPos() - 4; h.startcodeid = BitRead(4); h.profile_levelescape = BitRead(1); // reserved, should be 0 h.profile = BitRead(3); h.level = BitRead(4); h.progressive = BitRead(1); h.chroma = BitRead(2); h.width |= (BitRead(2) << 12); h.height |= (BitRead(2) << 12); h.bitrate |= (BitRead(12) << 18); MARKER; h.vbv |= (BitRead(8) << 10); h.lowdelay = BitRead(1); h.ifps = (DWORD)(h.ifps * (BitRead(2) + 1) / (BitRead(5) + 1)); shextlen = GetPos() - shextpos; struct { DWORD x, y; } ar[] = {{h.width, h.height}, {4, 3}, {16, 9}, {221, 100}, {h.width, h.height}}; int i = min(max(h.ar, 1), 5) - 1; h.arx = ar[i].x; h.ary = ar[i].y; type = mpeg2; } h.ifps = 10 * h.ifps / 27; h.bitrate = h.bitrate == (1 << 30) - 1 ? 0 : h.bitrate * 400; int gcd = GCD(h.arx, h.ary); if (gcd > 1) { h.arx /= gcd; h.ary /= gcd; } if (!pmt) { return true; } pmt->majortype = MEDIATYPE_Video; if (type == mpeg1) { pmt->subtype = MEDIASUBTYPE_MPEG1Payload; pmt->formattype = FORMAT_MPEGVideo; int len = FIELD_OFFSET(MPEG1VIDEOINFO, bSequenceHeader) + int(shlen + shextlen); MPEG1VIDEOINFO* vi = (MPEG1VIDEOINFO*)DEBUG_NEW BYTE[len]; memset(vi, 0, len); vi->hdr.dwBitRate = h.bitrate; vi->hdr.AvgTimePerFrame = h.ifps; vi->hdr.bmiHeader.biSize = sizeof(vi->hdr.bmiHeader); vi->hdr.bmiHeader.biWidth = h.width; vi->hdr.bmiHeader.biHeight = h.height; vi->hdr.bmiHeader.biXPelsPerMeter = h.width * h.ary; vi->hdr.bmiHeader.biYPelsPerMeter = h.height * h.arx; vi->cbSequenceHeader = DWORD(shlen + shextlen); Seek(shpos); ByteRead((BYTE*)&vi->bSequenceHeader[0], shlen); if (shextpos && shextlen) { Seek(shextpos); } ByteRead((BYTE*)&vi->bSequenceHeader[0] + shlen, shextlen); pmt->SetFormat((BYTE*)vi, len); delete [] vi; } else if (type == mpeg2) { pmt->subtype = MEDIASUBTYPE_MPEG2_VIDEO; pmt->formattype = FORMAT_MPEG2_VIDEO; int len = FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + int(shlen + shextlen); MPEG2VIDEOINFO* vi = (MPEG2VIDEOINFO*)DEBUG_NEW BYTE[len]; memset(vi, 0, len); vi->hdr.dwBitRate = h.bitrate; vi->hdr.AvgTimePerFrame = h.ifps; vi->hdr.dwPictAspectRatioX = h.arx; vi->hdr.dwPictAspectRatioY = h.ary; vi->hdr.bmiHeader.biSize = sizeof(vi->hdr.bmiHeader); vi->hdr.bmiHeader.biWidth = h.width; vi->hdr.bmiHeader.biHeight = h.height; vi->dwProfile = h.profile; vi->dwLevel = h.level; vi->cbSequenceHeader = DWORD(shlen + shextlen); Seek(shpos); ByteRead((BYTE*)&vi->dwSequenceHeader[0], shlen); if (shextpos && shextlen) { Seek(shextpos); } ByteRead((BYTE*)&vi->dwSequenceHeader[0] + shlen, shextlen); pmt->SetFormat((BYTE*)vi, len); delete [] vi; } else { return false; } return true; } bool CBaseSplitterFileEx::Read(mpahdr& h, int len, bool fAllowV25, CMediaType* pmt) { memset(&h, 0, sizeof(h)); int syncbits = fAllowV25 ? 11 : 12; for (; len >= 4 && BitRead(syncbits, true) != (1 << syncbits) - 1; len--) { BitRead(8); } if (len < 4) { return false; } h.sync = BitRead(11); h.version = BitRead(2); h.layer = BitRead(2); h.crc = BitRead(1); h.bitrate = BitRead(4); h.freq = BitRead(2); h.padding = BitRead(1); h.privatebit = BitRead(1); h.channels = BitRead(2); h.modeext = BitRead(2); h.copyright = BitRead(1); h.original = BitRead(1); h.emphasis = BitRead(2); if (h.version == 1 || h.layer == 0 || h.freq == 3 || h.bitrate == 15 || h.emphasis == 2) { return false; } if (h.version == 3 && h.layer == 2) { if ((h.bitrate == 1 || h.bitrate == 2 || h.bitrate == 3 || h.bitrate == 5) && h.channels != 3 && (h.bitrate >= 11 && h.bitrate <= 14) && h.channels == 3) { return false; } } h.layer = 4 - h.layer; // static int brtbl[][5] = { {0, 0, 0, 0, 0}, {32, 32, 32, 32, 8}, {64, 48, 40, 48, 16}, {96, 56, 48, 56, 24}, {128, 64, 56, 64, 32}, {160, 80, 64, 80, 40}, {192, 96, 80, 96, 48}, {224, 112, 96, 112, 56}, {256, 128, 112, 128, 64}, {288, 160, 128, 144, 80}, {320, 192, 160, 160, 96}, {352, 224, 192, 176, 112}, {384, 256, 224, 192, 128}, {416, 320, 256, 224, 144}, {448, 384, 320, 256, 160}, {0, 0, 0, 0, 0}, }; static int brtblcol[][4] = {{0, 3, 4, 4}, {0, 0, 1, 2}}; int bitrate = 1000 * brtbl[h.bitrate][brtblcol[h.version & 1][h.layer]]; if (bitrate == 0) { return false; } static int freq[][4] = {{11025, 0, 22050, 44100}, {12000, 0, 24000, 48000}, {8000, 0, 16000, 32000}}; bool l3ext = h.layer == 3 && !(h.version & 1); h.nSamplesPerSec = freq[h.freq][h.version]; h.FrameSize = h.layer == 1 ? (12 * bitrate / h.nSamplesPerSec + h.padding) * 4 : (l3ext ? 72 : 144) * bitrate / h.nSamplesPerSec + h.padding; h.rtDuration = 10000000i64 * (h.layer == 1 ? 384 : l3ext ? 576 : 1152) / h.nSamplesPerSec;// / (h.channels == 3 ? 1 : 2); h.nBytesPerSec = bitrate / 8; if (!pmt) { return true; } size_t size = h.layer == 3 ? sizeof(WAVEFORMATEX/*MPEGLAYER3WAVEFORMAT*/) // no need to overcomplicate this... : sizeof(MPEG1WAVEFORMAT); WAVEFORMATEX* wfe = (WAVEFORMATEX*)DEBUG_NEW BYTE[size]; memset(wfe, 0, size); wfe->cbSize = WORD(size - sizeof(WAVEFORMATEX)); if (h.layer == 3) { wfe->wFormatTag = WAVE_FORMAT_MPEGLAYER3; /* MPEGLAYER3WAVEFORMAT* f = (MPEGLAYER3WAVEFORMAT*)wfe; f->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3; f->wID = MPEGLAYER3_ID_UNKNOWN; f->fdwFlags = h.padding ? MPEGLAYER3_FLAG_PADDING_ON : MPEGLAYER3_FLAG_PADDING_OFF; // _OFF or _ISO ? */ } else { MPEG1WAVEFORMAT* f = (MPEG1WAVEFORMAT*)wfe; f->wfx.wFormatTag = WAVE_FORMAT_MPEG; f->fwHeadMode = 1 << h.channels; f->fwHeadModeExt = 1 << h.modeext; f->wHeadEmphasis = h.emphasis + 1; if (h.privatebit) { f->fwHeadFlags |= ACM_MPEG_PRIVATEBIT; } if (h.copyright) { f->fwHeadFlags |= ACM_MPEG_COPYRIGHT; } if (h.original) { f->fwHeadFlags |= ACM_MPEG_ORIGINALHOME; } if (h.crc == 0) { f->fwHeadFlags |= ACM_MPEG_PROTECTIONBIT; } if (h.version == 3) { f->fwHeadFlags |= ACM_MPEG_ID_MPEG1; } f->fwHeadLayer = 1 << (h.layer - 1); f->dwHeadBitrate = bitrate; } wfe->nChannels = h.channels == 3 ? 1 : 2; wfe->nSamplesPerSec = h.nSamplesPerSec; wfe->nBlockAlign = h.FrameSize; wfe->nAvgBytesPerSec = h.nBytesPerSec; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = FOURCCMap(wfe->wFormatTag); pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)wfe, sizeof(WAVEFORMATEX) + wfe->cbSize); delete [] wfe; return true; } bool CBaseSplitterFileEx::Read(latm_aachdr& h, int len, CMediaType* pmt) { memset(&h, 0, sizeof(h)); for (; len >= 7 && BitRead(11, true) != AAC_LATM_SYNC_WORD; len--) { BitRead(8); } if (len < 7) { return false; } BYTE buffer[32] = {0}; ByteRead(buffer, min(len, 32)); if (!ParseAACLATMHeader(buffer, min(len, 32), &h.samplerate, &h.channels)) { return false; } if (!pmt) { return true; } WAVEFORMATEX* wfe = (WAVEFORMATEX*)DEBUG_NEW BYTE[sizeof(WAVEFORMATEX)]; memset(wfe, 0, sizeof(WAVEFORMATEX)); wfe->wFormatTag = WAVE_FORMAT_LATM_AAC; wfe->nChannels = h.channels; wfe->nSamplesPerSec = h.samplerate; wfe->nBlockAlign = 1; wfe->nAvgBytesPerSec = 0; wfe->cbSize = 0; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_LATM_AAC; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)wfe, sizeof(WAVEFORMATEX) + wfe->cbSize); delete [] wfe; return true; } bool CBaseSplitterFileEx::Read(aachdr& h, int len, CMediaType* pmt, MPEG_TYPES m_type) { memset(&h, 0, sizeof(h)); __int64 pos = 0; int found_fake_sync = m_type == mpeg_ts ? 0 : 1; for (;;) { for (; len >= 7 && BitRead(12, true) != AAC_SYNC_WORD; len--) { BitRead(8); } if (len < 7) { return false; } pos = GetPos(); h.sync = BitRead(12); h.version = BitRead(1); h.layer = BitRead(2); h.fcrc = BitRead(1); h.profile = BitRead(2); h.freq = BitRead(4); h.privatebit = BitRead(1); h.channels = BitRead(3); h.original = BitRead(1); h.home = BitRead(1); h.copyright_id_bit = BitRead(1); h.copyright_id_start = BitRead(1); h.aac_frame_length = BitRead(13); h.adts_buffer_fullness = BitRead(11); h.no_raw_data_blocks_in_frame = BitRead(2); if (h.fcrc == 0) { h.crc = (WORD)BitRead(16); } if (h.layer != 0 || h.freq >= 12 || h.aac_frame_length <= (h.fcrc == 0 ? 9 : 7)) { if (found_fake_sync) { // skip only one "fake" sync. TODO - find better way to detect and skip "fake" sync return false; } found_fake_sync++; Seek(pos + 1); len--; continue; } h.FrameSize = h.aac_frame_length - (h.fcrc == 0 ? 9 : 7); static int freq[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000}; h.nBytesPerSec = h.aac_frame_length * freq[h.freq] / 1024; // ok? h.rtDuration = 10000000i64 * 1024 / freq[h.freq]; // ok? if (!pmt) { return true; } WAVEFORMATEX* wfe = (WAVEFORMATEX*)DEBUG_NEW BYTE[sizeof(WAVEFORMATEX) + 5]; memset(wfe, 0, sizeof(WAVEFORMATEX) + 5); wfe->wFormatTag = WAVE_FORMAT_AAC; wfe->nChannels = h.channels <= 6 ? h.channels : 2; wfe->nSamplesPerSec = freq[h.freq]; wfe->nBlockAlign = h.aac_frame_length; wfe->nAvgBytesPerSec = h.nBytesPerSec; wfe->cbSize = MakeAACInitData((BYTE*)(wfe + 1), h.profile, wfe->nSamplesPerSec, wfe->nChannels); pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_AAC; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)wfe, sizeof(WAVEFORMATEX) + wfe->cbSize); delete [] wfe; return true; } } bool CBaseSplitterFileEx::Read(ac3hdr& h, int len, CMediaType* pmt, bool find_sync, bool AC3CoreOnly) { static int freq[] = {48000, 44100, 32000, 0}; bool e_ac3 = false; __int64 startpos = GetPos(); memset(&h, 0, sizeof(h)); // Parse TrueHD and MLP header if (!AC3CoreOnly) { BYTE buf[20]; int channels; int samplerate; int framelength; WORD bitdepth; bool isTrueHD; int fsize = 0; ByteRead(buf, 20); fsize = ParseMLPHeader(buf, &samplerate, &channels, &framelength, &bitdepth, &isTrueHD); if (fsize) { if (!pmt) { return true; } int bitrate = (int)(fsize * 8i64 * samplerate / framelength); // inaccurate, because fsize is not constant pmt->majortype = MEDIATYPE_Audio; pmt->subtype = isTrueHD ? MEDIASUBTYPE_DOLBY_TRUEHD : MEDIASUBTYPE_MLP; pmt->formattype = FORMAT_WaveFormatEx; WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX)); wfe->wFormatTag = WAVE_FORMAT_UNKNOWN; wfe->nChannels = channels; wfe->nSamplesPerSec = samplerate; wfe->nAvgBytesPerSec = (bitrate + 4) / 8; wfe->nBlockAlign = fsize < WORD_MAX ? fsize : WORD_MAX; wfe->wBitsPerSample = bitdepth; wfe->cbSize = 0; pmt->SetSampleSize(0); return true; } } Seek(startpos); if (find_sync) { for (; len >= 7 && BitRead(16, true) != 0x0b77; len--) { BitRead(8); } } if (len < 7) { return false; } h.sync = (WORD)BitRead(16); if (h.sync != 0x0B77) { return false; } _int64 pos = GetPos(); h.crc1 = (WORD)BitRead(16); h.fscod = BitRead(2); h.frmsizecod = BitRead(6); h.bsid = BitRead(5); if (h.bsid > 16) { return false; } if (h.bsid <= 10) { /* Normal AC-3 */ if (h.fscod == 3) { return false; } if (h.frmsizecod > 37) { return false; } h.bsmod = BitRead(3); h.acmod = BitRead(3); if (h.acmod == 2) { h.dsurmod = BitRead(2); } if ((h.acmod & 1) && h.acmod != 1) { h.cmixlev = BitRead(2); } if (h.acmod & 4) { h.surmixlev = BitRead(2); } h.lfeon = BitRead(1); h.sr_shift = max(h.bsid, 8) - 8; } else { /* Enhanced AC-3 */ e_ac3 = true; Seek(pos); h.frame_type = (BYTE)BitRead(2); h.substreamid = (BYTE)BitRead(3); if (h.frame_type || h.substreamid) { return false; } h.frame_size = ((WORD)BitRead(11) + 1) << 1; if (h.frame_size < 7) { return false; } h.sr_code = (BYTE)BitRead(2); if (h.sr_code == 3) { BYTE sr_code2 = (BYTE)BitRead(2); if (sr_code2 == 3) { return false; } h.sample_rate = freq[sr_code2] / 2; h.sr_shift = 1; } else { static int eac3_blocks[4] = {1, 2, 3, 6}; h.num_blocks = eac3_blocks[BitRead(2)]; h.sample_rate = freq[h.sr_code]; h.sr_shift = 0; } h.acmod = BitRead(3); h.lfeon = BitRead(1); } if (!pmt) { return true; } WAVEFORMATEX wfe; memset(&wfe, 0, sizeof(wfe)); wfe.wFormatTag = WAVE_FORMAT_DOLBY_AC3; static int channels[] = {2, 1, 2, 3, 3, 4, 4, 5}; wfe.nChannels = channels[h.acmod] + h.lfeon; if (!e_ac3) { wfe.nSamplesPerSec = freq[h.fscod] >> h.sr_shift; static int rate[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640, 768, 896, 1024, 1152, 1280}; wfe.nAvgBytesPerSec = ((rate[h.frmsizecod >> 1] * 1000) >> h.sr_shift) / 8; } else { wfe.nSamplesPerSec = h.sample_rate; wfe.nAvgBytesPerSec = h.frame_size * h.sample_rate / (h.num_blocks * 256); } wfe.nBlockAlign = (WORD)(1536 * wfe.nAvgBytesPerSec / wfe.nSamplesPerSec); pmt->majortype = MEDIATYPE_Audio; if (e_ac3) { pmt->subtype = MEDIASUBTYPE_DOLBY_DDPLUS; } else { pmt->subtype = MEDIASUBTYPE_DOLBY_AC3; } pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); return true; } bool CBaseSplitterFileEx::Read(dtshdr& h, int len, CMediaType* pmt, bool find_sync) { memset(&h, 0, sizeof(h)); if (find_sync) { for (; len >= 10 && BitRead(32, true) != 0x7ffe8001; len--) { BitRead(8); } } if (len < 10) { return false; } h.sync = (DWORD)BitRead(32); if (h.sync != 0x7ffe8001) { return false; } h.frametype = BitRead(1); h.deficitsamplecount = BitRead(5); h.fcrc = BitRead(1); h.nblocks = BitRead(7) + 1; h.framebytes = (WORD)BitRead(14) + 1; h.amode = BitRead(6); h.sfreq = BitRead(4); h.rate = BitRead(5); h.downmix = BitRead(1); h.dynrange = BitRead(1); h.timestamp = BitRead(1); h.aux_data = BitRead(1); h.hdcd = BitRead(1); h.ext_descr = BitRead(3); h.ext_coding = BitRead(1); h.aspf = BitRead(1); h.lfe = BitRead(2); h.predictor_history = BitRead(1); if (!pmt) { return true; } WAVEFORMATEX wfe; memset(&wfe, 0, sizeof(wfe)); wfe.wFormatTag = WAVE_FORMAT_DVD_DTS; static int channels[] = {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8}; if (h.amode < _countof(channels)) { wfe.nChannels = channels[h.amode]; if (h.lfe > 0) { ++wfe.nChannels; } } static int freq[] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0}; wfe.nSamplesPerSec = freq[h.sfreq]; /*static int rate[] = { 32000, 56000, 64000, 96000, 112000, 128000, 192000, 224000, 256000, 320000, 384000, 448000, 512000, 576000, 640000, 768000, 960000, 1024000, 1152000, 1280000, 1344000, 1408000, 1411200, 1472000, 1536000, 1920000, 2048000, 3072000, 3840000, 0, 0, 0 //open, variable, lossless }; int nom_bitrate = rate[h.rate];*/ unsigned int bitrate = (unsigned int)(8ui64 * h.framebytes * wfe.nSamplesPerSec / (h.nblocks * 32)); wfe.nAvgBytesPerSec = (bitrate + 4) / 8; wfe.nBlockAlign = h.framebytes; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_DTS; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); return true; } bool CBaseSplitterFileEx::Read(lpcmhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); h.emphasis = BitRead(1); h.mute = BitRead(1); h.reserved1 = BitRead(1); h.framenum = BitRead(5); h.quantwordlen = BitRead(2); h.freq = BitRead(2); h.reserved2 = BitRead(1); h.channels = BitRead(3); h.drc = (BYTE)BitRead(8); if (h.quantwordlen == 3 || h.reserved1 || h.reserved2) { return false; } if (!pmt) { return true; } WAVEFORMATEX wfe; memset(&wfe, 0, sizeof(wfe)); wfe.wFormatTag = WAVE_FORMAT_PCM; wfe.nChannels = h.channels + 1; static int freq[] = {48000, 96000, 44100, 32000}; wfe.nSamplesPerSec = freq[h.freq]; switch (h.quantwordlen) { case 0: wfe.wBitsPerSample = 16; break; case 1: wfe.wBitsPerSample = 20; break; case 2: wfe.wBitsPerSample = 24; break; } wfe.nBlockAlign = (wfe.nChannels * 2 * wfe.wBitsPerSample) / 8; wfe.nAvgBytesPerSec = (wfe.nBlockAlign * wfe.nSamplesPerSec) / 2; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_DVD_LPCM_AUDIO; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); return true; } bool CBaseSplitterFileEx::Read(dvdalpcmhdr& h, int len, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if (len < 8) { return false; } h.firstaudioframe = (WORD)BitRead(16);// Byte pointer to start of first audio frame. h.unknown1 = (BYTE)BitRead(8); // Unknown - e.g. 0x10 for stereo, 0x00 for surround if (h.unknown1 != 0x10 && h.unknown1 != 0x00) { return false; // this is not the aob. maybe this is a vob. } h.bitpersample1 = (BYTE)BitRead(4); h.bitpersample2 = (BYTE)BitRead(4); h.samplerate1 = (BYTE)BitRead(4); h.samplerate2 = (BYTE)BitRead(4); h.unknown2 = (BYTE)BitRead(8); // Unknown - e.g. 0x00 h.groupassignment = (BYTE)BitRead(8); // Channel Group Assignment h.unknown3 = (BYTE)BitRead(8); // Unknown - e.g. 0x80 if (h.bitpersample1 > 2 || (h.samplerate1 & 7) > 2 || h.groupassignment > 20 || h.unknown2 != 0x00 || h.unknown3 != 0x80) { return false; // poor parameters or this is a vob. } // decoder limitations if (h.groupassignment > 1 && (h.bitpersample2 != h.bitpersample1 || h.samplerate2 != h.samplerate1)) { return false; // decoder does not support different bit depth and frequency. } if (!pmt) { return true; } WAVEFORMATEX wfe; memset(&wfe, 0, sizeof(wfe)); wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; static const WORD depth[] = {16, 20, 24}; static const DWORD freq[] = {48000, 96000, 192000, 0, 0, 0, 0, 0, 44100, 88200, 1764000}; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 static const WORD channels1[] = {1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4}; static const WORD channels2[] = {0, 0, 1, 2, 1, 2, 3, 1, 2, 3, 2, 3, 4, 1, 2, 1, 2, 3, 1, 1, 2}; wfe.wBitsPerSample = depth[h.bitpersample1]; wfe.nSamplesPerSec = freq[h.samplerate1]; wfe.nChannels = channels1[h.groupassignment] + channels2[h.groupassignment]; if (wfe.nChannels > 2) { wfe.nBlockAlign = (depth[h.bitpersample1] * channels1[h.groupassignment] * (WORD)(freq[h.samplerate1] / freq[h.samplerate2]) + depth[h.bitpersample2] * channels2[h.groupassignment]) * 2 / 8; } else { wfe.nBlockAlign = depth[h.bitpersample1] * channels1[h.groupassignment] * 2 / 8; } wfe.nAvgBytesPerSec = wfe.nBlockAlign * wfe.nSamplesPerSec / 2; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_DVD_LPCM_AUDIO; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); return true; } bool CBaseSplitterFileEx::Read(hdmvlpcmhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); h.size = (WORD)BitRead(16); h.channels = (BYTE)BitRead(4); h.samplerate = (BYTE)BitRead(4); h.bitpersample = (BYTE)BitRead(2); if (h.channels == 0 || h.channels == 2 || (h.samplerate != 1 && h.samplerate != 4 && h.samplerate != 5) || h.bitpersample < 0 || h.bitpersample > 3) { return false; } if (!pmt) { return true; } WAVEFORMATEX_HDMV_LPCM wfe; wfe.wFormatTag = WAVE_FORMAT_PCM; static int channels[] = {0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8}; wfe.nChannels = channels[h.channels]; wfe.channel_conf = h.channels; static int freq[] = {0, 48000, 0, 0, 96000, 192000}; wfe.nSamplesPerSec = freq[h.samplerate]; static int bitspersample[] = {0, 16, 20, 24}; wfe.wBitsPerSample = bitspersample[h.bitpersample]; wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample >> 3; wfe.nAvgBytesPerSec = wfe.nBlockAlign * wfe.nSamplesPerSec; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_HDMV_LPCM_AUDIO; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); return true; } bool CBaseSplitterFileEx::Read(mlphdr& h, int len, CMediaType* pmt, bool find_sync) { memset(&h, 0, sizeof(h)); if (len < 20) { return false; } __int64 startpos = GetPos(); int samplerate, channels, framelength; WORD bitdepth; bool isTrueHD; int fsize = 0; BYTE buf[20]; int k = find_sync ? len - 20 : 1; int i = 0; while (i < k) { Seek(startpos + i); ByteRead(buf, 20); if (GetMLPFrameSize(buf)) { fsize = ParseMLPHeader(buf, &samplerate, &channels, &framelength, &bitdepth, &isTrueHD); break; } ++i; } if (fsize && !isTrueHD) { h.size = fsize; if (!pmt) { return true; } int bitrate = (int)(fsize * 8i64 * samplerate / framelength); // inaccurate, because fsize is not constant pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_MLP; pmt->formattype = FORMAT_WaveFormatEx; WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX)); wfe->wFormatTag = WAVE_FORMAT_UNKNOWN; wfe->nChannels = channels; wfe->nSamplesPerSec = samplerate; wfe->nAvgBytesPerSec = (bitrate + 4) / 8; wfe->nBlockAlign = fsize < WORD_MAX ? fsize : WORD_MAX; wfe->wBitsPerSample = bitdepth; wfe->cbSize = 0; pmt->SetSampleSize(0); Seek(startpos + i); return true; } return false; } bool CBaseSplitterFileEx::Read(dvdspuhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if (!pmt) { return true; } pmt->majortype = MEDIATYPE_Video; pmt->subtype = MEDIASUBTYPE_DVD_SUBPICTURE; pmt->formattype = FORMAT_None; return true; } bool CBaseSplitterFileEx::Read(hdmvsubhdr& h, CMediaType* pmt, const char* language_code) { memset(&h, 0, sizeof(h)); if (!pmt) { return true; } pmt->majortype = MEDIATYPE_Subtitle; pmt->subtype = MEDIASUBTYPE_HDMVSUB; pmt->formattype = FORMAT_None; SUBTITLEINFO* psi = (SUBTITLEINFO*)pmt->AllocFormatBuffer(sizeof(SUBTITLEINFO)); if (psi) { memset(psi, 0, pmt->FormatLength()); strcpy_s(psi->IsoLang, language_code ? language_code : "eng"); } return true; } bool CBaseSplitterFileEx::Read(svcdspuhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if (!pmt) { return true; } pmt->majortype = MEDIATYPE_Video; pmt->subtype = MEDIASUBTYPE_SVCD_SUBPICTURE; pmt->formattype = FORMAT_None; return true; } bool CBaseSplitterFileEx::Read(cvdspuhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if (!pmt) { return true; } pmt->majortype = MEDIATYPE_Video; pmt->subtype = MEDIASUBTYPE_CVD_SUBPICTURE; pmt->formattype = FORMAT_None; return true; } bool CBaseSplitterFileEx::Read(ps2audhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if (BitRead(16, true) != 'SS') { return false; } __int64 pos = GetPos(); while (BitRead(16, true) == 'SS') { DWORD tag = (DWORD)BitRead(32, true); DWORD size = 0; if (tag == 'SShd') { BitRead(32); ByteRead((BYTE*)&size, sizeof(size)); ASSERT(size == 0x18); Seek(GetPos()); ByteRead((BYTE*)&h, sizeof(h)); } else if (tag == 'SSbd') { BitRead(32); ByteRead((BYTE*)&size, sizeof(size)); break; } } Seek(pos); if (!pmt) { return true; } WAVEFORMATEXPS2 wfe; wfe.wFormatTag = h.unk1 == 0x01 ? WAVE_FORMAT_PS2_PCM : h.unk1 == 0x10 ? WAVE_FORMAT_PS2_ADPCM : WAVE_FORMAT_UNKNOWN; wfe.nChannels = (WORD)h.channels; wfe.nSamplesPerSec = h.freq; wfe.wBitsPerSample = 16; // always? wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample >> 3; wfe.nAvgBytesPerSec = wfe.nBlockAlign * wfe.nSamplesPerSec; wfe.dwInterleave = h.interleave; pmt->majortype = MEDIATYPE_Audio; pmt->subtype = FOURCCMap(wfe.wFormatTag); pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); return true; } bool CBaseSplitterFileEx::Read(ps2subhdr& h, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if (!pmt) { return true; } pmt->majortype = MEDIATYPE_Subtitle; pmt->subtype = MEDIASUBTYPE_PS2_SUB; pmt->formattype = FORMAT_None; return true; } bool CBaseSplitterFileEx::Read(tshdr& h, bool fSync) { memset(&h, 0, sizeof(h)); BitByteAlign(); if (m_tslen == 0) { __int64 pos = GetPos(); int count = 0; for (int i = 0; i < 192; i++) { if (BitRead(8, true) == 0x47) { __int64 pos = GetPos(); Seek(pos + 188); if (BitRead(8, true) == 0x47) { if (m_tslen != 188) { count = 0; } m_tslen = 188; // TS stream if (count > 1) { break; } count++; } else { Seek(pos + 192); if (BitRead(8, true) == 0x47) { if (m_tslen != 192) { count = 0; } m_tslen = 192; // M2TS stream if (count > 1) { break; } count++; } } } else { BitRead(8); } } Seek(pos); if (m_tslen == 0) { return false; } } if (fSync) { for (int i = 0; i < m_tslen; i++) { if (BitRead(8, true) == 0x47) { if (i == 0) { break; } Seek(GetPos() + m_tslen); if (BitRead(8, true) == 0x47) { Seek(GetPos() - m_tslen); break; } } BitRead(8); if (i == m_tslen - 1) { return false; } } } if (BitRead(8, true) != 0x47) { return false; } h.next = GetPos() + m_tslen; h.sync = (BYTE)BitRead(8); h.error = BitRead(1); h.payloadstart = BitRead(1); h.transportpriority = BitRead(1); h.pid = BitRead(13); h.scrambling = BitRead(2); h.adapfield = BitRead(1); h.payload = BitRead(1); h.counter = BitRead(4); h.bytes = 188 - 4; if (h.adapfield) { h.length = (BYTE)BitRead(8); if (h.length > 0) { h.discontinuity = BitRead(1); h.randomaccess = BitRead(1); h.priority = BitRead(1); h.fPCR = BitRead(1); h.OPCR = BitRead(1); h.splicingpoint = BitRead(1); h.privatedata = BitRead(1); h.extension = BitRead(1); int i = 1; if (h.fPCR && h.length > 6) { h.PCR = BitRead(33); BitRead(6); UINT64 PCRExt = BitRead(9); h.PCR = (h.PCR * 300 + PCRExt) * 10 / 27; i += 6; } h.length = min(h.length, h.bytes - 1); for (; i < h.length; i++) { BitRead(8); } } h.bytes -= h.length + 1; if (h.bytes < 0) { ASSERT(0); return false; } } return true; } bool CBaseSplitterFileEx::Read(trsechdr& h) { memset(&h, 0, sizeof(h)); BYTE pointer_field = (BYTE)BitRead(8); while (pointer_field-- > 0) { BitRead(8); } h.table_id = (BYTE)BitRead(8); h.section_syntax_indicator = (WORD)BitRead(1); h.zero = (WORD)BitRead(1); h.reserved1 = (WORD)BitRead(2); h.section_length = (WORD)BitRead(12); h.transport_stream_id = (WORD)BitRead(16); h.reserved2 = (BYTE)BitRead(2); h.version_number = (BYTE)BitRead(5); h.current_next_indicator = (BYTE)BitRead(1); h.section_number = (BYTE)BitRead(8); h.last_section_number = (BYTE)BitRead(8); return h.section_syntax_indicator == 1 && h.zero == 0; } bool CBaseSplitterFileEx::Read(pvahdr& h, bool fSync) { memset(&h, 0, sizeof(h)); BitByteAlign(); if (fSync) { for (int i = 0; i < MAX_PROBE_SIZE; i++) { if ((BitRead(64, true) & 0xfffffc00ffe00000i64) == 0x4156000055000000i64) { break; } BitRead(8); } } if ((BitRead(64, true) & 0xfffffc00ffe00000i64) != 0x4156000055000000i64) { return false; } h.sync = (WORD)BitRead(16); h.streamid = (BYTE)BitRead(8); h.counter = (BYTE)BitRead(8); h.res1 = (BYTE)BitRead(8); h.res2 = BitRead(3); h.fpts = BitRead(1); h.postbytes = BitRead(2); h.prebytes = BitRead(2); h.length = (WORD)BitRead(16); if (h.length > 6136) { return false; } __int64 pos = GetPos(); if (h.streamid == 1 && h.fpts) { h.pts = 10000 * BitRead(32) / 90 + m_rtPTSOffset; } else if (h.streamid == 2 && (h.fpts || (BitRead(32, true) & 0xffffffe0) == 0x000001c0)) { BYTE b; if (!NextMpegStartCode(b, 4)) { return false; } peshdr h2; if (!Read(h2, b)) { return false; } // Maybe bug, code before: if (h.fpts = h2.fpts) h.pts = h2.pts; h.fpts = h2.fpts; if (h.fpts) { h.pts = h2.pts; } } BitRead(8 * h.prebytes); h.length -= (WORD)(GetPos() - pos); return true; } int CBaseSplitterFileEx::HrdParameters(CGolombBuffer& gb) { UINT64 cnt = gb.UExpGolombRead(); // cpb_cnt_minus1 if (cnt > 32U) { return -1; } gb.BitRead(4); // bit_rate_scale gb.BitRead(4); // cpb_size_scale for (unsigned int i = 0; i <= cnt; i++) { gb.UExpGolombRead(); // bit_rate_value_minus1 gb.UExpGolombRead(); // cpb_size_value_minus1 gb.BitRead(1); // cbr_flag } gb.BitRead(5); // initial_cpb_removal_delay_length_minus1 gb.BitRead(5); // cpb_removal_delay_length_minus1 gb.BitRead(5); // dpb_output_delay_length_minus1 gb.BitRead(5); // time_offset_length return 0; } void CBaseSplitterFileEx::RemoveMpegEscapeCode(BYTE* dst, BYTE* src, int length) { int si = 0; int di = 0; while (si + 2 < length) { //remove escapes (very rare 1:2^22) if (src[si + 2] > 3) { dst[di++] = src[si++]; dst[di++] = src[si++]; } else if (src[si] == 0 && src[si + 1] == 0) { if (src[si + 2] == 3) { //escape dst[di++] = 0; dst[di++] = 0; si += 3; continue; } else { //next start code return; } } dst[di++] = src[si++]; } } bool CBaseSplitterFileEx::Read(avchdr& h, int len, CMediaType* pmt) { __int64 endpos = GetPos() + len; __int64 nalstartpos = GetPos(); //__int64 nalendpos; bool repeat = false; // First try search for the start code DWORD _dwStartCode = (DWORD)BitRead(32, true); while (GetPos() < endpos + 4 && (_dwStartCode & 0xFFFFFF1F) != 0x101 && // Coded slide of a non-IDR (_dwStartCode & 0xFFFFFF1F) != 0x105 && // Coded slide of an IDR (_dwStartCode & 0xFFFFFF1F) != 0x107 && // Sequence Parameter Set (_dwStartCode & 0xFFFFFF1F) != 0x108 && // Picture Parameter Set (_dwStartCode & 0xFFFFFF1F) != 0x109 && // Access Unit Delimiter (_dwStartCode & 0xFFFFFF1F) != 0x10f // Subset Sequence Parameter Set (MVC) ) { BitRead(8); _dwStartCode = (DWORD)BitRead(32, true); } if (GetPos() >= endpos + 4) { return false; } // At least a SPS (normal or subset) and a PPS is required while (GetPos() < endpos + 4 && (!(h.spspps[index_sps].complete || h.spspps[index_subsetsps].complete) || !h.spspps[index_pps1].complete || repeat)) { BYTE id = h.lastid; repeat = false; // Get array index from NAL unit type spsppsindex index = index_unknown; if ((id & 0x60) != 0) { if ((id & 0x9f) == 0x07) { index = index_sps; } else if ((id & 0x9f) == 0x0F) { index = index_subsetsps; } else if ((id & 0x9f) == 0x08) { index = h.spspps[index_pps1].complete ? index_pps2 : index_pps1; } } // Search for next start code DWORD dwStartCode = (DWORD)BitRead(32, true); while (GetPos() < endpos + 4 && (dwStartCode != 0x00000001) && (dwStartCode & 0xFFFFFF00) != 0x00000100) { BitRead(8); dwStartCode = (DWORD)BitRead(32, true); } //nalendpos = GetPos(); // Skip start code __int64 pos; if (GetPos() < endpos + 4) { if (dwStartCode == 0x00000001) { BitRead(32); } else { BitRead(24); } pos = GetPos(); h.lastid = (BYTE)BitRead(8); } else { pos = GetPos() - 4; } // The SPS or PPS might be fragmented, copy data into buffer until NAL is complete if (index >= 0) { if (h.spspps[index].complete) { // Don't handle SPS/PPS twice continue; } else if (pos > nalstartpos) { // Copy into buffer Seek(nalstartpos); unsigned int bufsize = _countof(h.spspps[index].buffer); int len = min(int(bufsize - h.spspps[index].size), int(pos - nalstartpos)); ByteRead(h.spspps[index].buffer + h.spspps[index].size, len); Seek(pos); h.spspps[index].size += len; //ASSERT(h.spspps[index].size < bufsize); // disable for better debug ... if (h.spspps[index].size >= bufsize || dwStartCode == 0x00000001 || (dwStartCode & 0xFFFFFF00) == 0x00000100) { if (Read(h, index)) { h.spspps[index].complete = true; h.spspps[index].size -= 4; } else { h.spspps[index].size = 0; } } repeat = true; } } nalstartpos = pos; } // Exit and wait for next packet if there is no SPS and PPS yet if ((!h.spspps[index_sps].complete && !h.spspps[index_subsetsps].complete) || !h.spspps[index_pps1].complete || repeat) { return false; } if (!pmt) { return true; } { // Calculate size of extra data int extra = 0; for (int i = 0; i < 4; i++) { if (h.spspps[i].complete) { extra += 2 + (h.spspps[i].size); } } pmt->majortype = MEDIATYPE_Video; if (h.spspps[index_subsetsps].complete && !h.spspps[index_sps].complete) { pmt->subtype = FOURCCMap('CVME'); // MVC stream without base view } else if (h.spspps[index_subsetsps].complete && h.spspps[index_sps].complete) { pmt->subtype = FOURCCMap('CVMA'); // MVC stream with base view } else { pmt->subtype = FOURCCMap('1CVA'); // AVC stream } //pmt->subtype = MEDIASUBTYPE_H264; // TODO : put MEDIASUBTYPE_H264 to support Windows 7 decoder ! pmt->formattype = FORMAT_MPEG2_VIDEO; int len = FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + extra; MPEG2VIDEOINFO* vi = (MPEG2VIDEOINFO*)DEBUG_NEW BYTE[len]; memset(vi, 0, len); // vi->hdr.dwBitRate = ; vi->hdr.AvgTimePerFrame = h.AvgTimePerFrame; if (!h.sar.num) { h.sar.num = 1; } if (!h.sar.den) { h.sar.den = 1; } CSize aspect(h.width * h.sar.num, h.height * h.sar.den); int gcd = GCD(aspect.cx, aspect.cy); if (gcd > 1) { aspect.cx /= gcd; aspect.cy /= gcd; } if (aspect.cx * 2 < aspect.cy) { delete [] vi; return false; } vi->hdr.dwPictAspectRatioX = aspect.cx; vi->hdr.dwPictAspectRatioY = aspect.cy; vi->hdr.bmiHeader.biSize = sizeof(vi->hdr.bmiHeader); vi->hdr.bmiHeader.biWidth = h.width; vi->hdr.bmiHeader.biHeight = h.height; if (h.spspps[index_subsetsps].complete && !h.spspps[index_sps].complete) { vi->hdr.bmiHeader.biCompression = 'CVME'; } else if (h.spspps[index_subsetsps].complete && h.spspps[index_sps].complete) { vi->hdr.bmiHeader.biCompression = 'CVMA'; } else { vi->hdr.bmiHeader.biCompression = '1CVA'; } vi->dwProfile = h.profile; vi->dwFlags = 4; // ? vi->dwLevel = h.level; vi->cbSequenceHeader = extra; // Copy extra data BYTE* p = (BYTE*)&vi->dwSequenceHeader[0]; for (int i = 0; i < 4; i++) { if (h.spspps[i].complete) { *p++ = (h.spspps[i].size) >> 8; *p++ = (h.spspps[i].size) & 0xff; memcpy(p, h.spspps[i].buffer, h.spspps[i].size); p += h.spspps[i].size; } } pmt->SetFormat((BYTE*)vi, len); delete [] vi; } return true; } bool CBaseSplitterFileEx::Read(avchdr& h, spsppsindex index) { static BYTE profiles[] = {44, 66, 77, 88, 100, 110, 118, 122, 128, 144, 244}; static BYTE levels[] = {10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51}; // Only care about SPS and subset SPS if (index != index_sps && index != index_subsetsps) { return true; } // Manage escape codes BYTE buffer[MAX_SPSPPS]; RemoveMpegEscapeCode(buffer, h.spspps[index].buffer, MAX_SPSPPS); CGolombBuffer gb(buffer, MAX_SPSPPS); gb.BitRead(8); // nal_unit_type h.profile = (BYTE)gb.BitRead(8); bool b_ident = false; for (int i = 0; i < sizeof(profiles); i++) { if (h.profile == profiles[i]) { b_ident = true; break; } } if (!b_ident) { return false; } gb.BitRead(8); h.level = (BYTE)gb.BitRead(8); b_ident = false; for (int i = 0; i < sizeof(levels); i++) { if (h.level == levels[i]) { b_ident = true; break; } } if (!b_ident) { return false; } UINT64 sps_id = gb.UExpGolombRead(); // seq_parameter_set_id if (sps_id >= 32) { return false; } UINT64 chroma_format_idc = 0; if (h.profile >= 100) { // high profile chroma_format_idc = gb.UExpGolombRead(); if (chroma_format_idc == 3) { // chroma_format_idc gb.BitRead(1); // residue_transform_flag } gb.UExpGolombRead(); // bit_depth_luma_minus8 gb.UExpGolombRead(); // bit_depth_chroma_minus8 gb.BitRead(1); // qpprime_y_zero_transform_bypass_flag if (gb.BitRead(1)) { // seq_scaling_matrix_present_flag for (int i = 0; i < 8; i++) { if (gb.BitRead(1)) { // seq_scaling_list_present_flag for (int j = 0, size = i < 6 ? 16 : 64, next = 8; j < size && next != 0; ++j) { next = (next + gb.SExpGolombRead() + 256) & 255; } } } } } gb.UExpGolombRead(); // log2_max_frame_num_minus4 UINT64 pic_order_cnt_type = gb.UExpGolombRead(); if (pic_order_cnt_type == 0) { gb.UExpGolombRead(); // log2_max_pic_order_cnt_lsb_minus4 } else if (pic_order_cnt_type == 1) { gb.BitRead(1); // delta_pic_order_always_zero_flag gb.SExpGolombRead(); // offset_for_non_ref_pic gb.SExpGolombRead(); // offset_for_top_to_bottom_field UINT64 num_ref_frames_in_pic_order_cnt_cycle = gb.UExpGolombRead(); if (num_ref_frames_in_pic_order_cnt_cycle >= 256) { return false; } for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) { gb.SExpGolombRead(); // offset_for_ref_frame[i] } } else if (pic_order_cnt_type != 2) { return false; } UINT64 ref_frame_count = gb.UExpGolombRead(); // num_ref_frames if (ref_frame_count > 30) { return false; } gb.BitRead(1); // gaps_in_frame_num_value_allowed_flag UINT64 pic_width_in_mbs_minus1 = gb.UExpGolombRead(); UINT64 pic_height_in_map_units_minus1 = gb.UExpGolombRead(); BYTE frame_mbs_only_flag = (BYTE)gb.BitRead(1); if (!frame_mbs_only_flag) { gb.BitRead(1); // mb_adaptive_frame_field_flag } BYTE direct_8x8_inference_flag = (BYTE)gb.BitRead(1); // direct_8x8_inference_flag if (!frame_mbs_only_flag && !direct_8x8_inference_flag) { return false; } if (gb.BitRead(1)) { // frame_cropping_flag h.crop_left = (unsigned int)gb.UExpGolombRead(); // frame_cropping_rect_left_offset h.crop_right = (unsigned int)gb.UExpGolombRead(); // frame_cropping_rect_right_offset h.crop_top = (unsigned int)gb.UExpGolombRead(); // frame_cropping_rect_top_offset h.crop_bottom = (unsigned int)gb.UExpGolombRead(); // frame_cropping_rect_bottom_offset } if (gb.BitRead(1)) { // vui_parameters_present_flag if (gb.BitRead(1)) { // aspect_ratio_info_present_flag BYTE aspect_ratio_idc = (BYTE)gb.BitRead(8); // aspect_ratio_idc if (255 == aspect_ratio_idc) { h.sar.num = (WORD)gb.BitRead(16); // sar_width h.sar.den = (WORD)gb.BitRead(16); // sar_height } else if (aspect_ratio_idc < 17) { h.sar.num = pixel_aspect[aspect_ratio_idc][0]; h.sar.den = pixel_aspect[aspect_ratio_idc][1]; } else { return false; } } else { h.sar.num = 1; h.sar.den = 1; } if (gb.BitRead(1)) { // overscan_info_present_flag gb.BitRead(1); // overscan_appropriate_flag } if (gb.BitRead(1)) { // video_signal_type_present_flag gb.BitRead(3); // video_format gb.BitRead(1); // video_full_range_flag if (gb.BitRead(1)) { // colour_description_present_flag gb.BitRead(8); // colour_primaries gb.BitRead(8); // transfer_characteristics gb.BitRead(8); // matrix_coefficients } } if (gb.BitRead(1)) { // chroma_location_info_present_flag gb.UExpGolombRead(); // chroma_sample_loc_type_top_field gb.UExpGolombRead(); // chroma_sample_loc_type_bottom_field } if (gb.BitRead(1)) { // timing_info_present_flag __int64 num_units_in_tick = gb.BitRead(32); __int64 time_scale = gb.BitRead(32); /*long fixed_frame_rate_flag = */ gb.BitRead(1); // Trick for weird parameters if ((num_units_in_tick < 1000) || (num_units_in_tick > 1001)) { if ((time_scale % num_units_in_tick != 0) && ((time_scale * 1001) % num_units_in_tick == 0)) { time_scale = (time_scale * 1001) / num_units_in_tick; num_units_in_tick = 1001; } else { time_scale = (time_scale * 1000) / num_units_in_tick; num_units_in_tick = 1000; } } time_scale = time_scale / 2; // VUI consider fields even for progressive stream : divide by 2! if (time_scale) { h.AvgTimePerFrame = (10000000I64 * num_units_in_tick) / time_scale; } } bool nalflag = !!gb.BitRead(1); // nal_hrd_parameters_present_flag if (nalflag) { if (HrdParameters(gb) < 0) { return false; } } bool vlcflag = !!gb.BitRead(1); // vlc_hrd_parameters_present_flag if (vlcflag) { if (HrdParameters(gb) < 0) { return false; } } if (nalflag || vlcflag) { gb.BitRead(1); // low_delay_hrd_flag } gb.BitRead(1); // pic_struct_present_flag if (gb.BitRead(1)) { // bitstream_restriction_flag gb.BitRead(1); // motion_vectors_over_pic_boundaries_flag gb.UExpGolombRead(); // max_bytes_per_pic_denom gb.UExpGolombRead(); // max_bits_per_mb_denom gb.UExpGolombRead(); // log2_max_mv_length_horizontal gb.UExpGolombRead(); // log2_max_mv_length_vertical UINT64 num_reorder_frames = gb.UExpGolombRead(); // num_reorder_frames gb.UExpGolombRead(); // max_dec_frame_buffering if (gb.GetSize() < gb.GetPos()) { num_reorder_frames = 0; } if (num_reorder_frames > 16U) { return false; } } } if (index == index_subsetsps) { if (h.profile == 83 || h.profile == 86) { // TODO: SVC extensions return false; } else if (h.profile == 118 || h.profile == 128) { gb.BitRead(1); // bit_equal_to_one // seq_parameter_set_mvc_extension h.views = (unsigned int) gb.UExpGolombRead() + 1; /* for (unsigned int i = 0; i < h.views; i++) { gb.UExpGolombRead(); // view_id } for (unsigned int i = 1; i < h.views; i++) { for (int j = 0; j < gb.UExpGolombRead(); j++) { // num_anchor_refs_l0 gb.UExpGolombRead(); // anchor_refs_l0 } for (int j = 0; j < gb.UExpGolombRead(); j++) { // num_anchor_refs_l1 gb.UExpGolombRead(); // anchor_refs_l1 } } for (unsigned int i = 1; i < h.views; i++) { for (int j = 0; j < gb.UExpGolombRead(); j++) { // num_non_anchor_refs_l0 gb.UExpGolombRead(); // non_anchor_refs_l0 } for (int j = 0; j < gb.UExpGolombRead(); j++) { // num_non_anchor_refs_l1 gb.UExpGolombRead(); // non_anchor_refs_l1 } } for (unsigned int i = 0; i <= gb.UExpGolombRead(); i++) { // num_level_values_signalled_minus1 gb.BitRead(8); // level_idc for (int j = 0; j <= gb.UExpGolombRead(); j++) { // num_applicable_ops_minus1 gb.BitRead(3); // applicable_op_temporal_id for (int k = 0; k <= gb.UExpGolombRead(); k++) { // applicable_op_num_target_views_minus1 gb.UExpGolombRead(); // applicable_op_traget_view_id } gb.UExpGolombRead(); // applicable_op_num_views_minus1 } } if (gb.BitRead(1)) { // mvc_vui_parameters_present_flag // mvc_vui_parameters_extension for (unsigned int i = 0; i <= gb.UExpGolombRead(); i++) { // vui_mvc_num_ops_minus1 gb.BitRead(3); for (unsigned int j = 0; j <= gb.UExpGolombRead(); j++) { // vui_mvc_num_target_output_views_minus1 gb.UExpGolombRead(); // vui_mvc_view_id } if (gb.BitRead(1)) { // vui_mvc_timing_info_present_flag gb.BitRead(32); // vui_mvc_num_units_in_tick gb.BitRead(32); // vui_mvc_time_scale gb.BitRead(1); // vui_mvc_fixed_frame_rate_flag } bool nalflag = gb.BitRead(1); // vui_mvc_nal_hrd_parameters_present_flag if (nalflag) { HrdParameters(gb); } bool vclflag = gb.BitRead(1); // vui_mvc_vcl_hrd_parameters_present_flag if (vclflag) { HrdParameters(gb); } if (nalflag || vclflag) { gb.BitRead(1); // vui_mvc_low_delay_hrd_flag } gb.BitRead(1); // vui_mvc_pic_struct_present_flag } } */ } } unsigned int mb_Width = (unsigned int)pic_width_in_mbs_minus1 + 1; unsigned int mb_Height = ((unsigned int)pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag); BYTE CHROMA444 = (chroma_format_idc == 3); h.width = 16 * mb_Width - (2u >> CHROMA444) * min(h.crop_right, (8u << CHROMA444) - 1); if (frame_mbs_only_flag) { h.height = 16 * mb_Height - (2u >> CHROMA444) * min(h.crop_bottom, (8u << CHROMA444) - 1); } else { h.height = 16 * mb_Height - (4u >> CHROMA444) * min(h.crop_bottom, (8u << CHROMA444) - 1); } if (h.height < 100 || h.width < 100) { return false; } if (h.height == 1088) { h.height = 1080; // Prevent blur lines } return true; } bool CBaseSplitterFileEx::Read(vc1hdr& h, int len, CMediaType* pmt, int guid_flag) { memset(&h, 0, sizeof(h)); __int64 endpos = GetPos() + len; // - sequence header length __int64 extrapos = 0, extralen = 0; int nFrameRateNum = 0, nFrameRateDen = 1; if (GetPos() < endpos + 4 && BitRead(32, true) == 0x0000010F) { extrapos = GetPos(); BitRead(32); h.profile = (BYTE)BitRead(2); // Check if advanced profile if (h.profile != 3) { return false; } h.level = (BYTE)BitRead(3); h.chromaformat = (BYTE)BitRead(2); // (fps-2)/4 (->30) h.frmrtq_postproc = (BYTE)BitRead(3); //common // (bitrate-32kbps)/64kbps h.bitrtq_postproc = (BYTE)BitRead(5); //common h.postprocflag = (BYTE)BitRead(1); //common h.width = ((unsigned int)BitRead(12) + 1) << 1; h.height = ((unsigned int)BitRead(12) + 1) << 1; h.broadcast = (BYTE)BitRead(1); h.interlace = (BYTE)BitRead(1); h.tfcntrflag = (BYTE)BitRead(1); h.finterpflag = (BYTE)BitRead(1); BitRead(1); // reserved h.psf = (BYTE)BitRead(1); if (BitRead(1)) { int ar = 0; BitRead(14); BitRead(14); if (BitRead(1)) { ar = (int)BitRead(4); } if (ar && ar < 14) { h.sar.num = pixel_aspect[ar][0]; h.sar.den = pixel_aspect[ar][1]; } else if (ar == 15) { h.sar.num = (BYTE)BitRead(8); h.sar.den = (BYTE)BitRead(8); } // Read framerate const int ff_vc1_fps_nr[5] = { 24, 25, 30, 50, 60 }; const int ff_vc1_fps_dr[2] = { 1000, 1001 }; if (BitRead(1)) { if (BitRead(1)) { nFrameRateNum = 32; nFrameRateDen = (int)BitRead(16) + 1; } else { int nr, dr; nr = (int)BitRead(8); dr = (int)BitRead(4); if (nr && nr < 8 && dr && dr < 3) { nFrameRateNum = ff_vc1_fps_dr[dr - 1]; nFrameRateDen = ff_vc1_fps_nr[nr - 1] * 1000; } } } } Seek(extrapos + 4); extralen = 0; int parse = 0; // really need a signed type? may be unsigned will be better while (GetPos() < endpos + 4 && ((parse == 0x0000010E) || (parse & 0xFFFFFF00) != 0x00000100)) { parse = (parse << 8) | (int)BitRead(8); extralen++; } } if (!extrapos || !extralen) { return false; } if (!pmt) { return true; } { pmt->majortype = MEDIATYPE_Video; switch (guid_flag) { case 1: pmt->subtype = FOURCCMap('1CVW'); break; case 2: pmt->subtype = MEDIASUBTYPE_WVC1_CYBERLINK; break; case 3: pmt->subtype = MEDIASUBTYPE_WVC1_ARCSOFT; break; } pmt->formattype = FORMAT_VIDEOINFO2; int vi_len = sizeof(VIDEOINFOHEADER2) + (int)extralen + 1; VIDEOINFOHEADER2* vi = (VIDEOINFOHEADER2*)DEBUG_NEW BYTE[vi_len]; memset(vi, 0, vi_len); vi->AvgTimePerFrame = (10000000I64 * nFrameRateNum) / nFrameRateDen; if (!h.sar.num) { h.sar.num = 1; } if (!h.sar.den) { h.sar.den = 1; } CSize aspect = CSize(h.width * h.sar.num, h.height * h.sar.den); if (h.width == h.sar.num && h.height == h.sar.den) { aspect = CSize(h.width, h.height); } int gcd = GCD(aspect.cx, aspect.cy); if (gcd > 1) { aspect.cx /= gcd; aspect.cy /= gcd; } vi->dwPictAspectRatioX = aspect.cx; vi->dwPictAspectRatioY = aspect.cy; vi->bmiHeader.biSize = sizeof(vi->bmiHeader); vi->bmiHeader.biWidth = h.width; vi->bmiHeader.biHeight = h.height; vi->bmiHeader.biCompression = '1CVW'; BYTE* p = (BYTE*)vi + sizeof(VIDEOINFOHEADER2); *p++ = 0; Seek(extrapos); ByteRead(p, extralen); pmt->SetFormat((BYTE*)vi, vi_len); delete [] vi; } return true; } bool CBaseSplitterFileEx::Read(dvbsub& h, int len, CMediaType* pmt) { memset(&h, 0, sizeof(h)); if ((BitRead(32, true) & 0xFFFFFF00) == 0x20000f00) { static const SUBTITLEINFO SubFormat = { 0, "", L"" }; pmt->majortype = MEDIATYPE_Subtitle; pmt->subtype = MEDIASUBTYPE_DVB_SUBTITLES; pmt->formattype = FORMAT_None; pmt->SetFormat((BYTE*)&SubFormat, sizeof(SUBTITLEINFO)); return true; } return false; } /* To see working buffer in debugger, look : - m_pCache.m_p for the cached buffer - m_pos for current read position */