void CNutFile::Read(vint& vi) { vi = 0; bool more; do {more = !!BitRead(1); vi = (vi << 7) | BitRead(7);} while(more); }
bool CDSMSplitterFile::Read(__int64 len, BYTE& id, CMediaType& mt) { id = (BYTE)BitRead(8); ByteRead((BYTE*)&mt.majortype, sizeof(mt.majortype)); ByteRead((BYTE*)&mt.subtype, sizeof(mt.subtype)); mt.bFixedSizeSamples = (BOOL)BitRead(1); mt.bTemporalCompression = (BOOL)BitRead(1); mt.lSampleSize = (ULONG)BitRead(30); ByteRead((BYTE*)&mt.formattype, sizeof(mt.formattype)); len -= 5 + sizeof(GUID)*3; ASSERT(len >= 0); if(len > 0) {mt.AllocFormatBuffer((LONG)len); ByteRead(mt.Format(), mt.FormatLength());} else mt.ResetFormatBuffer(); return true; }
bool CDSMSplitterFile::Read(__int64 len, Packet* p, bool fData) { if (!p) { return false; } p->TrackNumber = (DWORD)BitRead(8); p->bSyncPoint = (BOOL)BitRead(1); bool fSign = !!BitRead(1); int iTimeStamp = (int)BitRead(3); int iDuration = (int)BitRead(3); if (fSign && !iTimeStamp) { ASSERT(!iDuration); p->rtStart = Packet::INVALID_TIME; p->rtStop = Packet::INVALID_TIME + 1; } else { p->rtStart = (REFERENCE_TIME)BitRead(iTimeStamp<<3) * (fSign ? -1 : 1); p->rtStop = p->rtStart + BitRead(iDuration<<3); } if (fData) { p->SetCount((INT_PTR)len - (2 + iTimeStamp + iDuration)); ByteRead(p->GetData(), p->GetCount()); } return true; }
__int64 CDSMSplitterFile::Read(__int64 len, CStringW& str) { char c; CStringA s; __int64 i = 0; while(i++ < len && (c = (char)BitRead(8)) != 0) s += c; str = UTF8To16(s); return i; }
bool CDSMSplitterFile::Sync(UINT64& syncpos, dsmp_t& type, UINT64& len, __int64 limit) { BitByteAlign(); limit += DSMSW_SIZE; for (UINT64 id = 0; (id&((1ui64<<(DSMSW_SIZE<<3))-1)) != DSMSW; id = (id << 8) | (BYTE)BitRead(8)) { if (limit-- <= 0 || GetRemaining() <= 2) { return false; } } syncpos = GetPos() - (DSMSW_SIZE<<3); type = (dsmp_t)BitRead(5); len = BitRead(((int)BitRead(3)+1)<<3); return true; }
unsigned CByteParser::UExpGolombRead() { int n = -1; for(BYTE b = 0; !b && RemainingBits(); n++) { b = get_bits1(m_gbCtx); } if (!RemainingBits()) return 0; return ((1 << n) | BitRead(n)) - 1; }
bool CDSMSplitterFile::Read(__int64 len, IDSMResourceBagImpl& res) { BYTE compression = (BYTE)BitRead(2); BYTE reserved = (BYTE)BitRead(6); len--; CDSMResource r; len -= Read(len, r.name); len -= Read(len, r.desc); len -= Read(len, r.mime); if(compression != 0) return false; // TODO r.data.SetCount(len); ByteRead(r.data.GetData(), r.data.GetCount()); res += r; return true; }
bool CDSMSplitterFile::Read(__int64 len, IDSMChapterBagImpl& chap) { CDSMChapter c(0, L""); while (len > 0) { bool fSign = !!BitRead(1); int iTimeStamp = (int)BitRead(3); BitRead(4); // reserved len--; c.rt += (REFERENCE_TIME)BitRead(iTimeStamp<<3) * (fSign ? -1 : 1); len -= iTimeStamp; len -= Read(len, c.name); chap += c; } chap.ChapSort(); return len == 0; }
unsigned int IntGetFlag(u8 numinter) { #if defined(UBW32_795) || defined(EMPEROR795) || defined(PIC32_PINGUINO_T795) if (numinter > 63) { numinter -= 64; return BitRead(IFS2, numinter); } else if (numinter > 31 && numinter <= 63) #else if (numinter > 31) #endif { numinter -= 32; return BitRead(IFS1, numinter); } else { return BitRead(IFS0, numinter); } }
bool CDSMSplitterFile::Read(__int64 len, CAtlArray<SyncPoint>& sps) { SyncPoint sp = {0, 0}; sps.RemoveAll(); while (len > 0) { bool fSign = !!BitRead(1); int iTimeStamp = (int)BitRead(3); int iFilePos = (int)BitRead(3); BitRead(1); // reserved sp.rt += (REFERENCE_TIME)BitRead(iTimeStamp<<3) * (fSign ? -1 : 1); sp.fp += BitRead(iFilePos<<3); sps.Add(sp); len -= 1 + iTimeStamp + iFilePos; } if (len != 0) { sps.RemoveAll(); return false; } // TODO: sort sps return true; }
bool CExtradataParser::NextMPEGStartCode(BYTE &code) { BitByteAlign(); DWORD dw = (DWORD)-1; do { if(!Remaining()) return false; dw = (dw << 8) | (BYTE)BitRead(8); } while((dw&0xffffff00) != 0x00000100); code = (BYTE)(dw&0xff); return true; }
u8 DS18B20Read(u8 pin, u8 num, u8 resolution, TEMPERATURE * t) { u8 res, busy = 0; u8 temp_lsb, temp_msb; switch (resolution) { case RES12BIT: res = Bin(01100000); break; // 12-bit resolution case RES11BIT: res = Bin(01000000); break; // 11-bit resolution case RES10BIT: res = Bin(00100000); break; // 10-bit resolution case RES9BIT: res = Bin(00000000); break; // 9-bit resolution default: res = Bin(00000000); break; // 9-bit resolution /// NB: The power-up default of these bits is R0 = 1 and R1 = 1 (12-bit resolution) } DS18B20Configure(pin, num, 0, 0, res); // no alarm if (OneWireReset(pin)) return FALSE; if (num == SKIPROM) { // Skip ROM, address all devices OneWireWrite(pin, SKIPROM); } else { // Talk to a particular device DS18B20MatchRom(pin, num); } OneWireWrite(pin, CONVERT_T); // Start temperature conversion while (busy == 0) // Wait while busy ( = bus is low) busy = OneWireRead(pin); if (OneWireReset(pin)) return FALSE; if (num == SKIPROM) { // Skip ROM, address all devices OneWireWrite(pin, SKIPROM); } else { // Talk to a particular device DS18B20MatchRom(pin, num); } OneWireWrite(pin, READ_SCRATCHPAD);// Read scratchpad temp_lsb = OneWireRead(pin); // byte 0 of scratchpad : temperature lsb temp_msb = OneWireRead(pin); // byte 1 of scratchpad : temperature msb OneWireReset(pin); // Calculation // --------------------------------------------------------------------- // Temperature Register Format // BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 // LS BYTE 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4 // BIT15 BIT14 BIT13 BIT12 BIT11 BIT10 BIT9 BIT8 // MS BYTE S S S S S 2^6 2^5 2^4 // S = SIGN if (temp_msb >= Bin(11111000)) // test if temperature is negative { t->sign = 1; temp_msb -= Bin(11111000); } else { t->sign = 0; } t->integer = temp_lsb >> 4; // fractional part is removed, it remains only integer part t->integer |= (temp_msb << 4); // integer part from temp_msb is added t->fraction = 0; // fractional part ( if (BitRead(temp_lsb, 0)) t->fraction += 625; if (BitRead(temp_lsb, 1)) t->fraction += 1250; if (BitRead(temp_lsb, 2)) t->fraction += 2500; if (BitRead(temp_lsb, 3)) t->fraction += 5000; t->fraction /= 100; // two digits after decimal return TRUE; }
HRESULT CDSMSplitterFile::Init(IDSMResourceBagImpl& res, IDSMChapterBagImpl& chap) { Seek(0); if (BitRead(DSMSW_SIZE<<3) != DSMSW || BitRead(5) != DSMP_FILEINFO) { return E_FAIL; } Seek(0); m_mts.RemoveAll(); m_rtFirst = m_rtDuration = 0; m_fim.RemoveAll(); m_sim.RemoveAll(); res.ResRemoveAll(); chap.ChapRemoveAll(); dsmp_t type; UINT64 len; int limit = 65536; // examine the beginning of the file ... while (Sync(type, len, 0)) { __int64 pos = GetPos(); if (type == DSMP_MEDIATYPE) { BYTE id; CMediaType mt; if (Read(len, id, mt)) { m_mts[id] = mt; } } else if (type == DSMP_SAMPLE) { Packet p; if (Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME) { m_rtFirst = p.rtStart; break; } } else if (type == DSMP_FILEINFO) { if ((BYTE)BitRead(8) > DSMF_VERSION) { return E_FAIL; } Read(len-1, m_fim); } else if (type == DSMP_STREAMINFO) { Read(len-1, m_sim[(BYTE)BitRead(8)]); } else if (type == DSMP_SYNCPOINTS) { Read(len, m_sps); } else if (type == DSMP_RESOURCE) { Read(len, res); } else if (type == DSMP_CHAPTERS) { Read(len, chap); } Seek(pos + len); } if (type != DSMP_SAMPLE) { return E_FAIL; } // ... and the end if (IsRandomAccess()) for (int i = 1, j = (int)((GetLength()+limit/2)/limit); i <= j; i++) { __int64 seekpos = max(0, (__int64)GetLength()-i*limit); Seek(seekpos); while (Sync(type, len, limit) && GetPos() < seekpos+limit) { __int64 pos = GetPos(); if (type == DSMP_SAMPLE) { Packet p; if (Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME) { m_rtDuration = max(m_rtDuration, p.rtStop - m_rtFirst); // max isn't really needed, only for safety i = j; } } else if (type == DSMP_SYNCPOINTS) { Read(len, m_sps); } else if (type == DSMP_RESOURCE) { Read(len, res); } else if (type == DSMP_CHAPTERS) { Read(len, chap); } Seek(pos + len); } } if (m_rtFirst < 0) { m_rtDuration += m_rtFirst; m_rtFirst = 0; } return m_mts.GetCount() > 0 ? S_OK : E_FAIL; }
DWORD CMpegSplitterFile::AddStream(WORD pid, BYTE pesid, BYTE ps1id, DWORD len) { if (pid) { if (pesid) { m_pid2pes[pid] = pesid; } else { m_pid2pes.Lookup(pid, pesid); } } stream s; s.pid = pid; s.pesid = pesid; s.ps1id = ps1id; const __int64 start = GetPos(); int type = unknown; if (pesid >= 0xe0 && pesid < 0xf0) { // mpeg video // MPEG2 if (type == unknown) { CMpegSplitterFile::seqhdr h; if (!m_streams[video].Find(s) && Read(h, len, &s.mt)) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsMPEG2Video(stream_type)) { type = video; } } else { type = video; } } } // H.264 if (type == unknown) { Seek(start); // PPS and SPS can be present on differents packets // and can also be split into multiple packets if (!avch.Lookup(pid)) { memset(&avch[pid], 0, sizeof(CMpegSplitterFile::avchdr)); } #if defined(MVC_SUPPORT) if (!m_streams[video].Find(s) && !m_streams[stereo].Find(s) && Read(avch[pid], len, &s.mt)) { if (avch[pid].spspps[index_subsetsps].complete) { type = stereo; } else { type = video; } } #else if (!m_streams[video].Find(s) && Read(avch[pid], len, &s.mt)) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsH264Video(stream_type)) { type = video; } } else { type = video; } } #endif } } else if (pesid >= 0xc0 && pesid < 0xe0) { // mpeg audio // AAC if (type == unknown) { CMpegSplitterFile::aachdr h; if (!m_streams[audio].Find(s) && Read(h, len, &s.mt, m_type)) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsAACAudio(stream_type)) { type = audio; } } else { type = audio; } } } // AAC LATM if (type == unknown) { Seek(start); CMpegSplitterFile::latm_aachdr h; if (!m_streams[audio].Find(s) && Read(h, len, &s.mt)) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsAACLATMAudio(stream_type)) { type = audio; } } else { type = audio; } } } // MPEG Audio if (type == unknown) { Seek(start); CMpegSplitterFile::mpahdr h; if (!m_streams[audio].Find(s) && Read(h, len, false, &s.mt)) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsMpegAudio(stream_type)) { type = audio; } } else { type = audio; } } } } else if (pesid == 0xbd || pesid == 0xfd) { // private stream 1 if (s.pid) { if (!m_streams[audio].Find(s) && !m_streams[video].Find(s)) { // AC3, E-AC3, TrueHD if (type == unknown) { CMpegSplitterFile::ac3hdr h; if (Read(h, len, &s.mt, true, (m_AC3CoreOnly == 1))) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsAC3Audio(stream_type)) { type = audio; } } else { type = audio; } } } // DTS, DTS HD, DTS HD MA if (type == unknown) { Seek(start); CMpegSplitterFile::dtshdr h; if (Read(h, len, &s.mt, false)) { type = audio; } } // VC1 if (type == unknown) { Seek(start); CMpegSplitterFile::vc1hdr h; if (!m_streams[video].Find(s) && Read(h, len, &s.mt, m_nVC1_GuidFlag)) { PES_STREAM_TYPE stream_type = INVALID; if (GetStreamType(s.pid, stream_type)) { if (IsVC1Video(stream_type)) { type = video; } } else { type = video; } } } // DVB subtitles if (type == unknown) { Seek(start); CMpegSplitterFile::dvbsub h; if (!m_streams[video].Find(s) && Read(h, len, &s.mt)) { type = subpic; } } int iProgram; const CHdmvClipInfo::Stream* pClipInfo; const program* pProgram = FindProgram(s.pid, iProgram, pClipInfo); if ((type == unknown) && (pProgram != NULL)) { PES_STREAM_TYPE StreamType = INVALID; Seek(start); StreamType = pProgram->streams[iProgram].type; switch (StreamType) { case AUDIO_STREAM_LPCM: { CMpegSplitterFile::hdmvlpcmhdr h; if (!m_streams[audio].Find(s) && Read(h, &s.mt)) { type = audio; } } break; case PRESENTATION_GRAPHICS_STREAM: { CMpegSplitterFile::hdmvsubhdr h; if (!m_streams[subpic].Find(s) && Read(h, &s.mt, pClipInfo ? pClipInfo->m_LanguageCode : NULL)) { m_bIsHdmv = true; type = subpic; } } break; } } } else if ((m_AC3CoreOnly != 1) && m_init) { int iProgram; const CHdmvClipInfo::Stream* pClipInfo; const program* pProgram = FindProgram(s.pid, iProgram, pClipInfo); if ((type == unknown) && (pProgram != NULL) && AUDIO_STREAM_AC3_TRUE_HD == pProgram->streams[iProgram].type) { const stream* source = m_streams[audio].FindStream(s.pid); if (source && source->mt.subtype == MEDIASUBTYPE_DOLBY_AC3) { CMpegSplitterFile::ac3hdr h; if (Read(h, len, &s.mt, false, (m_AC3CoreOnly == 1)) && s.mt.subtype == MEDIASUBTYPE_DOLBY_TRUEHD) { m_streams[audio].Replace((stream&)*source, s, this); } } } } } else if (pesid == 0xfd) { CMpegSplitterFile::vc1hdr h; if (!m_streams[video].Find(s) && Read(h, len, &s.mt, m_nVC1_GuidFlag)) { type = video; } } else { BYTE b = (BYTE)BitRead(8, true); WORD w = (WORD)BitRead(16, true); DWORD dw = (DWORD)BitRead(32, true); if (b >= 0x80 && b < 0x88 || w == 0x0b77) { // ac3 s.ps1id = (b >= 0x80 && b < 0x88) ? (BYTE)(BitRead(32) >> 24) : 0x80; CMpegSplitterFile::ac3hdr h; if (!m_streams[audio].Find(s) && Read(h, len, &s.mt)) { type = audio; } } else if (b >= 0x88 && b < 0x90 || dw == 0x7ffe8001) { // dts s.ps1id = (b >= 0x88 && b < 0x90) ? (BYTE)(BitRead(32) >> 24) : 0x88; CMpegSplitterFile::dtshdr h; if (!m_streams[audio].Find(s) && Read(h, len, &s.mt)) { type = audio; } } else if (b >= 0xa0 && b < 0xa8) { // lpcm
HRESULT CMpegSplitterFile::Init(IAsyncReader* pAsyncReader) { HRESULT hr; // get the type first m_type = mpeg_us; Seek(0); if (m_type == mpeg_us) { if (BitRead(32, true) == 'TFrc') { Seek(0x67c); } int cnt = 0, limit = 4; for (tshdr h; cnt < limit && Read(h); cnt++) { Seek(h.next); } if (cnt >= limit) { m_type = mpeg_ts; } } Seek(0); if (m_type == mpeg_us) { if (BitRead(32, true) == 'TFrc') { Seek(0xE80); } int cnt = 0, limit = 4; for (tshdr h; cnt < limit && Read(h); cnt++) { Seek(h.next); } if (cnt >= limit) { m_type = mpeg_ts; } } Seek(0); if (m_type == mpeg_us) { int cnt = 0, limit = 4; for (pvahdr h; cnt < limit && Read(h); cnt++) { Seek(GetPos() + h.length); } if (cnt >= limit) { m_type = mpeg_pva; } } Seek(0); if (m_type == mpeg_us) { BYTE b; for (int i = 0; (i < 4 || GetPos() < MAX_PROBE_SIZE) && m_type == mpeg_us && NextMpegStartCode(b); i++) { if (b == 0xba) { pshdr h; if (Read(h)) { m_type = mpeg_ps; m_rate = int(h.bitrate / 8); break; } } else if ((b & 0xe0) == 0xc0 // audio, 110xxxxx, mpeg1/2/3 || (b & 0xf0) == 0xe0 // video, 1110xxxx, mpeg1/2 // || (b&0xbd) == 0xbd) // private stream 1, 0xbd, ac3/dts/lpcm/subpic || b == 0xbd) { // private stream 1, 0xbd, ac3/dts/lpcm/subpic peshdr h; if (Read(h, b) && BitRead(24, true) == 0x000001) { m_type = mpeg_es; } } } } Seek(0); if (m_type == mpeg_us) { return E_FAIL; } // min/max pts & bitrate m_rtMin = m_posMin = _I64_MAX; m_rtMax = m_posMax = 0; m_rtPrec = _I64_MIN; m_bPTSWrap = false; m_init = true; if (IsRandomAccess() || IsStreaming()) { if (IsStreaming()) { for (int i = 0; i < 20 || i < 50 && S_OK != HasMoreData(MEGABYTE, 100); i++) { ; } } SearchPrograms(0, min(GetLength(), MEGABYTE * 5)); // max 5Mb for search a valid Program Map Table __int64 pfp = 0; const int k = 5; for (int i = 0; i <= k; i++) { __int64 fp = i * GetLength() / k; fp = min(GetLength() - MEGABYTE / 8, fp); fp = max(pfp, fp); __int64 nfp = fp + (pfp == 0 ? 10 * MEGABYTE : MEGABYTE / 8); if (FAILED(hr = SearchStreams(fp, nfp, pAsyncReader))) { return hr; } pfp = nfp; } } else { if (FAILED(hr = SearchStreams(0, MEGABYTE / 8, pAsyncReader))) { return hr; } } if (m_type == mpeg_ts) { if (IsRandomAccess() || IsStreaming()) { if (IsStreaming()) { for (int i = 0; i < 20 || i < 50 && S_OK != HasMoreData(1024 * 100, 100); i++) { ; } } __int64 pfp = 0; const int k = 5; for (int i = 0; i <= k; i++) { __int64 fp = i * GetLength() / k; fp = min(GetLength() - MEGABYTE / 8, fp); fp = max(pfp, fp); __int64 nfp = fp + (pfp == 0 ? 10 * MEGABYTE : MEGABYTE / 8); if (FAILED(hr = SearchStreams(fp, nfp, pAsyncReader, TRUE))) { return hr; } pfp = nfp; } } else { if (FAILED(hr = SearchStreams(0, MEGABYTE / 8, pAsyncReader, TRUE))) { return hr; } } } if (m_posMax - m_posMin <= 0 || (m_rtMax - m_rtMin <= 0 && !m_bPTSWrap)) { return E_FAIL; } m_init = false; int indicated_rate = m_rate; REFERENCE_TIME dur = !m_bPTSWrap ? (m_rtMax - m_rtMin) : (PTS_MAX_BEFORE_WRAP - m_rtMin + m_rtMax); int detected_rate = int(10000000i64 * (m_posMax - m_posMin) / dur); m_rate = detected_rate ? detected_rate : m_rate; #if (0) // normally "detected" should always be less than "indicated", but sometimes it can be a few percent higher (+10% is allowed here) // (update: also allowing +/-50k/s) if (indicated_rate == 0 || ((float)detected_rate / indicated_rate) < 1.1 || abs(detected_rate - indicated_rate) < 50 * 1024) { m_rate = detected_rate; } else { ; // TODO: in this case disable seeking, or try doing something less drastical... } #endif // Add fake subtitle stream... if (m_streams[video].GetCount() && m_streams[subpic].GetCount()) { if (m_type == mpeg_ts && m_bIsHdmv) { AddHdmvPGStream(NO_SUBTITLE_PID, "---"); } else { stream s; s.pid = NO_SUBTITLE_PID; s.mt.majortype = m_streams[subpic].GetHead().mt.majortype; s.mt.subtype = m_streams[subpic].GetHead().mt.subtype; s.mt.formattype = m_streams[subpic].GetHead().mt.formattype; m_streams[subpic].Insert(s, this); } } Seek(0); return S_OK; }
HRESULT CMpegSplitterFile::Init() { HRESULT hr; SVP_LogMsg5(L"HRESULT CMpegSplitterFile::Init()"); // get the type first m_type = us; Seek(0); if(m_type == us) { if(BitRead(32, true) == 'TFrc') Seek(0x67c); int cnt = 0, limit = 4; for(trhdr h; cnt < limit && Read(h); cnt++) Seek(h.next); if(cnt >= limit) m_type = ts; } Seek(0); if(m_type == us) { int cnt = 0, limit = 4; for(pvahdr h; cnt < limit && Read(h); cnt++) Seek(GetPos() + h.length); if(cnt >= limit) m_type = pva; } Seek(0); if(m_type == us) { BYTE b; for(int i = 0; (i < 4 || GetPos() < 65536) && m_type == us && NextMpegStartCode(b); i++) { if(b == 0xba) { pshdr h; if(Read(h)) { m_type = ps; m_rate = int(h.bitrate/8); break; } } else if((b&0xe0) == 0xc0 // audio, 110xxxxx, mpeg1/2/3 || (b&0xf0) == 0xe0 // video, 1110xxxx, mpeg1/2 // || (b&0xbd) == 0xbd) // private stream 1, 0xbd, ac3/dts/lpcm/subpic || b == 0xbd) // private stream 1, 0xbd, ac3/dts/lpcm/subpic { peshdr h; if(Read(h, b) && BitRead(24, true) == 0x000001) { m_type = es; } } } } Seek(0); if(m_type == us) { return E_FAIL; } // min/max pts & bitrate m_rtMin = m_posMin = _I64_MAX; m_rtMax = m_posMax = 0; if(IsRandomAccess() || IsStreaming()) { if(IsStreaming()) { for(int i = 0; i < 20 || i < 50 && S_OK != HasMoreData(1024*100, 100); i++); } CAtlList<__int64> fps; for(int i = 0, j = 5; i <= j; i++) fps.AddTail(i*GetLength()/j); for(__int64 pfp = 0; fps.GetCount(); ) { __int64 fp = fps.RemoveHead(); fp = min(GetLength() - MEGABYTE/8, fp); fp = max(pfp, fp); __int64 nfp = fp + (pfp == 0 ? 5*MEGABYTE : MEGABYTE/8); if(FAILED(hr = SearchStreams(fp, nfp))) return hr; pfp = nfp; } } else { if(FAILED(hr = SearchStreams(0, MEGABYTE/8))) return hr; } if(m_posMax - m_posMin <= 0 || m_rtMax - m_rtMin <= 0) return E_FAIL; int indicated_rate = m_rate; int detected_rate = int(10000000i64 * (m_posMax - m_posMin) / (m_rtMax - m_rtMin)); // normally "detected" should always be less than "indicated", but sometimes it can be a few percent higher (+10% is allowed here) // (update: also allowing +/-50k/s) if(indicated_rate == 0 || ((float)detected_rate / indicated_rate) < 1.1 || abs(detected_rate - indicated_rate) < 50*1024) m_rate = detected_rate; else ; // TODO: in this case disable seeking, or try doing something less drastical... //#ifndef DEBUG if(m_streams[audio].GetCount() < 1 && m_type == ts){ SVP_LogMsg5(_T("ts and no audio %d %d"), m_streams[audio].GetCount(), m_streams[unknown].GetCount()); return E_FAIL; } if(m_streams[video].GetCount()) { if (!m_bIsHdmv && m_streams[subpic].GetCount()) { stream s; s.mt.majortype = MEDIATYPE_Video; s.mt.subtype = MEDIASUBTYPE_DVD_SUBPICTURE; s.mt.formattype = FORMAT_None; m_streams[subpic].Insert(s, this); } else { // Add fake stream for "No subtitle" AddHdmvPGStream (NO_SUBTITLE_PID, "---"); } }else if(m_type == ts){ SVP_LogMsg5(_T("ts and no video")); return E_FAIL; } //#endif Seek(0); SVP_LogMsg5(_T("ts %d %d %d"), m_streams[video].GetCount() , m_streams[audio].GetCount(), m_bIsHdmv); return S_OK; }
HRESULT CNutFile::Init() { Seek(0); if(BitRead(64) != NUTM) return E_FAIL; m_streams.RemoveAll(); Seek(0); while(GetRemaining()) { frame_header fh; fh.checksum_flag = 1; UINT64 id = 0; if(BitRead(1, true) == 0 || (id = BitRead(64)) == NUTK) break; packet_header ph; Read(ph); if(id == NUTM) { Read(m_mh); } else if(id == NUTS) { CAutoPtr<stream_header> sh(new stream_header()); Read(*sh); if(sh->stream_class == SC_VIDEO) Read(sh->vsh); else if(sh->stream_class == SC_AUDIO) Read(sh->ash); // else if(sh->stream_class == SC_SUBTITLE) ; // nothing to do m_streams.AddTail(sh); } else if(id == NUTX) { index_header ih; Read(ih); } else if(id == NUTI) { info_header ih; Read(ih); } else if(id == 0) // frame { ASSERT(0); break; } if(fh.checksum_flag) { Seek(ph.pos + ph.fptr - 4); ph.checksum = (UINT32)BitRead(32); } Seek(ph.pos + ph.fptr); } Seek(0); return m_streams.GetCount() ? S_OK : E_FAIL; }
size_t CExtradataParser::ParseMPEGSequenceHeader(BYTE *pTarget) { BYTE id = 0; while(Remaining() && id != 0xb3) { if(!NextMPEGStartCode(id)) { return 0; } } if(id != 0xb3) { return 0; } size_t shpos = Pos() - 4; BitRead(12); // Width BitRead(12); // Height BitRead(4); // AR BitRead(4); // FPS BitRead(18); // Bitrate MARKER; BitRead(10); // VBV BitRead(1); // Constrained Flag // intra quantisizer matrix if(BitRead(1)) { for (uint8_t i = 0; i < 64; i++) { BitRead(8); } } // non-intra quantisizer matrix if(BitRead(1)) { for (uint8_t i = 0; i < 64; i++) { BitRead(8); } } size_t shlen = Pos() - shpos; size_t shextpos = 0; size_t shextlen = 0; if(NextMPEGStartCode(id) && id == 0xb5) { // sequence header ext shextpos = Pos() - 4; int startcode = BitRead(4); // Start Code Id; TODO: DIfferent start code ids mean different length of da2a ASSERT(startcode == 1); BitRead(1); // Profile Level Escape BitRead(3); // Profile BitRead(4); // Level BitRead(1); // Progressive BitRead(2); // Chroma BitRead(2); // Width Extension BitRead(2); // Height Extension BitRead(12); // Bitrate Extension MARKER; BitRead(8); // VBV Buffer Size Extension BitRead(1); // Low Delay BitRead(2); // FPS Extension n BitRead(5); // FPS Extension d shextlen = Pos() - shextpos; } memcpy(pTarget, Start()+shpos, shlen); if (shextpos) { memcpy(pTarget+shlen, Start()+shextpos, shextlen); } return shlen + shextlen; }