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

📄 mpeg2dataparser.cpp

📁 * This file is part of DigitalWatch, a free DTV watching and recording * program for the VisionPlu
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/**
 *	Mpeg2DataParser.cpp
 *	Copyright (C) 2004 Nate
 *  Copyright (C) 2004 JoeyBloggs
 *
 *  significant portions of this code are taken from 
 *  the linuxtv-dvb-apps-1.1.0 scan.c file
 *
 *	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 "Mpeg2DataParser.h"

#include <process.h>
#include <math.h>

void ParseMpeg2DataThread( void *pParam )
{
	Mpeg2DataParser *scanner;
	scanner = (Mpeg2DataParser *)pParam;
	scanner->StartMpeg2DataScanThread();
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Mpeg2DataParser::Mpeg2DataParser()
{
	m_hScanningDoneEvent = CreateEvent(NULL, TRUE, FALSE, "ScanningDone");
	m_piIMpeg2Data = NULL;

	long_timeout = 0;

	m_networkNumber = 0;
	current_tp = NULL;

	//verbose = FALSE;
	m_bThreadStarted = FALSE;
	m_bActivity = FALSE;
}

Mpeg2DataParser::~Mpeg2DataParser()
{
	if (m_piIMpeg2Data != NULL)
		m_piIMpeg2Data.Release();
}

void Mpeg2DataParser::SetNetworkNumber(int network)
{
	m_networkNumber = network;
}

void Mpeg2DataParser::SetFilter(CComPtr <IBaseFilter> pBDASecTab)
{
	m_piIMpeg2Data.Release(); 

	if (pBDASecTab != NULL) 
	{
		HRESULT hr = pBDASecTab->QueryInterface(__uuidof(IMpeg2Data), reinterpret_cast<void**>(&m_piIMpeg2Data));
	}
}

void Mpeg2DataParser::ReleaseFilter()
{
	m_piIMpeg2Data.Release();
}

//////////////////////////////////////////////////////////////////////
// Event stuff
//////////////////////////////////////////////////////////////////////
void Mpeg2DataParser::Reset()
{
	current_tp = NULL;

	struct section_buf *s;
	while (waiting_filters.size())
	{
		s = waiting_filters.back();
		waiting_filters.pop_back();
		free (s);
	}

	struct transponder *t;
	while (transponders.size())
	{
		t = transponders.back();
		transponders.pop_back();
		DeleteTransponder(t);
	}

	m_bThreadStarted = FALSE;
	m_bActivity = FALSE;
	ResetEvent(m_hScanningDoneEvent);
}

void Mpeg2DataParser::DeleteTransponder(struct transponder *t)
{
	struct service *s;
	while (t->services.size())
	{
		s = t->services.back();
		t->services.pop_back();
		DeleteService(s);
	}
	if (t->other_f)
		free(t->other_f);
	t->other_f = NULL;
	free(t);
}

void Mpeg2DataParser::DeleteService(struct service *s)
{
	if (s->provider_name)
		free(s->provider_name);
	s->provider_name = NULL;
	if (s->service_name)
		free(s->service_name);
	s->service_name = NULL;

	free(s);
}

DWORD Mpeg2DataParser::WaitForScanToFinish()
{
	DWORD result;
	do
	{
		result = WaitForSingleObject(m_hScanningDoneEvent, 15000);
	} while ((result == WAIT_TIMEOUT) && (m_bActivity));
	return result;
}

//////////////////////////////////////////////////////////////////////
// Method just to kick off a separate thread
//////////////////////////////////////////////////////////////////////
void Mpeg2DataParser::StartMpeg2DataScan()
{
	//Make sure we only start scanning the first time the ServiceChanged event calls us.
	if (m_bThreadStarted)
		return;
	m_bThreadStarted = TRUE;

	//Start a new thread to do the scanning because the 
	//IGuideDataEvent::ServiceChanged method isn't allowed to block.
	DWORD dwThreadId = 0;
	unsigned long result = _beginthread(ParseMpeg2DataThread, 0, (void *) this);
}

//////////////////////////////////////////////////////////////////////
// The real work starts here
//////////////////////////////////////////////////////////////////////
void Mpeg2DataParser::StartMpeg2DataScanThread()
{
	HRESULT hr = S_OK;

	m_bActivity = TRUE;
	try
	{
		if (m_piIMpeg2Data != NULL) 
		{
			struct section_buf *s0;

			s0 = (struct section_buf *)malloc(sizeof(struct section_buf));
			SetupFilter(s0, 0x00, 0x00, 1, 0, 5);  // PAT
			AddFilter(s0);

			s0 = (struct section_buf *)malloc(sizeof(struct section_buf));
			SetupFilter(s0, 0x10, 0x40, 1, 0, 15); // NIT
			AddFilter(s0);

			s0 = (struct section_buf *)malloc(sizeof(struct section_buf));
			SetupFilter(s0, 0x11, 0x42, 1, 0, 5);  // SDT
			AddFilter(s0);

			ReadFilters();
		}
	}
	catch(...)
	{
		output.showf("# Unhandled exception in Mpeg2DataParser::StartMpeg2DataScanThread()\n");
	}

	m_bActivity = FALSE;
	SetEvent(m_hScanningDoneEvent);
} 

//////////////////////////////////////////////////////////////////////
void Mpeg2DataParser::SetupFilter (struct section_buf* s, int pid, int tid, int run_once, int segmented, int timeout)
{
	memset (s, 0, sizeof(struct section_buf));

	s->fd = -1;
	s->pid = pid;
	s->table_id = tid;

	s->run_once = run_once;
	s->segmented = segmented;

	if (long_timeout)
		s->timeout = 5 * timeout;
	else
		s->timeout = timeout;

	s->table_id_ext = -1;
	s->section_version_number = -1;
}

void Mpeg2DataParser::AddFilter (struct section_buf *s)
{
	waiting_filters.push_back(s);
}

void Mpeg2DataParser::ReadFilters(void)
{
	struct section_buf *s;

	while (waiting_filters.size())
	{
		s = waiting_filters.front();
		ReadSection(s);
		waiting_filters.erase(waiting_filters.begin());
		free (s);
	}
}





//////////////////////////////////////////////////////////////////////
void Mpeg2DataParser::ReadSection(struct section_buf *s)
{
	PID pid = s->pid;
	TID tid = s->table_id;
	DWORD dwTimeout = s->timeout * 1000;
	if (m_piIMpeg2Data != NULL)
	{
		HRESULT hr;
		ISectionList* piSectionList = NULL;

		if (SUCCEEDED(hr = m_piIMpeg2Data->GetTable(pid, tid, NULL, dwTimeout, &piSectionList)))
		{
			WORD cSections;
			if (SUCCEEDED(hr = piSectionList->GetNumberOfSections(&cSections)))
			{
				verbose.showf(_T("\n%d section(s) found for pid=%.4x, tid=%.2x\n"), cSections, pid, tid);
			
				verbose.showf("pid \n");

				for (WORD i = 0; i < cSections; i++)
				{
					// Iterate through the list of sections.
					SECTION* pstSection;
					DWORD    ulSize;
					
					hr = piSectionList->GetSectionData(i, &ulSize, &pstSection);
					
					if (SUCCEEDED(hr))
					{
						s->buf = (unsigned char *)pstSection;
						parse_section(s);
					}
				}
			}
			else
			{
				output.showf(_T("Error 0x%x getting number of sections\n"), hr); 
			}
			
			piSectionList->Release();
		}
		else
		{
			output.showf(_T("Timeout getting table (pid=%.4x, tid=%.2x)\n"), pid, tid);
		}
	} 
}


/* service_ids are guaranteed to be unique within one TP
 * (the DVB standards say theay should be unique within one
 * network, but in real life...)
 */
