Exemple #1
0
STDMETHODIMP CSubtitleInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
    CAutoLock cAutoLock(&m_csReceive);

    if (m_mt.majortype == MEDIATYPE_Text
            || m_mt.majortype == MEDIATYPE_Subtitle
            && (m_mt.subtype == MEDIASUBTYPE_UTF8
                /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
                || m_mt.subtype == MEDIASUBTYPE_SSA
                || m_mt.subtype == MEDIASUBTYPE_ASS
                || m_mt.subtype == MEDIASUBTYPE_ASS2)) {
        CAutoLock cAutoLock2(m_pSubLock);
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
        pRTS->RemoveAll();
        pRTS->CreateSegments();
    } else if (m_mt.majortype == MEDIATYPE_Subtitle && (m_mt.subtype == MEDIASUBTYPE_VOBSUB)) {
        CAutoLock cAutoLock2(m_pSubLock);
        CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
        pVSS->RemoveAll();
    } else if (IsHdmvSub(&m_mt)) {
        CAutoLock cAutoLock2(m_pSubLock);
        CRenderedHdmvSubtitle* pHdmvSubtitle = (CRenderedHdmvSubtitle*)(ISubStream*)m_pSubStream;
        pHdmvSubtitle->NewSegment(tStart, tStop, dRate);
    }

    return __super::NewSegment(tStart, tStop, dRate);
}
Exemple #2
0
STDMETHODIMP CSubtitleInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
    CAutoLock cAutoLock(&m_csReceive);

    if (m_mt.majortype == MEDIATYPE_Text
            || m_mt.majortype == MEDIATYPE_Subtitle
            && (m_mt.subtype == MEDIASUBTYPE_UTF8
                /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
                || m_mt.subtype == MEDIASUBTYPE_SSA
                || m_mt.subtype == MEDIASUBTYPE_ASS
                || m_mt.subtype == MEDIASUBTYPE_ASS2)) {
        CAutoLock cAutoLock2(m_pSubLock);
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
        pRTS->RemoveAll();
        pRTS->CreateSegments();
    } else if (m_mt.majortype == MEDIATYPE_Subtitle && (m_mt.subtype == MEDIASUBTYPE_VOBSUB)) {
        CAutoLock cAutoLock2(m_pSubLock);
        CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
        pVSS->RemoveAll();
    } else if (IsHdmvSub(&m_mt)) {
        CAutoLock cAutoLock2(m_pSubLock);
        CRenderedHdmvSubtitle* pHdmvSubtitle = (CRenderedHdmvSubtitle*)(ISubStream*)m_pSubStream;
        pHdmvSubtitle->NewSegment(tStart, tStop, dRate);
    }

    TRACE(_T("NewSegment: InvalidateSubtitle(%I64d, ...)\n"), tStart);
    // IMPORTANT: m_pSubLock must not be locked when calling this
    InvalidateSubtitle(tStart, m_pSubStream);

    return __super::NewSegment(tStart, tStop, dRate);
}
Exemple #3
0
void CPlayerSubresyncBar::SaveSubtitle()
{
	CMainFrame* pFrame = ((CMainFrame*)AfxGetMainWnd());
	if (!pFrame) {
		return;
	}

	CLSID clsid;
	m_pSubStream->GetClassID(&clsid);

	if (clsid == __uuidof(CVobSubFile) && m_mode == VOBSUB) {
		CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)m_pSubStream;

		CAutoLock cAutoLock(m_pSubLock);

		ASSERT(pVSF->m_iLang >= 0);
		CAtlArray<CVobSubFile::SubPos>& sp = pVSF->m_langs[pVSF->m_iLang].subpos;

		for (size_t i = 0, j = sp.GetCount(); i < j; i++) {
			sp[i].fValid = false;
		}

		for (int i = 0, j = (int)m_sts.GetCount(); i < j; i++) {
			int vobid, cellid, forced, spnum;
			TCHAR c;
			if (_stscanf_s(m_sts.GetStrW(i), _T("%d%c%d%c%d%c%d"), &vobid,
						   &c, 1, &cellid, &c, 1, &forced, &c, 1, &spnum) != 7) {
				continue;
			}
			sp[spnum].start = m_sts[i].start;
			sp[spnum].stop = m_sts[i].end;
			sp[spnum].fValid = true;
		}
	} else if (clsid == __uuidof(CRenderedTextSubtitle) && m_mode == TEXTSUB) {
		CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

		CAutoLock cAutoLock(m_pSubLock);

		pRTS->Copy(m_sts);
	} else {
		return;
	}

	pFrame->InvalidateSubtitle();
}
STDMETHODIMP CSubtitleInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
    CAutoLock cAutoLock(&m_csReceive);

    if(m_mt.majortype == MEDIATYPE_Text
            || m_mt.majortype == MEDIATYPE_Subtitle
            && (m_mt.subtype == MEDIASUBTYPE_UTF8
                /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
                || m_mt.subtype == MEDIASUBTYPE_SSA
                || m_mt.subtype == MEDIASUBTYPE_ASS
                || m_mt.subtype == MEDIASUBTYPE_ASS2))
    {
        CAutoLock cAutoLock(m_pSubLock);
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
        pRTS->RemoveAll();
        pRTS->CreateSegments();
    }
    else if(m_mt.majortype == MEDIATYPE_Subtitle && m_mt.subtype == MEDIASUBTYPE_SSF)
    {
        CAutoLock cAutoLock(m_pSubLock);
        ssf::CRenderer* pSSF = (ssf::CRenderer*)(ISubStream*)m_pSubStream;
        // LAME, implement RemoveSubtitles
        DWORD dwOffset = ((SUBTITLEINFO*)m_mt.pbFormat)->dwOffset;
        pSSF->Open(ssf::MemoryInputStream(m_mt.pbFormat + dwOffset, m_mt.cbFormat - dwOffset, false, false), _T(""));
        // pSSF->RemoveSubtitles();
    }
    else if(m_mt.majortype == MEDIATYPE_Subtitle && (m_mt.subtype == MEDIASUBTYPE_VOBSUB))
    {
        CAutoLock cAutoLock(m_pSubLock);
        CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
        pVSS->RemoveAll();
    }
    else if (IsHdmvSub(&m_mt))
    {
        CAutoLock cAutoLock(m_pSubLock);
        CRenderedHdmvSubtitle* pHdmvSubtitle = (CRenderedHdmvSubtitle*)(ISubStream*)m_pSubStream;
        pHdmvSubtitle->NewSegment (tStart, tStop, dRate);
    }

    return __super::NewSegment(tStart, tStop, dRate);
}
void CPlayerSubresyncBar::SaveSubtitle()
{
    CMainFrame* pFrame = ((CMainFrame*)AfxGetMainWnd());
    if (!pFrame) {
        return;
    }

    CLSID clsid;
    m_pSubStream->GetClassID(&clsid);

    if (clsid == __uuidof(CVobSubFile) && m_mode == VOBSUB) {
        CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)m_pSubStream;

        CAutoLock cAutoLock(m_pSubLock);

        ASSERT(pVSF->m_iLang >= 0);
        CAtlArray<CVobSubFile::SubPos>& sp = pVSF->m_langs[pVSF->m_iLang].subpos;

        for (size_t i = 0, j = sp.GetCount(); i < j; i++) {
            sp[i].fValid = false;
        }

        for (size_t i = 0, j = m_sts.GetCount(); i < j; i++) {
            int spnum = m_sts[i].readorder;

            sp[spnum].start  = m_sts[i].start;
            sp[spnum].stop   = m_sts[i].end;
            sp[spnum].fValid = true;
        }
    } else if (clsid == __uuidof(CRenderedTextSubtitle) && m_mode == TEXTSUB) {
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

        CAutoLock cAutoLock(m_pSubLock);

        pRTS->Copy(m_sts);
    } else {
        return;
    }

    pFrame->InvalidateSubtitle();
}
HRESULT CSubtitleInputPin::CompleteConnect(IPin* pReceivePin)
{
    if(m_mt.majortype == MEDIATYPE_Text)
    {
        if(!(m_pSubStream = DNew CRenderedTextSubtitle(m_pSubLock))) return E_FAIL;
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
        pRTS->m_name = CString(GetPinName(pReceivePin)) + _T(" (embeded)");
        pRTS->m_dstScreenSize = CSize(384, 288);
        pRTS->CreateDefaultStyle(DEFAULT_CHARSET);
    }
    else if(m_mt.majortype == MEDIATYPE_Subtitle)
    {
        SUBTITLEINFO*	psi		= (SUBTITLEINFO*)m_mt.pbFormat;
        DWORD			dwOffset	= 0;
        CString			name;
        LCID			lcid = 0;

        if (psi != NULL)
        {
            dwOffset = psi->dwOffset;

            name = ISO6392ToLanguage(psi->IsoLang);
            lcid = ISO6392ToLcid(psi->IsoLang);
            if(name.IsEmpty()) name = _T("Unknown");
            if(wcslen(psi->TrackName) > 0) name += _T(" (") + CString(psi->TrackName) + _T(")");
        }

        if(m_mt.subtype == MEDIASUBTYPE_UTF8
                /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
                || m_mt.subtype == MEDIASUBTYPE_SSA
                || m_mt.subtype == MEDIASUBTYPE_ASS
                || m_mt.subtype == MEDIASUBTYPE_ASS2)
        {
            if(!(m_pSubStream = DNew CRenderedTextSubtitle(m_pSubLock))) return E_FAIL;
            CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
            pRTS->m_name = name;
            pRTS->m_lcid = lcid;
            pRTS->m_dstScreenSize = CSize(384, 288);
            pRTS->CreateDefaultStyle(DEFAULT_CHARSET);

            if(dwOffset > 0 && m_mt.cbFormat - dwOffset > 0)
            {
                CMediaType mt = m_mt;
                if(mt.pbFormat[dwOffset+0] != 0xef
                        && mt.pbFormat[dwOffset+1] != 0xbb
                        && mt.pbFormat[dwOffset+2] != 0xfb)
                {
                    dwOffset -= 3;
                    mt.pbFormat[dwOffset+0] = 0xef;
                    mt.pbFormat[dwOffset+1] = 0xbb;
                    mt.pbFormat[dwOffset+2] = 0xbf;
                }

                pRTS->Open(mt.pbFormat + dwOffset, mt.cbFormat - dwOffset, DEFAULT_CHARSET, pRTS->m_name);
            }

        }
        else if(m_mt.subtype == MEDIASUBTYPE_SSF)
        {
            if(!(m_pSubStream = DNew ssf::CRenderer(m_pSubLock))) return E_FAIL;
            ssf::CRenderer* pSSF = (ssf::CRenderer*)(ISubStream*)m_pSubStream;
            pSSF->Open(ssf::MemoryInputStream(m_mt.pbFormat + dwOffset, m_mt.cbFormat - dwOffset, false, false), name);
        }
        else if(m_mt.subtype == MEDIASUBTYPE_VOBSUB)
        {
            if(!(m_pSubStream = DNew CVobSubStream(m_pSubLock))) return E_FAIL;
            CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
            pVSS->Open(name, m_mt.pbFormat + dwOffset, m_mt.cbFormat - dwOffset);
        }
        else if (IsHdmvSub(&m_mt))
        {
            if(!(m_pSubStream = DNew CRenderedHdmvSubtitle(m_pSubLock, (m_mt.subtype == MEDIASUBTYPE_DVB_SUBTITLES) ? ST_DVB : ST_HDMV))) return E_FAIL;
        }
    }

    AddSubStream(m_pSubStream);

    return __super::CompleteConnect(pReceivePin);
}
STDMETHODIMP CSubtitleInputPin::Receive(IMediaSample* pSample)
{
    HRESULT hr;

    hr = __super::Receive(pSample);
    if(FAILED(hr)) return hr;

    CAutoLock cAutoLock(&m_csReceive);

    REFERENCE_TIME tStart, tStop;
    pSample->GetTime(&tStart, &tStop);
    tStart += m_tStart;
    tStop += m_tStart;

    BYTE* pData = NULL;
    hr = pSample->GetPointer(&pData);
    if(FAILED(hr) || pData == NULL) return hr;

    int len = pSample->GetActualDataLength();

    bool fInvalidate = false;

    if(m_mt.majortype == MEDIATYPE_Text)
    {
        CAutoLock cAutoLock(m_pSubLock);
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

        if(!strncmp((char*)pData, __GAB1__, strlen(__GAB1__)))
        {
            char* ptr = (char*)&pData[strlen(__GAB1__)+1];
            char* end = (char*)&pData[len];

            while(ptr < end)
            {
                WORD tag = *((WORD*)(ptr));
                ptr += 2;
                WORD size = *((WORD*)(ptr));
                ptr += 2;

                if(tag == __GAB1_LANGUAGE__)
                {
                    pRTS->m_name = CString(ptr);
                }
                else if(tag == __GAB1_ENTRY__)
                {
                    pRTS->Add(AToW(&ptr[8]), false, *(int*)ptr, *(int*)(ptr+4));
                    fInvalidate = true;
                }
                else if(tag == __GAB1_LANGUAGE_UNICODE__)
                {
                    pRTS->m_name = (WCHAR*)ptr;
                }
                else if(tag == __GAB1_ENTRY_UNICODE__)
                {
                    pRTS->Add((WCHAR*)(ptr+8), true, *(int*)ptr, *(int*)(ptr+4));
                    fInvalidate = true;
                }

                ptr += size;
            }
        }
        else if(!strncmp((char*)pData, __GAB2__, strlen(__GAB2__)))
        {
            char* ptr = (char*)&pData[strlen(__GAB2__)+1];
            char* end = (char*)&pData[len];

            while(ptr < end)
            {
                WORD tag = *((WORD*)(ptr));
                ptr += 2;
                DWORD size = *((DWORD*)(ptr));
                ptr += 4;

                if(tag == __GAB1_LANGUAGE_UNICODE__)
                {
                    pRTS->m_name = (WCHAR*)ptr;
                }
                else if(tag == __GAB1_RAWTEXTSUBTITLE__)
                {
                    pRTS->Open((BYTE*)ptr, size, DEFAULT_CHARSET, pRTS->m_name);
                    fInvalidate = true;
                }

                ptr += size;
            }
        }
        else if(pData != 0 && len > 1 && *pData != 0)
        {
            CStringA str((char*)pData, len);

            str.Replace("\r\n", "\n");
            str.Trim();

            if(!str.IsEmpty())
            {
                pRTS->Add(AToW(str), false, (int)(tStart / 10000), (int)(tStop / 10000));
                fInvalidate = true;
            }
        }
    }
    else if(m_mt.majortype == MEDIATYPE_Subtitle)
    {
        CAutoLock cAutoLock(m_pSubLock);

        if(m_mt.subtype == MEDIASUBTYPE_UTF8)
        {
            CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

            CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
            if(!str.IsEmpty())
            {
                pRTS->Add(str, true, (int)(tStart / 10000), (int)(tStop / 10000));
                fInvalidate = true;
            }
        }
        else if(m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS || m_mt.subtype == MEDIASUBTYPE_ASS2)
        {
            CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

            CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
            if(!str.IsEmpty())
            {
                STSEntry stse;

                int fields = m_mt.subtype == MEDIASUBTYPE_ASS2 ? 10 : 9;

                CAtlList<CStringW> sl;
                Explode(str, sl, ',', fields);
                if(sl.GetCount() == (size_t)fields)
                {
                    stse.readorder = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.layer = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.style = sl.RemoveHead();
                    stse.actor = sl.RemoveHead();
                    stse.marginRect.left = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.marginRect.right = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.marginRect.top = stse.marginRect.bottom = wcstol(sl.RemoveHead(), NULL, 10);
                    if(fields == 10) stse.marginRect.bottom = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.effect = sl.RemoveHead();
                    stse.str = sl.RemoveHead();
                }

                if(!stse.str.IsEmpty())
                {
                    pRTS->Add(stse.str, true, (int)(tStart / 10000), (int)(tStop / 10000),
                              stse.style, stse.actor, stse.effect, stse.marginRect, stse.layer, stse.readorder);
                    fInvalidate = true;
                }
            }
        }
        else if(m_mt.subtype == MEDIASUBTYPE_SSF)
        {
            ssf::CRenderer* pSSF = (ssf::CRenderer*)(ISubStream*)m_pSubStream;

            CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
            if(!str.IsEmpty())
            {
                pSSF->Append(tStart, tStop, str);
                fInvalidate = true;
            }
        }
        else if(m_mt.subtype == MEDIASUBTYPE_VOBSUB)
        {
            CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
            pVSS->Add(tStart, tStop, pData, len);
        }
        else if (IsHdmvSub(&m_mt))
        {
            CAutoLock cAutoLock(m_pSubLock);
            CRenderedHdmvSubtitle* pHdmvSubtitle = (CRenderedHdmvSubtitle*)(ISubStream*)m_pSubStream;
            pHdmvSubtitle->ParseSample (pSample);
        }
    }

    if(fInvalidate)
    {
        TRACE(_T("InvalidateSubtitle(%I64d, ..)\n"), tStart);
        // IMPORTANT: m_pSubLock must not be locked when calling this
        InvalidateSubtitle(tStart, m_pSubStream);
    }

    hr = S_OK;

    return hr;
}
Exemple #8
0
HRESULT CSubtitleInputPin::CompleteConnect(IPin* pReceivePin)
{
    if (m_mt.majortype == MEDIATYPE_Text) {
        if (!(m_pSubStream = DEBUG_NEW CRenderedTextSubtitle(m_pSubLock))) {
            return E_FAIL;
        }
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
        pRTS->m_name = CString(GetPinName(pReceivePin)) + _T(" (embeded)");
        pRTS->m_dstScreenSize = CSize(384, 288);
        pRTS->CreateDefaultStyle(DEFAULT_CHARSET);
    } else if (m_mt.majortype == MEDIATYPE_Subtitle) {
        SUBTITLEINFO* psi = (SUBTITLEINFO*)m_mt.pbFormat;
        DWORD   dwOffset = 0;
        CString name;
        LCID    lcid = 0;

        if (psi != nullptr) {
            dwOffset = psi->dwOffset;

            name = ISO6392ToLanguage(psi->IsoLang);
            lcid = ISO6392ToLcid(psi->IsoLang);

            CString trackName(psi->TrackName);
            trackName.Trim();
            if (!trackName.IsEmpty()) {
                if (!name.IsEmpty()) {
                    if (trackName[0] != _T('(') && trackName[0] != _T('[')) {
                        name += _T(",");
                    }
                    name += _T(" ");
                }
                name += trackName;
            }
            if (name.IsEmpty()) {
                name = _T("Unknown");
            }
        }

        name.Replace(_T(""), _T(""));
        name.Replace(_T(""), _T(""));

        if (m_mt.subtype == MEDIASUBTYPE_UTF8
                /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
                || m_mt.subtype == MEDIASUBTYPE_SSA
                || m_mt.subtype == MEDIASUBTYPE_ASS
                || m_mt.subtype == MEDIASUBTYPE_ASS2) {
            if (!(m_pSubStream = DEBUG_NEW CRenderedTextSubtitle(m_pSubLock))) {
                return E_FAIL;
            }
            CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
            pRTS->m_name = name;
            pRTS->m_lcid = lcid;
            pRTS->m_dstScreenSize = CSize(384, 288);
            pRTS->CreateDefaultStyle(DEFAULT_CHARSET);

            if (dwOffset > 0 && m_mt.cbFormat - dwOffset > 0) {
                CMediaType mt = m_mt;
                if (mt.pbFormat[dwOffset + 0] != 0xef
                        && mt.pbFormat[dwOffset + 1] != 0xbb
                        && mt.pbFormat[dwOffset + 2] != 0xfb) {
                    dwOffset -= 3;
                    mt.pbFormat[dwOffset + 0] = 0xef;
                    mt.pbFormat[dwOffset + 1] = 0xbb;
                    mt.pbFormat[dwOffset + 2] = 0xbf;
                }

                pRTS->Open(mt.pbFormat + dwOffset, mt.cbFormat - dwOffset, DEFAULT_CHARSET, pRTS->m_name);
            }
        } else if (m_mt.subtype == MEDIASUBTYPE_VOBSUB) {
            if (!(m_pSubStream = DEBUG_NEW CVobSubStream(m_pSubLock))) {
                return E_FAIL;
            }
            CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
            pVSS->Open(name, m_mt.pbFormat + dwOffset, m_mt.cbFormat - dwOffset);
        } else if (IsHdmvSub(&m_mt)) {
            if (!(m_pSubStream = DEBUG_NEW CRenderedHdmvSubtitle(m_pSubLock, (m_mt.subtype == MEDIASUBTYPE_DVB_SUBTITLES) ? ST_DVB : ST_HDMV, name, lcid))) {
                return E_FAIL;
            }
        }
    }

    AddSubStream(m_pSubStream);

    return __super::CompleteConnect(pReceivePin);
}
REFERENCE_TIME CSubtitleInputPin::DecodeSample(const CAutoPtr<SubtitleSample>& pSample)
{
    bool bInvalidate = false;

    if (m_mt.majortype == MEDIATYPE_Text) {
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

        char* pData = (char*)pSample->data.data();

        if (!strncmp(pData, __GAB1__, strlen(__GAB1__))) {
            char* ptr = &pData[strlen(__GAB1__) + 1];
            char* end = &pData[pSample->data.size()];

            while (ptr < end) {
                WORD tag = *((WORD*)(ptr));
                ptr += 2;
                WORD size = *((WORD*)(ptr));
                ptr += 2;

                if (tag == __GAB1_LANGUAGE__) {
                    pRTS->m_name = CString(ptr);
                } else if (tag == __GAB1_ENTRY__) {
                    pRTS->Add(AToW(&ptr[8]), false, *(int*)ptr, *(int*)(ptr + 4));
                    bInvalidate = true;
                } else if (tag == __GAB1_LANGUAGE_UNICODE__) {
                    pRTS->m_name = (WCHAR*)ptr;
                } else if (tag == __GAB1_ENTRY_UNICODE__) {
                    pRTS->Add((WCHAR*)(ptr + 8), true, *(int*)ptr, *(int*)(ptr + 4));
                    bInvalidate = true;
                }

                ptr += size;
            }
        } else if (!strncmp(pData, __GAB2__, strlen(__GAB2__))) {
            char* ptr = &pData[strlen(__GAB2__) + 1];
            char* end = &pData[pSample->data.size()];

            while (ptr < end) {
                WORD tag = *((WORD*)(ptr));
                ptr += 2;
                DWORD size = *((DWORD*)(ptr));
                ptr += 4;

                if (tag == __GAB1_LANGUAGE_UNICODE__) {
                    pRTS->m_name = (WCHAR*)ptr;
                } else if (tag == __GAB1_RAWTEXTSUBTITLE__) {
                    pRTS->Open((BYTE*)ptr, size, DEFAULT_CHARSET, pRTS->m_name);
                    bInvalidate = true;
                }

                ptr += size;
            }
        } else if (pSample->data.size() > 1 && *pData != '\0') {
            CStringA str(pData, (int)pSample->data.size());

            str.Replace("\r\n", "\n");
            str.Trim();

            if (!str.IsEmpty()) {
                pRTS->Add(AToW(str), false, (int)(pSample->rtStart / 10000), (int)(pSample->rtStop / 10000));
                bInvalidate = true;
            }
        }
    } else if (m_mt.majortype == MEDIATYPE_Subtitle) {
        if (m_mt.subtype == MEDIASUBTYPE_UTF8) {
            CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

            CStringW str = UTF8To16(CStringA((LPCSTR)pSample->data.data(), (int)pSample->data.size())).Trim();
            if (!str.IsEmpty()) {
                pRTS->Add(str, true, (int)(pSample->rtStart / 10000), (int)(pSample->rtStop / 10000));
                bInvalidate = true;
            }
        } else if (m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS || m_mt.subtype == MEDIASUBTYPE_ASS2) {
            CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

            CStringW str = UTF8To16(CStringA((LPCSTR)pSample->data.data(), (int)pSample->data.size())).Trim();
            if (!str.IsEmpty()) {
                STSEntry stse;

                int fields = m_mt.subtype == MEDIASUBTYPE_ASS2 ? 10 : 9;

                CAtlList<CStringW> sl;
                Explode(str, sl, ',', fields);
                if (sl.GetCount() == (size_t)fields) {
                    stse.readorder = wcstol(sl.RemoveHead(), nullptr, 10);
                    stse.layer = wcstol(sl.RemoveHead(), nullptr, 10);
                    stse.style = sl.RemoveHead();
                    stse.actor = sl.RemoveHead();
                    stse.marginRect.left = wcstol(sl.RemoveHead(), nullptr, 10);
                    stse.marginRect.right = wcstol(sl.RemoveHead(), nullptr, 10);
                    stse.marginRect.top = stse.marginRect.bottom = wcstol(sl.RemoveHead(), nullptr, 10);
                    if (fields == 10) {
                        stse.marginRect.bottom = wcstol(sl.RemoveHead(), nullptr, 10);
                    }
                    stse.effect = sl.RemoveHead();
                    stse.str = sl.RemoveHead();
                }

                if (!stse.str.IsEmpty()) {
                    pRTS->Add(stse.str, true, (int)(pSample->rtStart / 10000), (int)(pSample->rtStop / 10000),
                              stse.style, stse.actor, stse.effect, stse.marginRect, stse.layer, stse.readorder);
                    bInvalidate = true;
                }
            }
        } else if (m_mt.subtype == MEDIASUBTYPE_VOBSUB) {
            CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
            pVSS->Add(pSample->rtStart, pSample->rtStop, pSample->data.data(), (int)pSample->data.size());
        } else if (IsRLECodedSub(&m_mt)) {
            CRLECodedSubtitle* pRLECodedSubtitle = (CRLECodedSubtitle*)(ISubStream*)m_pSubStream;
            pRLECodedSubtitle->ParseSample(pSample->rtStart, pSample->rtStop, pSample->data.data(), (int)pSample->data.size());
        }
    }

    return bInvalidate ? pSample->rtStart : -1;
}
void CPlayerSubresyncBar::ReloadSubtitle()
{
    m_mode = NONE;
    m_lastSegment = -1;
    m_sts.Empty();
    m_vobSub.RemoveAll();

    ResetSubtitle();

    for (int i = 0, count = m_list.GetHeaderCtrl()->GetItemCount(); i < count; i++) {
        m_list.DeleteColumn(0);
    }

    if (!m_pSubStream) {
        return;
    }

    CLSID clsid;
    m_pSubStream->GetClassID(&clsid);

    if (clsid == __uuidof(CVobSubFile)) {
        CVobSubFile* pVSF = (CVobSubFile*)(ISubStream*)m_pSubStream;

        m_mode = VOBSUB;

        pVSF->Lock();
        ASSERT(pVSF->m_iLang >= 0);
        m_vobSub.Copy(pVSF->m_langs[pVSF->m_iLang].subpos);

        for (size_t i = 0, j = m_vobSub.GetCount(); i < j; i++) {
            CString str;
            str.Format(_T("%d,%d,%d,%Iu"), m_vobSub[i].vobid, m_vobSub[i].cellid, m_vobSub[i].fForced, i);
            m_sts.Add(TToW(str), false, (int)m_vobSub[i].start, (int)m_vobSub[i].stop);
        }
        pVSF->Unlock();

        m_sts.CreateDefaultStyle(DEFAULT_CHARSET);

        pVSF->m_fOnlyShowForcedSubs = false;

        m_list.InsertColumn(COL_START, ResStr(IDS_SUBRESYNC_CLN_TIME), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_END, ResStr(IDS_SUBRESYNC_CLN_END), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_PREVSTART, ResStr(IDS_SUBRESYNC_CLN_PREVIEW), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_PREVEND, ResStr(IDS_SUBRESYNC_CLN_END), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_VOBID, ResStr(IDS_SUBRESYNC_CLN_VOB_ID), LVCFMT_CENTER, 60);
        m_list.InsertColumn(COL_CELLID, ResStr(IDS_SUBRESYNC_CLN_CELL_ID), LVCFMT_CENTER, 60);
        m_list.InsertColumn(COL_FORCED, ResStr(IDS_SUBRESYNC_CLN_FORCED), LVCFMT_CENTER, 60);
    } else if (clsid == __uuidof(CRenderedTextSubtitle)) {
        CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;

        m_mode = TEXTSUB;

        pRTS->Lock();
        m_sts.Copy(*pRTS);
        pRTS->Unlock();
        m_sts.ConvertToTimeBased(m_fps);
        m_sts.Sort(true); /*!!m_bUnlink*/

        m_list.InsertColumn(COL_START, ResStr(IDS_SUBRESYNC_CLN_TIME), LVCFMT_LEFT, 90);
        m_list.InsertColumn(COL_END, ResStr(IDS_SUBRESYNC_CLN_END), LVCFMT_LEFT, 4);
        m_list.InsertColumn(COL_PREVSTART, ResStr(IDS_SUBRESYNC_CLN_PREVIEW), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_PREVEND, ResStr(IDS_SUBRESYNC_CLN_END), LVCFMT_LEFT, 4);
        m_list.InsertColumn(COL_TEXT, ResStr(IDS_SUBRESYNC_CLN_TEXT), LVCFMT_LEFT, 275);
        m_list.InsertColumn(COL_STYLE, ResStr(IDS_SUBRESYNC_CLN_STYLE), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_FONT, ResStr(IDS_SUBRESYNC_CLN_FONT), LVCFMT_LEFT, 60);
        m_list.InsertColumn(COL_CHARSET, ResStr(IDS_SUBRESYNC_CLN_CHARSET), LVCFMT_CENTER, 20);
        m_list.InsertColumn(COL_UNICODE, ResStr(IDS_SUBRESYNC_CLN_UNICODE), LVCFMT_CENTER, 40);
        m_list.InsertColumn(COL_LAYER, ResStr(IDS_SUBRESYNC_CLN_LAYER), LVCFMT_CENTER, 50);
        m_list.InsertColumn(COL_ACTOR, ResStr(IDS_SUBRESYNC_CLN_ACTOR), LVCFMT_LEFT, 80);
        m_list.InsertColumn(COL_EFFECT, ResStr(IDS_SUBRESYNC_CLN_EFFECT), LVCFMT_LEFT, 80);
    }

    m_subtimes.SetCount(m_sts.GetCount());

    for (size_t i = 0, j = m_sts.GetCount(); i < j; i++) {
        m_subtimes[i].orgStart = m_sts[i].start;
        m_subtimes[i].orgEnd = m_sts[i].end;
    }

    ResetSubtitle();
}
STDMETHODIMP_(CSubtitleInputPinHelper*) CSubtitleInputPin::CreateHelper( const CMediaType& mt, IPin* pReceivePin )
{
    XY_LOG_INFO(XY_LOG_VAR_2_STR(pReceivePin));
    CSubtitleInputPinHelper *ret = NULL;
    if(mt.majortype == MEDIATYPE_Text)
    {
        XY_LOG_INFO("Create CTextSubtitleInputPinHepler");
        CRenderedTextSubtitle* pRTS = DEBUG_NEW CRenderedTextSubtitle(m_pSubLock);
        pRTS->m_name = CString(GetPinName(pReceivePin)) + _T(" (embeded)");
        pRTS->m_dstScreenSize = CSize(384, 288);
        ret = DEBUG_NEW CTextSubtitleInputPinHepler(pRTS, m_mt);
    }
    else if(mt.majortype == MEDIATYPE_Subtitle)
    {
        SUBTITLEINFO* psi      = (SUBTITLEINFO*)mt.pbFormat;
        DWORD         dwOffset = 0;
        CString       name;
        LCID          lcid     = 0;

        if (psi != NULL) {
            dwOffset = psi->dwOffset;

            name = ISO6392ToLanguage(psi->IsoLang);
            lcid = ISO6392ToLcid(psi->IsoLang);

            CString trackName(psi->TrackName);
            trackName.Trim();
            if (!trackName.IsEmpty()) {
                if (!name.IsEmpty()) {
                    if (trackName[0] != _T('(') && trackName[0] != _T('[')) {
                        name += _T(",");
                    }
                    name += _T(" ");
                }
                name += trackName;
            }
            if (name.IsEmpty()) {
                name = _T("Unknown");
            }
        }

        name.Replace(_T(""), _T(""));//CAUTION: VS may show name.Replace(_T(""),_T("")), however there is a character in the first _T("")
        name.Replace(_T(""), _T(""));//CAUTION: VS may show name.Replace(_T(""),_T("")), however there is a character in the first _T("")

        if(mt.subtype == MEDIASUBTYPE_UTF8 
            /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
            || mt.subtype == MEDIASUBTYPE_SSA 
            || mt.subtype == MEDIASUBTYPE_ASS 
            || mt.subtype == MEDIASUBTYPE_ASS2)
        {
            XY_LOG_INFO("Create CTextSubtitleInputPinHepler");
            CRenderedTextSubtitle* pRTS = DEBUG_NEW CRenderedTextSubtitle(m_pSubLock);
            pRTS->m_name = name;
            pRTS->m_lcid = lcid;
            pRTS->m_dstScreenSize = CSize(384, 288);

            if(dwOffset > 0 && mt.cbFormat - dwOffset > 0)
            {
                CMediaType mt1 = mt;
                if(mt1.pbFormat[dwOffset+0] != 0xef
                    && mt1.pbFormat[dwOffset+1] != 0xbb
                    && mt1.pbFormat[dwOffset+2] != 0xfb)
                {
                    dwOffset -= 3;
                    mt1.pbFormat[dwOffset+0] = 0xef;
                    mt1.pbFormat[dwOffset+1] = 0xbb;
                    mt1.pbFormat[dwOffset+2] = 0xbf;
                }

                pRTS->Open(mt1.pbFormat + dwOffset, mt1.cbFormat - dwOffset, DEFAULT_CHARSET, pRTS->m_name);
            }
            ret = DEBUG_NEW CTextSubtitleInputPinHepler(pRTS, m_mt);
        }
        else if(mt.subtype == MEDIASUBTYPE_SSF)
        {
            XY_LOG_INFO("Create CSSFInputPinHepler");
            ssf::CRenderer* pSSF = DEBUG_NEW ssf::CRenderer(m_pSubLock);
            pSSF->Open(ssf::MemoryInputStream(mt.pbFormat + dwOffset, mt.cbFormat - dwOffset, false, false), name);
            ret = DEBUG_NEW CSSFInputPinHepler(pSSF, m_mt);
        }
        else if(mt.subtype == MEDIASUBTYPE_VOBSUB)
        {
            XY_LOG_INFO("Create CVobsubInputPinHepler");
            CVobSubStream* pVSS = DEBUG_NEW CVobSubStream(m_pSubLock);
            pVSS->Open(name, mt.pbFormat + dwOffset, mt.cbFormat - dwOffset);
            ret = DEBUG_NEW CVobsubInputPinHepler(pVSS, m_mt);
        }
        else if (IsHdmvSub(&mt)) 
        {
            XY_LOG_INFO("Create CHdmvInputPinHepler");
            CRenderedHdmvSubtitle *hdmv_sub = DEBUG_NEW CRenderedHdmvSubtitle(m_pSubLock,
                (mt.subtype == MEDIASUBTYPE_DVB_SUBTITLES) ? ST_DVB : ST_HDMV, name, lcid);
            ret = DEBUG_NEW CHdmvInputPinHepler(hdmv_sub, m_mt);
        }
    }
    return ret;
}
STDMETHODIMP CTextSubtitleInputPinHepler::Receive( IMediaSample* pSample )
{
    REFERENCE_TIME tStart, tStop;
    pSample->GetTime(&tStart, &tStop);
    tStart += m_tStart; 
    tStop += m_tStart;

    BYTE* pData = NULL;
    HRESULT hr = pSample->GetPointer(&pData);
    if(FAILED(hr) || pData == NULL) return hr;

    int len = pSample->GetActualDataLength();

    if(m_mt.majortype == MEDIATYPE_Text)
    {
        if(!strncmp((char*)pData, __GAB1__, strlen(__GAB1__)))
        {
            char* ptr = (char*)&pData[strlen(__GAB1__)+1];
            char* end = (char*)&pData[len];

            while(ptr < end)
            {
                WORD tag = *((WORD*)(ptr)); ptr += 2;
                WORD size = *((WORD*)(ptr)); ptr += 2;

                if(tag == __GAB1_LANGUAGE__)
                {
                    m_pRTS->m_name = CString(ptr);
                }
                else if(tag == __GAB1_ENTRY__)
                {
                    m_pRTS->Add(AToW(&ptr[8]), false, *(int*)ptr, *(int*)(ptr+4));
                }
                else if(tag == __GAB1_LANGUAGE_UNICODE__)
                {
                    m_pRTS->m_name = (WCHAR*)ptr;
                }
                else if(tag == __GAB1_ENTRY_UNICODE__)
                {
                    m_pRTS->Add((WCHAR*)(ptr+8), true, *(int*)ptr, *(int*)(ptr+4));
                }

                ptr += size;
            }
        }
        else if(!strncmp((char*)pData, __GAB2__, strlen(__GAB2__)))
        {
            char* ptr = (char*)&pData[strlen(__GAB2__)+1];
            char* end = (char*)&pData[len];

            while(ptr < end)
            {
                WORD tag = *((WORD*)(ptr)); ptr += 2;
                DWORD size = *((DWORD*)(ptr)); ptr += 4;

                if(tag == __GAB1_LANGUAGE_UNICODE__)
                {
                    m_pRTS->m_name = (WCHAR*)ptr;
                }
                else if(tag == __GAB1_RAWTEXTSUBTITLE__)
                {
                    m_pRTS->Open((BYTE*)ptr, size, DEFAULT_CHARSET, m_pRTS->m_name);
                }

                ptr += size;
            }
        }
        else if(pData != 0 && len > 1 && *pData != 0)
        {
            CStringA str((char*)pData, len);

            str.Replace("\r\n", "\n");
            str.Trim();

            if(!str.IsEmpty())
            {
                m_pRTS->Add(AToW(str), false, (int)(tStart / 10000), (int)(tStop / 10000));
            }
        }
        else
        {
            XY_LOG_WARN("Unexpected data");
        }
    }
    else if(m_mt.majortype == MEDIATYPE_Subtitle)
    {
        if(m_mt.subtype == MEDIASUBTYPE_UTF8)
        {
            CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
            if(!str.IsEmpty())
            {
                m_pRTS->Add(str, true, (int)(tStart / 10000), (int)(tStop / 10000));
            }
            else
            {
                XY_LOG_WARN("Empty data");
            }
        }
        else if(m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS || m_mt.subtype == MEDIASUBTYPE_ASS2)
        {
            CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
            if(!str.IsEmpty())
            {
                STSEntry stse;

                int fields = m_mt.subtype == MEDIASUBTYPE_ASS2 ? 10 : 9;

                CAtlList<CStringW> sl;
                Explode(str, sl, ',', fields);
                if(sl.GetCount() == fields)
                {
                    stse.readorder = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.layer = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.style = sl.RemoveHead();
                    stse.actor = sl.RemoveHead();
                    stse.marginRect.left = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.marginRect.right = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.marginRect.top = stse.marginRect.bottom = wcstol(sl.RemoveHead(), NULL, 10);
                    if(fields == 10) stse.marginRect.bottom = wcstol(sl.RemoveHead(), NULL, 10);
                    stse.effect = sl.RemoveHead();
                    stse.str = sl.RemoveHead();
                }

                if(!stse.str.IsEmpty())
                {
                    m_pRTS->Add(stse.str, true, (int)(tStart / 10000), (int)(tStop / 10000), 
                        stse.style, stse.actor, stse.effect, stse.marginRect, stse.layer, stse.readorder);
                }
            }
            else
            {
                XY_LOG_WARN("Empty data");
            }
        }
        else
        {
            XY_LOG_WARN("Unsupported media type "<<XyUuidToString(m_mt.subtype));
        }
    }
    else
    {
        XY_LOG_WARN("Unsupported media type "<<XyUuidToString(m_mt.majortype));
    }
    return S_OK;
}
STDMETHODIMP CTextSubtitleInputPinHepler::NewSegment( REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate )
{
    m_pRTS->RemoveAllEntries();
    m_pRTS->CreateSegments();
    return __super::NewSegment(tStart,tStop,dRate);
}