Example #1
0
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;
}
Example #2
0
HRESULT CMpegSplitterFile::SearchStreams(__int64 start, __int64 stop)
{
	Seek(start);
	stop = min(stop, GetLength());

	while(GetPos() < stop)
	{
		BYTE b;

		if(m_type == ps || m_type == es)
		{
			if(!NextMpegStartCode(b)) continue;

			if(b == 0xba) // program stream header
			{
				pshdr h;
				if(!Read(h)) continue;
			}
			else if(b == 0xbb) // program stream system header
			{
				pssyshdr h;
				if(!Read(h)) continue;
			}
#if (EVO_SUPPORT == 0)
			else if(b >= 0xbd && b < 0xf0) // pes packet
#else
			else if((b >= 0xbd && b < 0xf0) || (b == 0xfd)) // pes packet
#endif
			{
				peshdr h;
				if(!Read(h, b)) continue;

				if(h.type == mpeg2 && h.scrambling) {ASSERT(0); return E_FAIL;}

				if(h.fpts)
				{
					if(m_rtMin == _I64_MAX) {m_rtMin = h.pts; m_posMin = GetPos();}
					if(m_rtMin < h.pts && m_rtMax < h.pts) {m_rtMax = h.pts; m_posMax = GetPos();}
/*
int rate = 10000000i64 * (m_posMax - m_posMin) / (m_rtMax - m_rtMin); 
if(m_rate == 0) m_rate = rate;
TRACE(_T("rate = %d (%d), (h.pts = %I64d)\n"), rate, rate - m_rate, h.pts);
m_rate = rate;
*/
				}

				__int64 pos = GetPos();
				AddStream(0, b, h.len);
				if(h.len) Seek(pos + h.len);
			}
		}
		else if(m_type == ts)
		{
			trhdr h;
			if(!Read(h)) continue;

			// if(h.scrambling) {ASSERT(0); return E_FAIL;}

			__int64 pos = GetPos();

			if(h.payload && h.payloadstart)
			{
				UpdatePrograms(h);
			}
				
			if(h.payload && ISVALIDPID(h.pid))
			{
				peshdr h2;
				if(h.payloadstart && NextMpegStartCode(b, 4) && Read(h2, b)) // pes packet
				{
					if(h2.type == mpeg2 && h2.scrambling) {
						ASSERT(0); 
						return E_FAIL;
					}

					if(h2.fpts)
					{
						if(m_rtMin == _I64_MAX) {m_rtMin = h2.pts; m_posMin = GetPos();}
						if(m_rtMin < h2.pts && m_rtMax < h2.pts) {m_rtMax = h2.pts; m_posMax = GetPos();}
					}
				}
				else
				{
					b = 0;
				}

				AddStream(h.pid, b, DWORD(h.bytes - (GetPos() - pos)));
			}

			Seek(h.next);
		}
		else if(m_type == pva)
		{
			pvahdr h;
			if(!Read(h)) continue;

			if(h.fpts)
			{
				if(m_rtMin == _I64_MAX) {m_rtMin = h.pts; m_posMin = GetPos();}
				if(m_rtMin < h.pts && m_rtMax < h.pts) {m_rtMax = h.pts; m_posMax = GetPos();}
			}

			__int64 pos = GetPos();
			if(h.streamid == 1) AddStream(h.streamid, 0xe0, h.length);
			else if(h.streamid == 2) AddStream(h.streamid, 0xc0, h.length);
			if(h.length) Seek(pos + h.length);
		}
	}
Example #3
0
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;
}
Example #4
0
REFERENCE_TIME CMpegSplitterFile::NextPTS(DWORD TrackNum)
{
	REFERENCE_TIME rt = -1;
	__int64 rtpos = -1;

	BYTE b;

	while(GetRemaining())
	{
		if(m_type == ps || m_type == es)
		{
			if(!NextMpegStartCode(b)) // continue;
				{ASSERT(0); break;}

			rtpos = GetPos()-4;

#if (EVO_SUPPORT == 0)
			if(b >= 0xbd && b < 0xf0)
#else
			if((b >= 0xbd && b < 0xf0) || (b == 0xfd))
#endif
			{
				peshdr h;
				if(!Read(h, b) || !h.len) continue;

				__int64 pos = GetPos();

				if(h.fpts && AddStream(0, b, h.len) == TrackNum)
				{
					ASSERT(h.pts >= m_rtMin && h.pts <= m_rtMax);
					rt = h.pts;
					break;
				}

				Seek(pos + h.len);
			}
		}
		else if(m_type == ts)
		{
			trhdr h;
			if(!Read(h)) continue;

			rtpos = GetPos()-4;

			if(h.payload && h.payloadstart && ISVALIDPID(h.pid))
			{
				peshdr h2;
				if(NextMpegStartCode(b, 4) && Read(h2, b)) // pes packet
				{
					if(h2.fpts && AddStream(h.pid, b, DWORD(h.bytes - (GetPos() - rtpos)) == TrackNum))
					{
						ASSERT(h2.pts >= m_rtMin && h2.pts <= m_rtMax);
						rt = h2.pts;
						break;
					}
				}
			}

			Seek(h.next);
		}
		else if(m_type == pva)
		{
			pvahdr h;
			if(!Read(h)) continue;

			if(h.fpts)
			{
				rt = h.pts;
				break;
			}
		}
	}

	if(rtpos >= 0) Seek(rtpos);
	if(rt >= 0) rt -= m_rtMin;

	return rt;
}
Example #5
0
HRESULT CMpegSplitterFile::SearchStreams(__int64 start, __int64 stop, IAsyncReader* pAsyncReader, BOOL CalcDuration)
{
    Seek(start);
    stop = min(stop, GetLength());

    while (GetPos() < stop) {
        BYTE b;

        if (m_type == mpeg_ps || m_type == mpeg_es) {
            if (!NextMpegStartCode(b)) {
                continue;
            }

            if (b == 0xba) { // program stream header
                pshdr h;
                if (!Read(h)) {
                    continue;
                }
                m_rate = int(h.bitrate / 8);
            } else if (b == 0xbb) { // program stream system header
                pssyshdr h;
                if (!Read(h)) {
                    continue;
                }
            } else if ((b >= 0xbd && b < 0xf0) || (b == 0xfd)) { // pes packet
                peshdr h;
                if (!Read(h, b) || !h.len) {
                    continue;
                }

                if (h.type == mpeg2 && h.scrambling) {
                    ASSERT(0);
                    return E_FAIL;
                }

                if (h.fpts) {
                    if (m_rtMin == _I64_MAX) {
                        m_rtMin = h.pts;
                        m_posMin = GetPos();
                        TRACE(_T("m_rtMin(SearchStreams)=%s\n"), ReftimeToString(m_rtMin));
                    }
                    if (m_rtMin < h.pts && m_rtMax < h.pts) {
                        m_rtMax = h.pts;
                        m_posMax = GetPos();
                        TRACE(_T("m_rtMax(SearchStreams)=%s\n"), ReftimeToString(m_rtMax));
                    }
                }

                __int64 pos = GetPos();
                AddStream(0, b, h.id_ext, h.len);
                if (h.len) {
                    Seek(pos + h.len);
                }
            }
        } else if (m_type == mpeg_ts) {
            tshdr h;
            if (!Read(h)) {
                continue;
            }

            __int64 pos = GetPos();

            //UpdatePrograms(h);

            if (h.payload && ISVALIDPID(h.pid)) {
                peshdr h2;
                if (h.payloadstart && NextMpegStartCode(b, 4) && Read(h2, b)) { // pes packet
                    if (h2.type == mpeg2 && h2.scrambling) {
                        ASSERT(0);
                        return E_FAIL;
                    }

                    if (h2.fpts && CalcDuration && (m_AlternativeDuration || (GetMasterStream() && GetMasterStream()->GetHead() == h.pid))) {
                        if (m_rtPrec != _I64_MIN && abs(h2.pts - m_rtPrec) >= PTS_MAX_BEFORE_WRAP / 2) {
                            m_bPTSWrap = true;
                            m_rtMax = h2.pts;
                            m_posMax = GetPos();
                            TRACE(_T("PTS Wrap detected --> m_rtMax(SearchStreams)=%s\n"), ReftimeToString(m_rtMax));
                        }
                        m_rtPrec = h2.pts;

                        if ((m_rtMin == _I64_MAX) || (m_rtMin > h2.pts && m_rtMax > h2.pts && !m_bPTSWrap)) {
                            m_rtMin = h2.pts;
                            m_posMin = GetPos();
                            TRACE(_T("m_rtMin(SearchStreams)=%s, PID=%d\n"), ReftimeToString(m_rtMin), h.pid);
                        }

                        if (m_rtMax < h2.pts && (m_rtMin < h2.pts || m_bPTSWrap)) {
                            m_rtMax = h2.pts;
                            m_posMax = GetPos();
                            TRACE(_T("m_rtMax(SearchStreams)=%s, PID=%d\n"), ReftimeToString(m_rtMax), h.pid);
                            // Ugly code : to support BRD H264 seamless playback, CMultiFiles need to update m_rtPTSOffset variable
                            // each time a new part is open...
                            // use this code only if Blu-ray is detected
                            if (m_ClipInfo.IsHdmv()) {
                                for (size_t i = 0; i < m_ClipInfo.GetStreamNumber(); i++) {
                                    CHdmvClipInfo::Stream* stream = m_ClipInfo.GetStreamByIndex(i);
                                    if (stream->m_Type == VIDEO_STREAM_H264 && m_rtMin == 116506666) {
                                        CComQIPtr<ISyncReader>  pReader = pAsyncReader;
                                        if (pReader) {
                                            pReader->SetPTSOffset(&m_rtPTSOffset);
                                        }
                                        //TRACE(_T("UPDATE m_rtPTSOffset(SearchStreams)=%s\n"), ReftimeToString(m_rtPTSOffset));
                                        //TRACE(_T("m_rtMin(Boucle)=%s\n"), ReftimeToString(m_rtMin));
                                        //TRACE(_T("stream=%d\n"), stream->m_Type);
                                        //TRACE(_T("m_rtMax(Boucle)=%s\n"), ReftimeToString(m_rtMax));
                                        //TRACE(_T("m_rtMax - m_rtMin(Boucle)=%s\n"), ReftimeToString(m_rtMax - m_rtMin));
                                    }
                                }
                            }
                        }
                    }
                } else {
                    b = 0;
                }

                if (!CalcDuration) {
                    AddStream(h.pid, b, 0, DWORD(h.bytes - (GetPos() - pos)));
                }
            }

            Seek(h.next);
        } else if (m_type == mpeg_pva) {
            pvahdr h;
            if (!Read(h)) {
                continue;
            }

            if (h.fpts) {
                if (m_rtMin == _I64_MAX) {
                    m_rtMin = h.pts;
                    m_posMin = GetPos();
                }

                if (m_rtMin < h.pts && m_rtMax < h.pts) {
                    m_rtMax = h.pts;
                    m_posMax = GetPos();
                }
            }

            __int64 pos = GetPos();

            if (h.streamid == 1) {
                AddStream(h.streamid, 0xe0, 0, h.length);
            } else if (h.streamid == 2) {
                AddStream(h.streamid, 0xc0, 0, h.length);
            }

            if (h.length) {
                Seek(pos + h.length);
            }
        }
    }

    return S_OK;
}