#!/Perl/bin/perl
# TSファイル中のエレメンタリPIDとストリーム形式種別を適当に出力してみるテスト
# TOTも適当に出力してみる
# 地デジのEIT(!=0x0012)のイベント識別と継続時間も適当に出力してみる
# 放送中と思われる地デジ番組のEITを適当に表示してみる

binmode(STDIN);
binmode(STDOUT);

%stream_id_table=(
0x01, "ISO/IEC 11172-2映像",
0x02, "ITU-T勧告H.262|ISO/IEC 13818-2映像またはISO/IEC 11172-2制約パラメータ映像ストリーム",
0x03, "ISO/IEC 11172-3音声",
0x04, "ISO/IEC 13818-3音声",
0x05, "ITU-T勧告H.222.0|ISO/IEC 13818-1プライベートセクション",
0x06, "プライベートデータを収容したITU-T勧告H.222.0|ISO/IEC 13818-1 PESパケット",
0x07, "ISO/IEC 13522 MHEG",
0x08, "ITU-T勧告H.222.0|ISO/IEC 13818-1付属書A DSM-CC",
0x09, "ITU-T勧告H.222.1",
0x0A, "ISO/IEC 13818-6（タイプA）",
0x0B, "ISO/IEC 13818-6（タイプB）",
0x0C, "ISO/IEC 13818-6（タイプC）",
0x0D, "ISO/IEC 13818-6（タイプD）",
0x0E, "上記勧告以外でITU-T勧告H.222.0|ISO/IEC 13818-1で規定されるデータタイプ",
0x0F, "ISO/IEC 13818-7音声（ADTSトランスポート構\造）",
0x10, "ISO/IEC 14496-2 映像",
0x11, "ISO/IEC 14496-3 音声（ISO/IEC 14496-3 / AMD 1で規定されるLATM トランスポート構\造）",
0x12, "PES パケットで伝送されるISO/IEC 14496-1 SL パケット化ストリーム又はフレックスマックスストリーム",
0x13, "ISO/IEC 14496 セクションで伝送されるISO/IEC14496-1 SL パケット化ストリーム又はフレックスマックスストリーム",
0x14, "ISO/IEC 13818-6 同期ダウンロードプロトコル",
0x15, "PES パケットで伝送されるメタデータ",
0x16, "メタデータセクションで伝送されるメタデータ",
0x17, "ISO/IEC 13818-6 データカルーセルで伝送されるメタデータ",
0x18, "ISO/IEC 13818-6 オブジェクトカルーセルで伝送されるメタデータ",
0x19, "ISO/IEC 13818-6 同期ダウンロードプロトコルで伝送されるメタデータ",
0x1A, "IPMP ストリーム（ISO/IEC 13818-11 で規定されるMPEG-2 IPMP）",
0x1B, "ITU-T 勧告H.264|ISO/IEC 14496-10 映像で規定されるAVC 映像ストリーム",
0x1C, "ISO/IEC 14496-3 音声（DST、ALS、SLS など何ら追加のトランスポート構\造を使用しないもの）",
0x1D, "ISO/IEC 14496-17 テキスト",
0x1E, "ISO/IEC 23002-3 で規定される補助映像ストリーム",
0x1F, "ITU-T 勧告H.264|ISO/IEC 14496-10 映像の付録Gで規定される一つ以上のプロファイルに準拠するAVC 映像ストリームのSVC 映像サブビットストリーム",
0x20, "ITU-T 勧告H.264|ISO/IEC 14496-10 映像の付録Hで規定される一つ以上のプロファイルに準拠するAVC 映像ストリームのMVC 映像サブビットストリーム",
0x7F, "IPMPストリーム"
);

