diff recpt1/tssplitter_lite.c @ 99:3a3f15b063e1

now recpt1 accepts single sid for terrestrial channels. technical summary: - mark pid to record instead of pid to drop - split after decoding for now
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Fri, 12 Feb 2010 21:40:21 +0900
parents 3fd15032fd3a
children aeba1988234f
line wrap: on
line diff
--- a/recpt1/tssplitter_lite.c	Wed Feb 10 15:02:25 2010 +0900
+++ b/recpt1/tssplitter_lite.c	Fri Feb 12 21:40:21 2010 +0900
@@ -27,11 +27,19 @@
 #include "recpt1.h"
 #include "tssplitter_lite.h"
 
+/* prototypes */
+static char** AnalyzeSid(char* sid);
+static int ReadTs( unsigned char** pat, unsigned char* pids, char** sid_list, unsigned char* pmt_pids, ARIB_STD_B25_BUFFER *sbuf, int* pmt_remain, int* pmt_counter);
+static int AnalyzePat(unsigned char* buf, unsigned char** pat, unsigned char* pids, char** sid_list, unsigned char* pmt_pids, int* pmt_remain);
+static int RecreatePat(unsigned char* buf, unsigned char** pat, unsigned char* pids, int *pos);
+static int AnalyzePmt(unsigned char* buf, unsigned char* pids);
+static int GetCrc32(unsigned char* data, int len);
+static int GetPid(unsigned char* data);
 
 /**
  * サービスID解析
  */
