diff recpt1/tssplitter_lite.c @ 100:aeba1988234f

support macros to specify sid: - macros: hd, sd1, sd2, sd3, 1seg and all are supported. - if sid has been specified but no suitable sid found, fall back to "all". technical summary: - use splitter structure as the argument where it is applicable. - add tab configuration to some source files.
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Sat, 13 Feb 2010 19:43:25 +0900
parents 3a3f15b063e1
children 3f7288b0672c
line wrap: on
line diff
--- a/recpt1/tssplitter_lite.c	Fri Feb 12 21:40:21 2010 +0900
+++ b/recpt1/tssplitter_lite.c	Sat Feb 13 19:43:25 2010 +0900
@@ -1,3 +1,4 @@
+/* -*- tab-width: 4; indent-tabs-mode: t -*- */
 /* tssplitter_lite.c -- split TS stream.
 
    Copyright 2009 querulous
@@ -28,13 +29,13 @@
 #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);
+static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf);
+static int AnalyzePat(splitter *sp, unsigned char *buf);
+static int RecreatePat(splitter *sp, unsigned char *buf, int *pos);
+static char** AnalyzeSid(char *sid);
+static int AnalyzePmt(splitter *sp, unsigned char *buf);
+static int GetCrc32(unsigned char *data, int len);
+static int GetPid(unsigned char *data);
 
 /**
  * サービスID解析
@@ -156,7 +157,7 @@
 		return NULL;
 	}
 	sp->pat_count	= 0xFF;
-	sp->pmt_remain = -1;
+	sp->pmt_retain = -1;
 	sp->pmt_counter = 0;
 
 	return sp;
@@ -172,7 +173,7 @@
 {
 	int result;
 	// TS解析
-	result = ReadTs(&(sp->pat), sp->pids, sp->sid_list, sp->pmt_pids, sbuf, &(sp->pmt_remain), &(sp->pmt_counter));
+	result = ReadTs(sp, sbuf);
 
 	return result;
 }
@@ -180,9 +181,7 @@
 /**
  * 終了処理
  */