$lenght = 0;
$phase  = 0;
$prior_pid = 0xffff;
while(not eof(STDIN)){

	read(STDIN, $ts_data, 188);
	$lenght += 188;

	$pid = hex(unpack("H*", substr($ts_data, 1, 2))) & 0x1FFF;

	if ($prior_pid == $pid) {
#		printf STDOUT ".";
	} else {
#		printf STDOUT "\nphase=%d PID=0x%04.4x\n", $phase, $pid;
	}
	$prior_pid = $pid;

	if         ($phase == 0) {
		#PAT RECORD
		if ($pid == 0x0000) {

			$phase = 1;

			$section_len = hex(unpack("H*", substr($ts_data, 6, 2))) & 0x0FFF;
#			printf STDOUT "LEN=%d ", $section_len;
			$pmt_count = ($section_len - 5 - 4) / 4;
#			printf STDOUT "COUNT=%d ", $pmt_count;

			$program_cnt = 0;
			for ($i = 0; $i < $pmt_count; $i++) {
#				printf STDOUT "(ID=0x%s) ", unpack("H*", substr($ts_data, 4 + 9 + $i * 4, 2));
				$id = hex(unpack("H*", substr($ts_data, 4 + 9 + $i * 4, 2))) & 0x1FFF;
				next if ($id == 0x0000);
				$pmt_id[$program_cnt++] =
					hex(unpack("H*", substr($ts_data, 4 + 9 + $i * 4 + 2, 2))) & 0x1FFF;
				printf STDOUT "PMT ID=0x%04.4x ", $pmt_id[$program_cnt - 1];
			}
			printf STDOUT "\n";
		}

	} elsif  ($phase == 1) {
		#PMT RECORD
		if ($pid == $pmt_id[0]) {

			$phase = 2;

			$section_len = hex(unpack("H*", substr($ts_data, 6, 2))) & 0x0FFF;
#			printf STDOUT "LEN=%d ", $section_len;

			$start_point = 4 + 8;
			while($next_point < $section_len) {
#				printf STDOUT "start_point=%03.3d ", $start_point;

				$temp = hex(unpack("H*", substr($ts_data, $start_point, 4)));
#				printf STDOUT "start_point_data=0x%08.8x ", $temp;

				$stream_id = hex(unpack("H*", substr($ts_data, $start_point, 1)));
#				printf STDOUT "STREAM_ID=0x%02.2x ", $stream_id;

#				$program_id = hex(unpack("H*", substr($ts_data, $start_point + 1, 2)));
#				printf STDOUT "PROGRAM_ID=0x%04.4x ", $program_id;

				$program_id = hex(unpack("H*", substr($ts_data, $start_point + 1, 2))) & 0x1FFF;
#				printf STDOUT "PROGRAM_ID=0x%04.4x ", $program_id;

				$program_len = hex(unpack("H*", substr($ts_data, $start_point + 3, 2))) & 0x0FFF;
#				printf STDOUT "PROGRAM_LEN=%04.4d ", $program_len;

				$next_point = $start_point + 3 + 2 + $program_len; 
#				$temp = hex(unpack("H*", substr($ts_data, $next_point, 4)));
#				printf STDOUT "next_point_data=0x%08.8x ", $temp;

				if ($stream_id != 0x00) {
					printf STDOUT "STREAM_ID=0x%02.2x PROGRAM ID=0x%04.4x %s\n", 
						$stream_id, $program_id, $stream_id_table{$stream_id};
				}
				$start_point = $next_point;
			}
		}

	} elsif  ($phase == 2) {
		#TOT RECORD
		if ($pid == 0x0014) {

			$phase = 3;
#			printf STDOUT "TOT_RECORD\n";
			$now_date_time =
				&conv_date_time(substr($ts_data, 4 + 1 + 3, 2), substr($ts_data, 4 + 1 + 3 + 2, 3));
			printf STDOUT "NOW_DATE_TIME=%s\n", $now_date_time;
		}

	} elsif  (($phase == 3) || ($phase == 4)) {
		#EIT RECORD
#		if (($pid == 0x0012) || ($pid == 0x0026) || ($pid == 0x0027) ) {
		if (                    ($pid == 0x0026) || ($pid == 0x0027) ) {

#			printf STDOUT "lenght=0x%08.8x\n", $lenght - 188;

			$phase = 4;
#			printf STDOUT "EIT_RECORD=%04.4x\n", $pid;

			if (hex(unpack("H*", substr($ts_data, 4, 1))) != 0x00) {
#				printf STDOUT "not support SKIP =%02.2x\n",  hex(unpack("H*", substr($ts_data, 4, 1)));
				next;
			}

			$section_len = hex(unpack("H*", substr($ts_data, 4 + 1 + 1, 2))) & 0x0FFF;
#			printf STDOUT "LEN=%d ", $section_len;

			$event_id = hex(unpack("H*", substr($ts_data, 4 + 1 + 1 + 2 + 2 + 1 + 1 + 1 + 2 + 2 + 1 + 1 , 2)));
#			printf STDOUT "EVENT_ID=%04.4x ", $event_id;

			$event_date_time = 
				&conv_date_time(substr($ts_data, 4 + 1 + 1 + 2 + 2 + 1 + 1 + 1 + 2 + 2 + 1 + 1 + 2, 2),
						substr($ts_data, 4 + 1 + 1 + 2 + 2 + 1 + 1 + 1 + 2 + 2 + 1 + 1 + 2 + 2, 3));
#			printf STDOUT "EVENT_DATE_TIME=%s ", $event_date_time;

			$event_duration =
				unpack("H*",
					substr($ts_data, 4 + 1 + 1 + 2 + 2 + 1 + 1 + 1 + 2 + 2 + 1 + 1 + 2 + 2 + 3, 3));
#			printf STDOUT "EVENT_DURATION=%s\n", $event_duration;

			if (check_on_air($now_date_time, $event_date_time, $event_duration) != 0) {
				printf STDOUT "EIT_RECORD=%04.4x\n", $pid;
				printf STDOUT "LEN=%d EVENT_ID=%04.4x EVENT_DATE_TIME=%s EVENT_DURATION=%s\n",
					$section_len, $event_id, $event_date_time, $event_duration;
				last;
			}

		} elsif ($pid == 0x0012) {
#			printf STDOUT "not support PID=%04.4x\n", $pid;
		}
	}
}