struct service *Mpeg2DataParser::alloc_service(struct transponder *tp, int service_id)
{
	struct service *s = (struct service *)calloc(1, sizeof(*s));
	s->service_id = service_id;
	tp->services.push_back(s);
	return s;
}

struct service *Mpeg2DataParser::find_service(struct transponder *tp, int service_id)
{
	struct service *s;

	vector<service *>::iterator it;
	for ( it = tp->services.begin() ; it != tp->services.end() ; it++ )
	{
		s = *it;
		if (s->service_id == service_id)
			return s;
	}
	return NULL;
}

struct transponder *Mpeg2DataParser::alloc_transponder(int transport_stream_id)
{
	struct transponder *tp = (struct transponder *)calloc(1, sizeof(*tp));

	tp->transport_stream_id = transport_stream_id;
	transponders.push_back(tp);
	return tp;
}

struct transponder *Mpeg2DataParser::find_transponder(int transport_stream_id)
{
	struct transponder *tp;

	vector<transponder *>::iterator it;
	for ( it = transponders.begin() ; it != transponders.end() ; it++ )
	{
		tp = *it;
		if (tp->transport_stream_id == transport_stream_id)
			return tp;
	}
	return NULL;
}

void Mpeg2DataParser::parse_iso639_language_descriptor (const unsigned char *buf, struct service *s)
{
	unsigned char len = buf [1];

	buf += 2;

	if (len >= 4)
	{
		verbose.showf("    LANG=%.3s %d\n", buf, buf[3]);
		memcpy(s->audio_lang[s->audio_num], buf, 3);
#if 0
		/* seems like the audio_type is wrong all over the place */
		//if (buf[3] == 0) -> normal
		if (buf[3] == 1)
			s->audio_lang[s->audio_num][3] = '!'; /* clean effects (no language) */
		else if (buf[3] == 2)
			s->audio_lang[s->audio_num][3] = '?'; /* for the hearing impaired */
		else if (buf[3] == 3)
			s->audio_lang[s->audio_num][3] = '+'; /* visually impaired commentary */
#endif
	}
}

