Analyzátor servisních informací z trasportního toku DVB-T

Libor Macek, Tomáš Kučera
xmacek15 stud.feec.vutbr.cz, xkucer62stud.feec.vutbr.cz  

Obsah:

  1. Úvod
  2. Realizace
  3. Závěr
  4. Soubory
  5. Literatura

Úvod

Servisní informace jsou přídavné informace v trasportním toku. Tyto informace jsou potřebné pro správné dekódování jednotlivých elementárních datových proudů. Dále pak také obohacují obrazové a zvukové data o informace, které mohou být pro diváka užitečné. Typickým příkladem může být elektronický programový průvodce.
       Cílem toho projektu je vytvořit program pro analýzu servisních informací z trasportního toku DVB-T. Trasportní tok je získáván pomocí karty TechniSat AirStar 2. Program ovládá tuto kartu, zísává potřebné data pro analýzu a poté data analyzuje a zobrazí dostupné servisní informace.

Realizace

Princip funkce programu
Pro vývoj programu byl zvolen objektově orientovaný jazyk C++. Tento jazyk byl zvolen z důvodu lepší vazby programu na DVB-T PC kartu TechniSat AirStar 2, pro kterou je software napsán rovněž v jazyce C++. Program je možné rozdělit na několik základních částí. První částí je načítání dat ze souboru. Tento proces zajišťuje třída DataLoader. S touto třídou spolupracuje třída TablesContainer, do které DataLoader ukládá načtené data. Dále je zde třída CardDriver, která obsluhuje kartu. Poslední třídou je SiAnalyzator. V této třídě jsou definovány objekty pro grafické uživatelské prostředí. Dále pak také funkce, které strukturují výpis dat ze třídy TablesContainer do příslušných objektů textBox.

Karta

Obr.1: Karta TechniSat AirStar 2 s příslušenstvím.

Podrobnější popis programu
První částí programu je datový kontejner. Zde se ukládají načtené servisní informace. Důležitým požadavkem je přehlednost uložených dat spolu s použitím minimálního množství do jisté míry universálních struktur nebo tříd. Datový kontejner je samostatná třída s názvem TablesContainer.

Datový kontejner

Obr. 2: Třída datového kontejneru.


       Analýzu dat a jejich ukládání do datového kontejneru zajišťuje třída DataLoader. Tato třída obsahuje metody a proměnné určené pro práci se souborem s obsahem transportního toku uloženým na pevném disku. Pro spuštění načítání dat slouží public (veřejná) metoda loadData(). Tato metoda dále volá privátní funkce, které zajišťují například plnění datového kontejneru, počítání paketů a jiné. Vývojový diagram metody loadData()je na obr. 3.

Schéma

Obr. 3: Vývojový diagram metody pro analýzu dat.


       Veškerou komunikaci s kartou TechniSat AitStar 2 zajišťujě třída CardDriver. Tato třída je realizována jako dynamická knihovna v souboru CardDriver.dll. Hlavním úkolem metod této třídy je vytvoření dočasného souboru s daty určenými pro analýzu. Metoda, která je v tomto případě volána se nazývá getTunerData(frequencyMhz, bandwidthMhz, durationS). Tato metoda vrací hodnotu typu bool, která informuje o jejím úspěchu. Metoda v sobě osahuje volání všech potřebných metod pro korektní práci s kartou. Mezi tyto metody patří například initializeCard(), setTuner(), recordData() a jiné. Pro získání paketů transportního toku z karty je nutné zadat PID paketů, které se mají zachytávat na příslušném datovém pinu 0 až 3. Je zřejmé, že není možné znát dopředu PID paketů z obsahem PMT tabulek, protože jsou vysílány v PAT tabulce. Dočasný soubor je tedy vytvářen tak, že je nejprve zachycena sekvence dat s PID 0x00, což jsou pakety tabulky PAT. Dále pak jsou pomocí metody fastDecodePat() získány PID jednotlivých PMT tabulek a o tyto informace je obohacen vektor pids, který v sobě nese všechny PID, které mají byt zachyceny na pinu 0. Během tohoto zachytávaní jsou tyto pakety ukládány do dočasného souboru s názvem PIN0.ts. Po dokončení této metody, která je závislá na nastavené délce analýzy, je toto zachytávání ukončeno a metoda getTunerData() provede uvolnění karty pomocí metody Release(). Poté metoda vrátí hodnotu true, což značí úspěšné dokončení. Dočasný soubor se zachycenými daty transportního toku je ve stejném adresáři jako program. Vývojový diagram metody getTunerData() je na obr. 4.