close(STDIN);
close(STDOUT);

exit;

use Time::Local;

sub check_on_air {

	local($now_date_time, $event_date_time, $event_duration) = @_;
	local($now_time, $event_start_time, $event_end_time);

	$now_time = timelocal(substr($now_date_time, 12, 2) + 0, substr($now_date_time, 10, 2) + 0,
		substr($now_date_time,  8, 2) + 0, substr($now_date_time,  6, 2) + 0,
		substr($now_date_time,  4, 2) + 0 - 1, (substr($now_date_time,  0, 4) + 0 - 1900));

	$event_start_time = timelocal(substr($event_date_time, 12, 2) + 0, substr($event_date_time, 10, 2) + 0,
		substr($event_date_time,  8, 2) + 0, substr($event_date_time,  6, 2) + 0,
		substr($event_date_time,  4, 2) + 0 - 1, (substr($event_date_time,  0, 4) + 0 - 1900));

	$event_end_time =  $event_start_time +
		((substr($event_duration, 0, 2) + 0) * 60 * 60) +
		((substr($event_duration, 2, 2) + 0) * 60) +
		 (substr($event_duration, 4, 2) + 0);

#	printf "%d %d %d", $now_time, $event_start_time, $event_end_time;
	if (($event_start_time <= $now_time) && ($now_time < $event_end_time)) {
		return(1);
	} else {
		return(0);
	}
}

sub conv_date_time {

	local($mjd_data, $jst_data);
	local($y_, $m_, $d, $y, $m, $k, $date_time);


	$mjd_data = hex(unpack("H*", $_[0]));
	$jst_data = unpack("H*", $_[1]);

	$y_ = int(($mjd_data - 15078.2) / 365.25);
	$m_ = int(($mjd_data - 14956.1 - int ($y_ * 365.25)) / 30.6001);
	$d  = $mjd_data - 14956 - int ($y_ * 365.25) - int ($m_ * 30.6001);
	if (($m_ == 14) || ($m_ == 15)) {
		$k = 1;
	} else {
		$k = 0;
	}
	$y  = $y_ + $k;
	$m  = $m_ - 1 - $k * 12;

	$date_time = sprintf("%4.4d%02.2d%02.2d%s", 1900 + $y, $m, $d, $jst_data);
#	printf STDOUT "(func)DATE_TIME=%s\n", $date_time;
#	printf STDOUT "YMD=%4.4d%02.2d%02.2d ", 1900 + $y, $m, $d;

	return($date_time);
}

# end of file