void Mpeg2DataParser::parse_network_name_descriptor (const unsigned char *buf, struct transponder *tp)
{
	if (tp->network_name)
		free (tp->network_name);

	unsigned char len = buf [1];

	tp->network_name = (unsigned char *)malloc (len + 1);
	memcpy (tp->network_name, buf+2, len);
	tp->network_name[len] = '\0';

	verbose.showf("    Network Name '%.*s'\n", len, buf + 2);
}

void Mpeg2DataParser::print_unknown_descriptor(const unsigned char *buf, int descriptor_len)
{
	PrintByteArray(buf, descriptor_len);
}

void Mpeg2DataParser::parse_terrestrial_delivery_system_descriptor (const unsigned char *buf, struct transponder *t)
{
	//static const fe_modulation_t m_tab [] = { QPSK, QAM_16, QAM_64, QAM_AUTO };
	//static const fe_code_rate_t ofec_tab [8] = { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8 };
	//struct dvb_ofdm_parameters *o;

	if (!t) {
		verbose.showf("    terrestrial_delivery_system_descriptor outside transport stream definition (ignored)\n");
		return;
	}
	//o = &t->param.u.ofdm;
	//t->type = FE_OFDM;


	t->frequency = (buf[2] << 24) | (buf[3] << 16);
	t->frequency |= (buf[4] << 8) | buf[5];
	t->frequency /= 100;
	verbose.showf("    Frequency %i", t->frequency);


	t->bandwidth = 8 - ((buf[6] >> 5) & 0x3);
	verbose.showf("    Bandwidth %i", t->bandwidth);


	//o->constellation = m_tab[(buf[7] >> 6) & 0x3];
	switch ((buf[7] >> 6) & 0x3)
	{
	case 0:
		verbose.showf("    QPSK\n");
		break;
	case 1:
		verbose.showf("    QAM_16\n");
		break;
	case 2:
		verbose.showf("    QAM_64\n");
		break;
	case 3:
		verbose.showf("    QAM_AUTO\n");
		break;
	}

	//o->hierarchy_information = HIERARCHY_NONE + ((buf[7] >> 3) & 0x3);

	//DWORD coderateHP = buf[7] & 0x7;
	switch (buf[7] & 0x7)
	{
	case 0:
		verbose.showf("    HP - FEC_1_2");

⌨️ 快捷键说明

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