⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvbteletextsubtitles.cpp

📁 Teletext module usually used in the DVB area.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// DVBTeletextSubtitles.cpp
/* 

(C) Luke Paton 2004.

Copyright notice:

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


Parts of this code from Mpeg2DataParser.cpp, part of the ScanChannelsBDA program
written by Nate.

 *	Mpeg2DataParser.cpp
 *	Copyright (C) 2004 Nate
 *
 *	This file is part of DigitalWatch, a free DTV watching and recording
 *	program for the VisionPlus DVB-T.
 *
 *	DigitalWatch is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	DigitalWatch 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 DigitalWatch; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#include "stdafx.h"
#include "resource.h"
#include "DVBTeletextSubtitles.h"
#include "DVBSubtitlesFilter.h"
#include "DVBTeletextSubtitlesPropertiesPage1.h"
#include <ks.h>
#include <ksmedia.h>
#include <bdatypes.h>
#include <bdamedia.h>

#define NTOH_S(s)   ( (((s) & 0xFF00) >> 8)  |  (((s) & 0x00FF) << 8) )

#define BYTE_OFFSET(pb,i)           (& BYTE_VALUE((pb),i))
#define BYTE_VALUE(pb,i)            (((BYTE *) (pb))[i])
#define WORD_VALUE(pb,i)            (* (UNALIGNED WORD *) BYTE_OFFSET((pb),i))

CDVBTeletextSubtitles::CDVBTeletextSubtitles(LPUNKNOWN punk,HRESULT *phr) 
    : CSource(TEXT("DVBTeletextSubtitles"), punk, CLSID_DVBTeletextSubtitles)
    , CPersistStream(punk, phr)
	, m_pTeletextPIDInput(NULL)
	, m_pTeletextOutput(NULL)
	, m_nTeletextPid(0x204)
	, m_nSubtitlesDecimalPage(801)
    , m_nSubtitlesDecimalSubPage(0)
	, m_nLastLine(23)
    , m_DisplayHeadingLine(FALSE)
	, m_TransparencyPercent(85)
    , m_FilePath(L"C:\\home\\lukep\\DTV\\capture\\teletextdump.ts")
	, m_ConnectedToInputPID(false)
	, m_ThreadId(0)
	, m_FirstEventMilliseconds(0)
	, m_SubtitleDelayTime(0)
	, m_SubtitleDelayRange(2000)
{
	ClearDisplay();

    HRESULT hr;
	m_pTeletextOutput = new CTeletextOutputPin
		(
			NAME("Teletext video output pin"),
			this,        // Owner filter
			&m_csFilter,
            &hr,         // Result code
            L"Teletext Video Output"    // Pin name
        );

    m_Colours[Colour_Background] = RGB(0, 0, 0);
    m_Colours[Colour_Black] = RGB(128, 128, 128);
    m_Colours[Colour_Red] = RGB(255, 0, 0);
    m_Colours[Colour_Green] = RGB(0, 255, 0);
    m_Colours[Colour_Yellow] = RGB(255, 255, 0);
    m_Colours[Colour_Blue] = RGB(0, 0, 255);
    m_Colours[Colour_Magenta] = RGB(255, 0, 255);
    m_Colours[Colour_Cyan] = RGB(0, 255, 255);
    m_Colours[Colour_White] = RGB(255, 255, 255);
    m_Colours[Colour_Key] = RGB(0, 0, 0);
}

CDVBTeletextSubtitles::~CDVBTeletextSubtitles(void)
{
	if (m_pTeletextPIDInput != NULL)
	{
        delete m_pTeletextPIDInput;
	}

	if (m_pTeletextOutput != NULL)
	{
        delete m_pTeletextOutput;
	}
}

int CDVBTeletextSubtitles::GetPinCount()
{
    return 2;
}

CBasePin* CDVBTeletextSubtitles::GetPin(int n)
{
	if (n == 0)
	{
		// Create an input pin if not already done
		if (m_pTeletextPIDInput == NULL)
		{
            HRESULT hr;
			m_pTeletextPIDInput = new CTeletextPIDInputPin
				(
					NAME("Teletext PID input pin"),
					this,        // Owner filter
					&m_csFilter,
                    &hr,         // Result code
                    L"Teletext PID Input"    // Pin name
                );

			// Constructor for CTeletextPIDInputPin can't fail
		}

		return m_pTeletextPIDInput;
	}
    else
    {
        if (n == 1)
        {
		    // Create an output pin if not already done
		    if (m_pTeletextOutput == NULL)
		    {
                HRESULT hr;
			    m_pTeletextOutput = new CTeletextOutputPin
				    (
					    NAME("Teletext video output pin"),
					    this,        // Owner filter
					    &m_csFilter,
                        &hr,         // Result code
                        L"Teletext Video Output"    // Pin name
                    );

			    // Constructor for CTeletextOutputPin can't fail
		    }

		    return m_pTeletextOutput;
        }
    }

	return NULL;
}

HRESULT CDVBTeletextSubtitles::Run(REFERENCE_TIME tStart)
{
	if (m_pGraph == NULL)
	{
		return E_POINTER;
	}

    /*
	CComPtr<IBaseFilter> video_mixing_renderer_filter_9;
	HRESULT hr = m_pGraph->FindFilterByName(L"Video Mixing Renderer 9", &video_mixing_renderer_filter_9);
	if (!SUCCEEDED(hr) || (video_mixing_renderer_filter_9 == NULL))
	{
		return hr;
	}

	CComPtr<IBasicVideo> basic_video;
    basic_video.Release();
	hr = video_mixing_renderer_filter_9->QueryInterface(IID_IBasicVideo, (void**)&basic_video);
	if (!SUCCEEDED(hr) || (basic_video == NULL))
	{
		return hr;
	}

	hr = basic_video->GetVideoSize(&m_nWidth, &m_nHeight);
	if (!SUCCEEDED(hr) || (m_nWidth == 0) || (m_nHeight == 0))
	{
		return hr;
	}

    // Get alpha-blended bitmap interface
	m_pVMRMixerBitmap9.Release();
    hr = video_mixing_renderer_filter_9->QueryInterface(IID_IVMRMixerBitmap9, (void**)&m_pVMRMixerBitmap9);
	if (!SUCCEEDED(hr) || (m_pVMRMixerBitmap9 == NULL))
	{
		return hr;
	}
    */

	m_PesPacketDirty = false;
	m_PesPacketLength = -1;
	m_tsPacketCounter = -1;
	m_tsStatus = TS_WAITING;

	ClearDisplay();

	return CSource::Run(tStart);
}