-char** AnalyzeSid(
+static char** AnalyzeSid(
 	char* sid)						// [in]		サービスID(カンマ区切りテキスト)
 {
 	int i = 0;
@@ -148,7 +156,7 @@
 		return NULL;
 	}
 	sp->pat_count	= 0xFF;
-	sp->pmt_drop = -1;
+	sp->pmt_remain = -1;
 	sp->pmt_counter = 0;
 
 	return sp;
@@ -164,7 +172,7 @@
 {
 	int result;
 	// TS解析
-	result = ReadTs(&(sp->pat), sp->pids, sp->sid_list, sp->pmt_pids, sbuf, &(sp->pmt_drop), &(sp->pmt_counter));
+	result = ReadTs(&(sp->pat), sp->pids, sp->sid_list, sp->pmt_pids, sbuf, &(sp->pmt_remain), &(sp->pmt_counter));
 
 	return result;
 }
@@ -197,13 +205,13 @@
  *
  * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う
  */
-int ReadTs(
+static int ReadTs(
 	unsigned char** pat,				// [out]	PAT 情報(再構築後)
 	unsigned char* pids,				// [out]	出力対象 PID 情報
 	char** sid_list,					// [in]		出力対象サービス ID のリスト
 	unsigned char* pmt_pids,			// [in]		出力対象PIDのPMT PID
 	ARIB_STD_B25_BUFFER *sbuf,			// [in]		pt1_drvの入力TS
-	int* pmt_drop,						// [in]		PMTの落とすべき数
+	int* pmt_remain,						// [in]		PMTの落とすべき数
 	int* pmt_counter					// [out]	PMTの落とした数
 )
 {
@@ -219,7 +227,7 @@
 		// PAT
 		if (0x0000 == pid)
 		{
-			result = AnalyzePat(((unsigned char*)sbuf->data)+index, pat, pids, sid_list, pmt_pids, pmt_drop);
+			result = AnalyzePat(((unsigned char*)sbuf->data)+index, pat, pids, sid_list, pmt_pids, pmt_remain);
 			if (TSS_SUCCESS != result)
 			{
 				/* 下位の関数内部でmalloc error発生 */
@@ -228,23 +236,24 @@
 		}
 
 		// PMT
-		/* 落とすpmt_pidである場合には、pmtに書かれている
-		 * 落とすべきPCR/AUDIO/VIDEO PIDを取得する */
+		/* 残すpmt_pidである場合には、pmtに書かれている
+		 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */
 		if (pmt_pids[pid] == 1)
 		{
+//			fprintf(stderr, "\npmt_pid=%d\n", pid);
 			/* この中にはPMT毎に一度しか入らないようにしておく */
 			AnalyzePmt(((unsigned char*)sbuf->data)+index, pids);
 			pmt_pids[pid]++;
-			*pmt_counter = *(pmt_counter)+1;
+			*pmt_counter += 1;
 		}
-		/* 全ての落とすPMTの中に書かれている、落とすPCR/AUDIO/VIDEOのPIDを得たら処理を抜ける */
-		/* pmt_counter と pmt_drop が一致する場合に条件は満たされる */
-		if ((*pmt_counter == *pmt_drop)) {
+		/* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを
+		 * 得る */
+		/* pmt_counter と pmt_remain が一致する場合に条件は満たされる */
+		if ((*pmt_counter == *pmt_remain)) {
 			result = TSS_SUCCESS;
 			break;
 		}
-		else
-		{
+		else {
 			result = TSS_ERROR;
 		}
 		index += LENGTH_PACKET;
@@ -259,58 +268,53 @@
 int split_ts(
 	splitter *splitter,					// [in]		splitterパラメータ
 	ARIB_STD_B25_BUFFER *sbuf,			// [in]		入力TS
-	BUFSZ *dbuf							// [out]	出力TS
+	splitbuf_t *dbuf							// [out]	出力TS
 )
 {
 	int pid;
+	unsigned char *sptr, *dptr;
 	int s_offset = 0;
 	int d_offset = 0;
 
 	/* 初期化 */
 	dbuf->size = 0;
-	if ( sbuf->size < 0 )
-	{
+	if (sbuf->size < 0) {
 		return TSS_ERROR;
 	}
 
-	while (sbuf->size > s_offset)
-	{
-		pid = GetPid(((unsigned char*)sbuf->data)+s_offset+1);
+	sptr = sbuf->data;
+	dptr = dbuf->buffer;
+
+	while(sbuf->size > s_offset) {
+		pid = GetPid(sptr + s_offset + 1);
+        switch(pid) {
 
 		// PAT
-		if (0x0000 == pid)
-		{
+		case 0x0000:
 			// 巡回カウンタカウントアップ
-			if (0xFF == splitter->pat_count)
-			{
+			if(0xFF == splitter->pat_count) {
 				splitter->pat_count = splitter->pat[3];
-			} else
-			{
-				splitter->pat_count = (splitter->pat_count)+1;
-				if (0 == splitter->pat_count % 0x10)
-				{
-					splitter->pat_count = splitter->pat_count - 0x10;
-				}
+			}
+			else {
+				splitter->pat_count = (splitter->pat_count + 1) % 16;
 			}
 			splitter->pat[3] = splitter->pat_count;
 
-			memcpy(((unsigned char*)dbuf->buffer)+d_offset, splitter->pat, LENGTH_PACKET);
+			memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET);
 			d_offset += LENGTH_PACKET;
-			dbuf->size = dbuf->size + LENGTH_PACKET;
-		}
+			dbuf->size += LENGTH_PACKET;
+			break;
+		default:
+			/* pids[pid] が 1 は残すパケットなので書き込む */
+			if(1 == splitter->pids[pid]) {
+				memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET);
+				d_offset += LENGTH_PACKET;
+				dbuf->size += LENGTH_PACKET;
+			}
+			break;
+		} /* switch */
 
-		// その他 PID
-		else
-		{
-			/* pids[pid] が 0 は落とさないパケットなので書き込む */
-			if (0 == splitter->pids[pid])
-			{
-				memcpy(((unsigned char*)dbuf->buffer)+d_offset, ((unsigned char*)sbuf->data)+s_offset, LENGTH_PACKET);
-				d_offset += LENGTH_PACKET;
-				dbuf->size = dbuf->size + LENGTH_PACKET;
-			}
-		}
-		s_offset = s_offset + LENGTH_PACKET;
+		s_offset += LENGTH_PACKET;
 	}
 
 	return(TSS_SUCCESS);
@@ -321,13 +325,13 @@
  *
  * PAT を解析し、出力対象チャンネルが含まれているかチェックを行い、PAT を再構築する
  */
-int AnalyzePat(
+static int AnalyzePat(
 	unsigned char* buf,					// [in]		読み込んだバッファ
 	unsigned char** pat,				// [out]	PAT 情報(再構築後)
 	unsigned char* pids,				// [out]	出力対象 PID 情報
 	char** sid_list,					// [in]		出力対象サービス ID のリスト
 	unsigned char* pmt_pids,			// [out]	サービス ID に対応する PMT の PID
-	int* pmt_drop
+	int* pmt_remain
 )						// [out]	落とすPMTの数
 {
 	int pos[MAX_PID];
@@ -340,61 +344,55 @@
 	int sid_found;
 	int avail_sids[MAX_SERVICES];
 
-	if (NULL == *pat)
-	{
+	if(*pat == NULL) {
 		/* 初期化 */
-		*pmt_drop = 0;
+		*pmt_remain = 0;
 		memset(pos, 0, sizeof(pos));
 		size = buf[7];
 
 		// 対象チャンネル判定
 		/* size + 8 = パケット全長 */
 		/* 最終 4 バイトはCRCなので飛ばす */
-		for (i = 17; i < (size + 8) - 4; i = i + 4)
-		{
+		for(i = 17; i < (size + 8) - 4; i = i + 4) {
+
 			sid_found = 0;
 			service_id = (buf[i] << 8) + buf[i + 1];
 			avail_sids[j] = service_id;
 			p = sid_list;
-			while(*p != NULL)
-			{
-				if (service_id == atoi(*p))
-				{
+
+			while(*p) {
+				if(service_id == atoi(*p)) {
 					/* 録画対象 = 落とす対象とはしないものなので、基本的に何もしない */
-					/* 録画対象の pmt_pids は 0 とする */
-					/* 録画対象の pmt の pids は 0 とする */
+					/* 録画対象の pmt_pids は 1 とする */
+					/* 録画対象の pmt の pids は 1 とする */
 					pid = GetPid(&buf[i + 2]);
-					*(pmt_pids+pid) = 0;
-					*(pids+pid) = 0;
+					*(pmt_pids+pid) = 1;
+					*(pids+pid) = 1;
 					pos[pid] = i;
 					sid_found = 1;
+					*pmt_remain += 1;
+//					fprintf(stderr, "sid=%d pid=%d\n", service_id, pid);
 					break;
 				}
-				else if (strstr(*p, "all") != NULL )
-				{
+				else if(strstr(*p, "all")) {
 					/* all指定時には全保存する */
 					pid = GetPid(&buf[i + 2]);
-					*(pmt_pids+pid) = 0;
-					*(pids+pid) = 0;
+					*(pmt_pids+pid) = 1;
+					*(pids+pid) = 1;
 					pos[pid] = i;
 					sid_found = 1;
+					*pmt_remain += 1;
+//					fprintf(stderr, "sid=%d pid=%d\n", service_id, pid);
 					break;
 				}
+
 				p++;
-			}
-			if ( ! sid_found )
-			{
-				/* sid_list を全部なめたが録画対象であると判定されないものを落とす */
-				/* 削除対象の pmt_pids は 1 とする */
-				/* 削除対象の pmt の pids は 1 とする */
-				pid = GetPid(&buf[i + 2]);
-				*(pmt_pids+pid) = 1;
-				*(pids+pid) = 1;
-				pos[pid] = i;
-				*(pmt_drop) = *(pmt_drop)+1;
-			}
+			} /* while */
+
 			j++;
 		}
+
+		/* print SIDs */
 		fprintf(stderr, "Available sid = ");
 		for(k=0; k<j; k++)
 			fprintf(stderr, "%d ", avail_sids[k]);
@@ -410,6 +408,11 @@
 
 		// PAT 再構築
 		result = RecreatePat(buf, pat, pids, pos);
+#if 0
+		int tc;
+		for(tc=0; tc<188; tc++)
+			fprintf(stderr, "%02x ", *(*pat+tc));
+#endif
 	}
 
 	return(result);
@@ -420,7 +423,7 @@
  *
  * PMT から出力対象チャンネル以外のチャンネル情報を削除し、PAT を再構築する
  */
-int RecreatePat(
+static int RecreatePat(
 	unsigned char* buf,					// [in]		読み込んだバッファ
 	unsigned char** pat,				// [out]	PAT 情報(再構築後)
 	unsigned char* pids,				// [out]	出力対象 PID 情報
@@ -486,9 +489,9 @@
 /**
  * PMT 解析処理
  *
- * PMT を解析し、削除対象の PID を特定する
+ * PMT を解析し、保存対象の PID を特定する
  */
-int AnalyzePmt(
+static int AnalyzePmt(
 	unsigned char* buf,					// [in]		読み込んだバッファ
 	unsigned char* pids)				// [out]	出力対象 PID 情報
 {
@@ -502,15 +505,21 @@
 	// PCR
 	pcr = GetPid(&buf[13]);
 	pids[pcr] = 1;
+//    fprintf(stderr, "pcr_pid:%5d", pcr);
 
 	N = ((buf[15] & 0x0F) << 4) + buf[16] + 16 + 1;
 
 	// ES PID
 	while (N < Nall + 8 - 4)
 	{
-		epid = GetPid(&buf[N + 1]);
+		// ストリーム種別が 0x0D(type D)は出力対象外
+		if (0x0D != buf[N])
+		{
+			epid = GetPid(&buf[N + 1]);
 
-		pids[epid] = 1;
+			pids[epid] = 1;
+//			fprintf(stderr, "%10d", epid);
+		}
 		N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1;
 	}
 
@@ -520,7 +529,7 @@
 /**
  * CRC 計算
  */
-int GetCrc32(
+static int GetCrc32(
 	unsigned char* data,				// [in]		CRC 計算対象データ
 	int len)							// [in]		CRC 計算対象データ長
 {
@@ -563,7 +572,7 @@
 /**
  * PID 取得
  */
-int GetPid(
+static int GetPid(
 	unsigned char* data)				// [in]		取得対象データのポインタ
 {
 	return ((data[0] & 0x1F) << 8) + data[1];