Uživatelské prostředí

Obr. 4: Vývojový diagram metody pro získávaní dat z karty.


       Vzhled uživatelského prostředí je na obr. 5. Z tohoto obrázku je patrné rozdělení prostředí na ovládací a zobrazovací část. Na levé straně jsou ovládací prvky pro konfiguraci požadovaných dat. Na pravé straně jsou pak jednotlivé záložky, kde mohou být tyto data zobrazeny. Pro práci s programem je nutné, aby uživatel nejprve zvolil zdroj dat. Vybírat je možné ze dvou variant. První variantou je analýza dat ze souboru na pevném disku počítače, druhou pak analýza dat dostupných z DVB-T PC karty TechniSat AirStar 2. Aby nedocházelo k nechtěnému kombinování obou variant nastavení, jsou vždy ovládací prvky druhé varianty neaktivní.

Uživatelské prostředí
Uživatelské prostředí

Obr. 5: Vzhled uživatelského prostředí s daty druhého multiplexu.

Ukázka zdrojového kódu načítání PAT tabulky

/******************************************************PAT TABLE***********************************************************************************************/
void DataLoader::loadPat()
{
	if (patLoaded){return;}  //overeni, zda tabulka jeste neni nactena
	
	counterByte = 4+2; //nastaveni pocitadla prectenzch bajtu (4 bajty hlavicky paketu TS + 2 bajty ID tabulky
	tables->PAT.setTableID(tableID); //ulozeni hodnoty ID tabulky
	try  //blok try pro osetreni vyjimek behem nacitani
	{
		int byteBuff = readByte();	//metoda readByte() cte jednotlive bajty, hodnota je ulozena do pomocne promenne
		counterByte++;	//zvysena hodnota prectenych bajtu - vzdy po volani readByte()
		tables->PAT.setSectionSyntaxIndicator(binaryShift(byteBuff,1,1)); //nacitani hlavicky tabulky PAT, metoda binaryShift() vraci cislo po bitovem posuvu, posuv je zavisly na vstupnich parametrech 
									
		tables->PAT.setPrivateFlag(binaryShift(byteBuff,2,2));
		tables->PAT.setSectionLength((binaryShift(byteBuff,5,8))*0x100+readByte());
		counterByte++;
		numberOfNotLoadedByte = tables->PAT.getSectionLength() - 4; //numberOfNotLoadedByte je postupne odecitana, jakmile je nula je tabulka nactena, -4 je zde protoze neni nacitan cyklicky soucet na konci CRC
									 

		if (tables->PAT.getSectionSyntaxIndicator())  //rozhodovani zda se jedna o dlouho nebo kratkou tabulku
		{
			tables->PAT.setTransportStreamID(readByte()*0x100+readByte());
			counterByte = counterByte+2;
			numberOfNotLoadedByte = numberOfNotLoadedByte-2;
			byteBuff = readByte();
			counterByte++;
			numberOfNotLoadedByte--;
			tables->PAT.setVersionNumb(binaryShift(byteBuff,3,7));
			tables->PAT.setCurrentIndicator(binaryShift(byteBuff,8,8));
			tables->PAT.setSectionNumb(readByte());
			counterByte++;
			numberOfNotLoadedByte--;
			tables->PAT.setLastSectionNumb(readByte());
			counterByte++;
			numberOfNotLoadedByte--;	//konec nacitani hlavicky tabulky PAT
		}
		if (tables->PAT.getSectionLength() > 176)	//pokut jsou data v tabulce delsi nez jeden paket TS - v pripade PAT vyhozena vyjimka
		{
			//pat je kratka takze vyhodi vyjimku
			throw TooLongTableException("Table PAT contain is too long data");
		}

		while (numberOfNotLoadedByte != 0)	//smycka nacitani tela tabulky, testovan numberOfNotLoadedByte na nulu
		{
			programNumbers.push_back(readByte()*0x100+readByte()); //nacitani cisel programu
			counterByte = counterByte+2;
			numberOfNotLoadedByte = numberOfNotLoadedByte-2;
			pmtPIDs.push_back(binaryShift(readByte(),4,8)*0x100+readByte()); //nacitani PID PMT tabulek
			counterByte = counterByte+2;
			numberOfNotLoadedByte = numberOfNotLoadedByte-2;
			if (counterByte > 188)	//kontrola zda nedoslo ke cteni mimo paket TS
			{
				throw ReadDataOutsideTsPacketException("Read data outside TS packet when loading PAT");
			}
		}
		if (numberOfNotLoadedByte < 0)	//kontrola zda nedoslo k behem smycky while k chybe a numberOfNotLoadedByte jiz neni zaporny
		{							                                                     
			throw BadInformationAboutLengthDataException("Bad information about length data when loading PAT");
		}
	}
	catch(TooLongTableException tLTex)	//odchytavani vyjimek
	{
		cerr << tLTex.what() << endl;
		return;
	}
	catch(ReadDataOutsideTsPacketException rdoTSpex)
	{
		cerr << rdoTSpex.what() << endl;
		return;
	}
	catch(BadInformationAboutLengthDataException bIALDex)
	{
		cerr << bIALDex.what() << endl;
		return;
	}
	//pocet programu - bez nit
	for (unsigned int m=0;m<programNumbers.size();m++)	//zjistovani poctu programu a filtrovani cisla programu 0 a PID 0x10 - NIT tabulka
	{
		if (programNumbers.at(m) != 0)
		{
			numberOfPrograms++;
			programNumbersWithoutNit.push_back(programNumbers.at(m));
			pmtPIDsWithoutNit.push_back(pmtPIDs.at(m));
		}
	}
	numberOfNotLoadedEitActualPService = numberOfPrograms; //nastaveni poctu programu pro nacitani jinych tabulek
	numberOfNotLoadedEitActualSService = numberOfPrograms;

	tables->PAT.setProgramNumbers(programNumbers);	//predani nactenych informaci do datoveho kontejneru
	tables->PAT.setProgramNumbersWithoutNit(programNumbersWithoutNit);
	tables->PAT.setPmtPIDsWithoutNit(pmtPIDsWithoutNit);
	tables->PAT.setPmtPIDs(pmtPIDs);
	
	patLoaded = true;	//nastaveni prizanku korektniho nacteni PAT tabulky
}

Závěr

Tento projekt se zabýval anylýzou dat v transportním toku DVB-T. Transportní tok byl získán z PC karty TechniSat AirStar 2. Ve vývojovém prostředí Visual Studio 2010 byl vytvořen program v jazyce C++ pro ovládání této karty a získání potřebných dat pro analýzu.
       Analýzou dat, tj. hledáním příslušných paketů a jejich skládáním jsou v programu zobrazeny příslušné servisní informace přenášené v transportním toku. Na obr. 5 je zobrazeno uživatelské rozhraní s elektronickým programovým průvodcem EPG. V uživatelském rozhraní lze také přepínat mezi jednotlivými televizními programy, které jsou vysílány v daném multiplexu.
       Tento projekt je součástí diplomové práce.


Soubory

Zdrojový kód projektu


Literatura

[1] ETSI EN 300 468 V1.7.1 Specification for Service Information (SI) in DVB Systems,Sophia Antipolis: ETSI, 2005.
[2] Proprietary and Confidential. B2C2 SDK Help. TechniSat - Software development kit.