/*
Structure of Transport Stream (from ISO/IEC 13818-1):

transport_packet()
{
	sync_byte                                   8    bslbf       0
	transport_error_indicator                   1    bslbf       1
	payload_unit_start_indicator                1    bslbf       1
	transport_priority                          1    bslbf       1
	PID                                         13   uimsbf      1,2
	transport_scrambling_control                2    bslbf       3
	adaption_field_control                      2    bslbf       3
	continuity_counter                          4    uimsbf      3
	if (adaption_field_control == '10' || adaption_field_control == '11')
	{
		adaption_field()
	}

	if (adaption_field_control == '01' || adaption_field_control=='11')
	{
		for (i = 0; i < N; i++)
		{
			data_byte                             8    bslbf
		}
	}
}
*/

bool CDVBTeletextSubtitles::ReadTeletextTransportStreamPacket(unsigned char* ts_buf)
{
	if ( ( ( ( ts_buf[1] & 0x1f ) << 8 ) | ts_buf[2]) == m_nTeletextPid)
	{
		int	continuity_counter = ts_buf[3] & 0x0f;
		int adaption_field_control = (ts_buf[3] & 0x30) >> 4;
		int discontinuity_indicator = 0;
		
		if ( (adaption_field_control == 2) || (adaption_field_control == 3) )
		{
			// adaption_field
			if (ts_buf[4] > 0)
			{
				// adaption_field_length
				discontinuity_indicator = (ts_buf[5] & 0x80) >> 7;
			}
		}

		/* Firstly, check the integrity of the stream */
		if (m_tsPacketCounter == -1)
		{
			m_tsPacketCounter = continuity_counter;
		}
		else
		{
			if ( (adaption_field_control != 0) && (adaption_field_control != 2) )
			{
				m_tsPacketCounter++;
				m_tsPacketCounter %= 16;
			}
		}

		if (m_tsPacketCounter != continuity_counter)
		{
			if (discontinuity_indicator == 0)
			{
				m_PesPacketDirty = true;
			}

			m_tsPacketCounter = continuity_counter;
		}

		// Check payload start indicator.
		if (ts_buf[1] & 0x40)
		{
			if (m_tsStatus == TS_IN_PAYLOAD)
			{
				if ( !m_PesPacketDirty && CheckPesPacket() )
				{
					if (!ProcessPesPacket())
					{
						return false;
					}
				}

				m_PesPacketDirty = false;
			}
			else
			{
				m_tsStatus = TS_IN_PAYLOAD;
			}

			m_PesPacketLength = 0;
		}

		if (m_tsStatus == TS_IN_PAYLOAD)
		{
			int i = 4;
			if ( (adaption_field_control == 2) || (adaption_field_control == 3) )
			{
				// Adaption field!!!
				int adaption_field_length = ts_buf[i++];
				if (adaption_field_length > 182)
				{
					adaption_field_length = 182;
					m_tsStatus = TS_WAITING;
					return false;
				}

				i += adaption_field_length;
			}

			if ( (adaption_field_control == 1) || (adaption_field_control == 3) )
			{
				// Data
				if ( (m_PesPacketLength + (188 - i)) > sizeof(m_PesPacketBuffer) )
				{
				}
				else
				{
					memcpy(&m_PesPacketBuffer[m_PesPacketLength], &ts_buf[i],188-i);
				}

				m_PesPacketLength += (188 - i);

				if (m_PesPacketLength > 2000)
				{
					return false;
				}
			}
		}
	}

	return true;
}