-void split_shutdown(
-	splitter* sp
-)
+void split_shutdown(splitter* sp)
 {
 	if ( sp != NULL ) {
 		if ( sp->pat != NULL )
@@ -205,31 +204,30 @@
  *
  * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う
  */
-static int ReadTs(
-	unsigned char** pat,				// [out]	PAT 情報(再構築後)
+static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf)
+{
+#if 0
+	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_remain,						// [in]		PMTの落とすべき数
+	,			// [in]		pt1_drvの入力TS
+	int* pmt_retain,						// [in]		PMTの落とすべき数
 	int* pmt_counter					// [out]	PMTの落とした数
-)
-{
+#endif
+
 	int length = sbuf->size;
 	int pid;
 	int result = TSS_ERROR;
 	int index;
 
 	index = 0;
-	while (((length - index - LENGTH_PACKET)) > 0)
-	{
-		pid = GetPid(((unsigned char*)sbuf->data)+index+1);
+	while(length - index - LENGTH_PACKET > 0) {
+		pid = GetPid(sbuf->data + index + 1);
 		// PAT
-		if (0x0000 == pid)
-		{
-			result = AnalyzePat(((unsigned char*)sbuf->data)+index, pat, pids, sid_list, pmt_pids, pmt_remain);
-			if (TSS_SUCCESS != result)
-			{
+		if(0x0000 == pid) {
+			result = AnalyzePat(sp, sbuf->data + index);
+			if(TSS_SUCCESS != result) {
 				/* 下位の関数内部でmalloc error発生 */
 				return result;
 			}
@@ -238,18 +236,16 @@
 		// PMT
 		/* 残すpmt_pidである場合には、pmtに書かれている
 		 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */
-		if (pmt_pids[pid] == 1)
-		{
-//			fprintf(stderr, "\npmt_pid=%d\n", pid);
+		if(sp->pmt_pids[pid] == 1) {
 			/* この中にはPMT毎に一度しか入らないようにしておく */
-			AnalyzePmt(((unsigned char*)sbuf->data)+index, pids);
-			pmt_pids[pid]++;
-			*pmt_counter += 1;
+			AnalyzePmt(sp, sbuf->data + index);
+			sp->pmt_pids[pid]++;
+			sp->pmt_counter += 1;
 		}
 		/* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを
 		 * 得る */
-		/* pmt_counter と pmt_remain が一致する場合に条件は満たされる */
-		if ((*pmt_counter == *pmt_remain)) {
+		/* pmt_counter と pmt_retain が一致する場合に条件は満たされる */
+		if(sp->pmt_counter == sp->pmt_retain) {
 			result = TSS_SUCCESS;
 			break;
 		}
@@ -287,7 +283,7 @@
 
 	while(sbuf->size > s_offset) {
 		pid = GetPid(sptr + s_offset + 1);
-        switch(pid) {
+		switch(pid) {
 
 		// PAT
 		case 0x0000:
@@ -325,93 +321,177 @@
  *
  * PAT を解析し、出力対象チャンネルが含まれているかチェックを行い、PAT を再構築する
  */
-static int AnalyzePat(
+static int AnalyzePat(splitter *sp, unsigned char *buf)
+#if 0
 	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_remain
-)						// [out]	落とすPMTの数
+	int* pmt_retain						// [out]	残すPMTの数
+)
+#endif
 {
 	int pos[MAX_PID];
 	int service_id;
-	int i, j=0, k;
+	int i, j, k;
 	int size = 0;
 	int pid;
 	int result = TSS_SUCCESS;
 	char **p;
-	int sid_found;
+	int sid_found = FALSE;
 	int avail_sids[MAX_SERVICES];
 
-	if(*pat == NULL) {
+	unsigned char *pat = sp->pat;
+	unsigned char *pids = sp->pids;
+	char **sid_list = sp->sid_list;
+	unsigned char *pmt_pids = sp->pmt_pids;
+
+	char chosen_sid[512];
+	chosen_sid[0] = '\0';
+
+	if(pat == NULL) {
 		/* 初期化 */
-		*pmt_remain = 0;
+		sp->pmt_retain = 0;
 		memset(pos, 0, sizeof(pos));
 		size = buf[7];
 
+		/* prescan SID/PMT */
+		for(i = 17, j = 0; i < (size + 8) - 4; i = i + 4, j++) {
+			avail_sids[j] = (buf[i] << 8) + buf[i+1];
+			sp->avail_pmts[j] = GetPid(&buf[i+2]);
+		}
+		sp->num_pmts = j;
+
 		// 対象チャンネル判定
 		/* size + 8 = パケット全長 */
 		/* 最終 4 バイトはCRCなので飛ばす */
 		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;
+			service_id = (buf[i] << 8) + buf[i+1];
 			p = sid_list;
 
 			while(*p) {
 				if(service_id == atoi(*p)) {
-					/* 録画対象 = 落とす対象とはしないものなので、基本的に何もしない */
 					/* 録画対象の pmt_pids は 1 とする */
 					/* 録画対象の pmt の pids は 1 とする */
 					pid = GetPid(&buf[i + 2]);
 					*(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;
+					sid_found = TRUE;
+					sp->pmt_retain += 1;
+					sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
+					p++;
+					continue;
+				}
+				else if(!strcasecmp(*p, "hd") || !strcasecmp(*p, "sd1")) {
+					/* hd/sd1 指定時には1番目のサービスを保存する */
+					if(service_id == avail_sids[0]) {
+						pid = GetPid(&buf[i + 2]);
+						*(pmt_pids+pid) = 1;
+						*(pids+pid) = 1;
+						pos[pid] = i;
+						sid_found = TRUE;
+						sp->pmt_retain += 1;
+						sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
+					}
+					p++;
+					continue;
 				}
-				else if(strstr(*p, "all")) {
+				else if(!strcasecmp(*p, "sd2")) {
+					/* sd2 指定時には2番目のサービスを保存する */
+					if(service_id == avail_sids[1]) {
+						pid = GetPid(&buf[i + 2]);
+						*(pmt_pids+pid) = 1;
+						*(pids+pid) = 1;
+						pos[pid] = i;
+						sid_found = TRUE;
+						sp->pmt_retain += 1;
+						sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
+					}
+					p++;
+					continue;
+				}
+				else if(!strcasecmp(*p, "sd3")) {
+					/* sd3 指定時には3番目のサービスを保存する */
+					if(service_id == avail_sids[2]) {
+						pid = GetPid(&buf[i + 2]);
+						*(pmt_pids+pid) = 1;
+						*(pids+pid) = 1;
+						pos[pid] = i;
+						sid_found = TRUE;
+						sp->pmt_retain += 1;
+						sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
+					}
+					p++;
+					continue;
+				}
+				else if(!strcasecmp(*p, "1seg")) {
+					/* 1seg 指定時には PMTPID=0x1FC8 のサービスを保存する */
+					pid = GetPid(&buf[i + 2]);
+					if(pid == 0x1FC8) {
+						*(pmt_pids+pid) = 1;
+						*(pids+pid) = 1;
+						pos[pid] = i;
+						sid_found = TRUE;
+						sp->pmt_retain += 1;
+						sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
+					}
+					p++;
+					continue;
+				}
+				else if(!strcasecmp(*p, "all")) {
 					/* all指定時には全保存する */
 					pid = GetPid(&buf[i + 2]);
 					*(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);
+					sid_found = TRUE;
+					sp->pmt_retain += 1;
+					sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
 					break;
 				}
 
 				p++;
 			} /* while */
+		}
 
-			j++;
+		/* if sid has been specified but no sid found, fall back to all */
+		if(*sid_list && !sid_found) {
+			for(i = 17; i < (size + 8) - 4; i = i + 4) {
+				service_id = (buf[i] << 8) + buf[i+1];
+				pid = GetPid(&buf[i + 2]);
+				*(pmt_pids+pid) = 1;
+				*(pids+pid) = 1;
+				pos[pid] = i;
+				sid_found = TRUE;
+				sp->pmt_retain += 1;
+				sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id);
+			}
 		}
 
 		/* print SIDs */
 		fprintf(stderr, "Available sid = ");
-		for(k=0; k<j; k++)
+		for(k=0; k < sp->num_pmts; k++)
 			fprintf(stderr, "%d ", avail_sids[k]);
 		fprintf(stderr, "\n");
+		fprintf(stderr, "Chosen sid    =%s\n", chosen_sid);
 
-		fprintf(stderr, "Chosen sid    = ");
-		p = sid_list;
-		while(*p != NULL) {
-			fprintf(stderr, "%s ", *p);
-			p++;
-		}
+#if 0
+		/* print PMTs */
+		fprintf(stderr, "Available PMT = ");
+		for(k=0; k < sp->num_pmts; k++)
+			fprintf(stderr, "%d ", sp->avail_pmts[k]);
 		fprintf(stderr, "\n");
+#endif
 
 		// PAT 再構築
-		result = RecreatePat(buf, pat, pids, pos);
+		result = RecreatePat(sp, buf, pos);
 #if 0
 		int tc;
 		for(tc=0; tc<188; tc++)
-			fprintf(stderr, "%02x ", *(*pat+tc));
+			fprintf(stderr, "%02x ", *(pat+tc));
 #endif
 	}
 
@@ -423,11 +503,13 @@
  *
  * PMT から出力対象チャンネル以外のチャンネル情報を削除し、PAT を再構築する
  */
-static int RecreatePat(
+static int RecreatePat(splitter *sp, unsigned char *buf, int *pos)
+#if 0
 	unsigned char* buf,					// [in]		読み込んだバッファ
 	unsigned char** pat,				// [out]	PAT 情報(再構築後)
 	unsigned char* pids,				// [out]	出力対象 PID 情報
 	int *pos)							// [in]		取得対象 PMT のバッファ中の位置
+#endif
 {
 	unsigned char y[LENGTH_CRC_DATA];
 	int crc;
@@ -464,25 +546,26 @@
 	crc = GetCrc32(y, LENGTH_PAT_HEADER + pid_num*4);
 
 	// PAT 再構成
-	*pat = (unsigned char*)malloc(LENGTH_PACKET);
-	if ( *pat == NULL )
+	sp->pat = (unsigned char*)malloc(LENGTH_PACKET);
+	if(sp->pat == NULL)
 	{
 		fprintf(stderr, "RecreatePat() malloc error.\n");
 		return(TSS_NULL);
 	}
-	memset(*pat, 0xFF, LENGTH_PACKET);
+	memset(sp->pat, 0xFF, LENGTH_PACKET);
 	for (i = 0; i < 5; i++)
 	{
-		(*pat)[i] = buf[i];
+		(sp->pat)[i] = buf[i];
 	}
 	for (i = 0; i < LENGTH_PAT_HEADER + pid_num*4; i++)
 	{
-		(*pat)[i + 5] = y[i];
+		(sp->pat)[i + 5] = y[i];
 	}
-	(*pat)[5 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 24) & 0xFF;
-	(*pat)[6 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 16) & 0xFF;
-	(*pat)[7 + LENGTH_PAT_HEADER + pid_num*4] = (crc >>  8) & 0xFF;
-	(*pat)[8 + LENGTH_PAT_HEADER + pid_num*4] = (crc      ) & 0xFF;
+	(sp->pat)[5 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 24) & 0xFF;
+	(sp->pat)[6 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 16) & 0xFF;
+	(sp->pat)[7 + LENGTH_PAT_HEADER + pid_num*4] = (crc >>  8) & 0xFF;
+	(sp->pat)[8 + LENGTH_PAT_HEADER + pid_num*4] = (crc      ) & 0xFF;
+
 	return(TSS_SUCCESS);
 }
 
@@ -491,9 +574,11 @@
  *
  * PMT を解析し、保存対象の PID を特定する
  */
-static int AnalyzePmt(
+static int AnalyzePmt(splitter *sp, unsigned char *buf)
+#if 0
 	unsigned char* buf,					// [in]		読み込んだバッファ
 	unsigned char* pids)				// [out]	出力対象 PID 情報
+#endif
 {
 	unsigned char Nall;
 	unsigned char N;
@@ -504,8 +589,7 @@
 
 	// PCR
 	pcr = GetPid(&buf[13]);
-	pids[pcr] = 1;
-//    fprintf(stderr, "pcr_pid:%5d", pcr);
+	sp->pids[pcr] = 1;
 
 	N = ((buf[15] & 0x0F) << 4) + buf[16] + 16 + 1;
 
@@ -517,8 +601,7 @@
 		{
 			epid = GetPid(&buf[N + 1]);
 
-			pids[epid] = 1;
-//			fprintf(stderr, "%10d", epid);
+			sp->pids[epid] = 1;
 		}
 		N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1;
 	}