bool CDVBTeletextSubtitles::ReadTeletextTransportStreamSample(IMediaSample * pSample)
{
    REFERENCE_TIME rtStart = 0;
    REFERENCE_TIME rtStop = 0;
    pSample->GetTime( &rtStart, &rtStop );

    BYTE* pBuffer = 0;
    pSample->GetPointer(&pBuffer);

	long length = pSample->GetActualDataLength();

	unsigned char* buf_pos = pBuffer;

	while ((buf_pos - pBuffer) < length)
	{
		if (((buf_pos - pBuffer) + 188) < length)
		{
			unsigned char ts_buf[188];
            memcpy(&ts_buf, buf_pos, 188);
			if (ts_buf[0] == 0x47)
			{
				// complete TS packet
				if (!ReadTeletextTransportStreamPacket(ts_buf))
				{
					return false;
				}
			}
			else
			{
				StartFixTeletextInputPinThread();
				return true;
			}
		}

		buf_pos += 188;
	}

	return true;
}

STDMETHODIMP
CDVBTeletextSubtitles::set_SubtitlesDecimalPage(LONG subtitles_page)
{
	m_nSubtitlesDecimalPage = subtitles_page;
    SetDirty(TRUE);
	return S_OK;
}

STDMETHODIMP
CDVBTeletextSubtitles::get_SubtitlesDecimalPage(LONG* subtitles_page)
{
	*subtitles_page = m_nSubtitlesDecimalPage;
	return S_OK;
}

STDMETHODIMP
CDVBTeletextSubtitles::set_SubtitlesDecimalSubPage(LONG subtitles_subpage)
{
	m_nSubtitlesDecimalSubPage = subtitles_subpage;
    SetDirty(TRUE);
	return S_OK;
}

STDMETHODIMP
CDVBTeletextSubtitles::get_SubtitlesDecimalSubPage(LONG* subtitles_subpage)
{
	*subtitles_subpage = m_nSubtitlesDecimalSubPage;
	return S_OK;
}

STDMETHODIMP
CDVBTeletextSubtitles::set_SubtitleDelayTime(/* [in] */ DWORD subtitle_delay_time)
{
	m_SubtitleDelayTime = subtitle_delay_time;
    SetDirty(TRUE);
	return S_OK;
}

STDMETHODIMP
CDVBTeletextSubtitles::get_SubtitleDelayTime(/* [out] */ DWORD *subtitle_delay_time)
{
	*subtitle_delay_time = m_SubtitleDelayTime;
	return S_OK;
}


STDMETHODIMP
CDVBTeletextSubtitles::set_SubtitleDelayRange(/* [in] */ DWORD subtitle_delay_range)
{
	m_SubtitleDelayRange = subtitle_delay_range;
    SetDirty(TRUE);
	return S_OK;
}

STDMETHODIMP
CDVBTeletextSubtitles::get_SubtitleDelayRange(/* [out] */ DWORD *subtitle_delay_range)
{
	*subtitle_delay_range = m_SubtitleDelayRange;
	return S_OK;
}

HRESULT
CDVBTeletextSubtitles::PrintMpeg2Section
(
    IMpeg2Data* pMpeg2Data,
    SECTION *pSection,
    DWORD dwPacketLength
)
{ 
    if (!pSection)
        return E_POINTER;
	
    if (dwPacketLength < sizeof(SECTION))
    {
        ATLTRACE(L"Malformed MPEG-2 section data.\n");
        return E_FAIL;
    }

    HRESULT hr = S_OK;

    // Coerce the header bits to a bit field structure.
    MPEG_HEADER_BITS *pHeader = (MPEG_HEADER_BITS*)&pSection->Header.W;

    if (pHeader->SectionSyntaxIndicator)
    { 
        // Coerce the section structure to a long section header. 
        LONG_SECTION *pLong = (LONG_SECTION*) pSection; 

        MPEG_HEADER_VERSION_BITS *pVersion = (MPEG_HEADER_VERSION_BITS*)&pLong->Version.B; 

		switch (pSection->TableId)
		{
		case 0x00:	//PAT
			{
				ATLTRACE(TEXT("Transport Stream ID = %.4x\n\n"), NTOH_S(WORD_VALUE(pSection,3)));

				BYTE* pbBuf = pLong->RemainingData;
				int number_of_programs = (pHeader->SectionLength - 5 - 4) / 4;

				int i = 0;
				while (i < pHeader->SectionLength - 5)
				{
					int programNumber = (pbBuf[i] << 8) | pbBuf[i+1];
					int programId = ((pbBuf[i+2] & 0x1f) << 8) | pbBuf[i+3];
					if ((pbBuf[i+2] & 0xe0) == 0xe0)
					{
						if (programNumber != 0)
                        {
                            hr = PrintMpeg2Table(pMpeg2Data, programId, 0x02, 5000);
                            if (!SUCCEEDED(hr))
                            {
                                return hr;
                            }
                        }

                        ATLTRACE("\n");
					}

                    i += 4;
				} 

                ATLTRACE("\n");
				break;
			}

        case 0x01:	//CAT
			{
				break;
			}

        case 0x02:	//PMT
			{
				int program_info_length = (NTOH_S(WORD_VALUE(pSection, 10)) & 0x0fff);
				ATLTRACE(TEXT("Program Number = 0x%.4x (%d)\n"), WORD_VALUE(pSection, 3), WORD_VALUE(pSection, 3));

				BYTE* pStartEs  = (BYTE*)pSection + 12 + program_info_length;
				BYTE* pEndEs    = (BYTE*)pSection + pHeader->SectionLength + 3 - 4;   //points to the byte before CRS_323, 4
				BYTE* pTmp ;

				unsigned short EsNumber = 0;
				int offset = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -