changeset 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
files recpt1/recpt1.c recpt1/tssplitter_lite.c recpt1/tssplitter_lite.h
diffstat 3 files changed, 164 insertions(+), 170 deletions(-) [+]
line wrap: on
line diff
--- a/recpt1/recpt1.c	Wed Feb 10 15:02:25 2010 +0900
+++ b/recpt1/recpt1.c	Fri Feb 12 21:40:21 2010 +0900
@@ -301,11 +301,15 @@
     pthread_t signal_thread = data->signal_thread;
     struct sockaddr_in *addr = NULL;
     BUFSZ *qbuf;
-    BUFSZ splitbuf;
+    splitbuf_t splitbuf;
     ARIB_STD_B25_BUFFER sbuf, dbuf, buf;
     int code;
     int split_select_finish = TSS_ERROR;
 
+    buf.size = 0;
+    buf.data = NULL;
+    splitbuf.size = 0;
+
     if(wfd == -1)
         fileless = TRUE;
 
@@ -328,47 +332,6 @@
 
         buf = sbuf; /* default */
 
-        if ( use_splitter )
-        {
-            /* $BJ,N%BP>](BPID$B$NCj=P(B */
-            if ( split_select_finish != TSS_SUCCESS )
-            {
-                split_select_finish = split_select(splitter, &sbuf);
-                if ( split_select_finish == TSS_NULL )
-                {
-                    /* malloc$B%(%i!<H/@8(B */
-                    use_splitter = FALSE;
-                }
-                else if ( split_select_finish != TSS_SUCCESS )
-                {
-                    /* $BJ,N%BP>](BPID$B$,40A4$KCj=P$G$-$k$^$G=PNO$7$J$$(B
-                     * 1$BICDxEYM>M5$r8+$k$H$$$$$+$b(B
-                     */
-                    free(qbuf);
-                    qbuf = NULL;
-                    continue;
-                }
-            }
-            /* $BJ,N%BP>]0J30$r$U$k$$Mn$H$9(B */
-            code = split_ts(splitter, &sbuf, &splitbuf);
-            if ( code != TSS_SUCCESS )
-            {
-                free(qbuf);
-                qbuf = NULL;
-                continue;
-            }
-            /* $BJ,N%7k2L$,%<%m%P%$%H$G$"$k>l9g$K$O(Bb25$B$K2s$5$J$$(B */
-            if ( splitbuf.size == 0 )
-            {
-                free(qbuf);
-                qbuf = NULL;
-                continue;
-            }
-            sbuf.data = splitbuf.buffer;
-            sbuf.size = splitbuf.size;
-            buf = sbuf;
-        }
-
         if(use_b25) {
             code = b25_decode(dec, &sbuf, &dbuf);
             if(code < 0) {
@@ -379,12 +342,52 @@
                 buf = dbuf;
         }
 
+
+        if(use_splitter) {
+            splitbuf.size = 0;
+
+            while(buf.size) {
+                /* $BJ,N%BP>](BPID$B$NCj=P(B */
+                if(split_select_finish != TSS_SUCCESS) {
+                    split_select_finish = split_select(splitter, &buf);
+                    if(split_select_finish == TSS_NULL) {
+                        /* malloc$B%(%i!<H/@8(B */
+                        fprintf(stderr, "split_select malloc failed\n");
+                        use_splitter = FALSE;
+                        goto fin;
+                    }
+                    else if(split_select_finish != TSS_SUCCESS) {
+                        /* $BJ,N%BP>](BPID$B$,40A4$KCj=P$G$-$k$^$G=PNO$7$J$$(B
+                         * 1$BICDxEYM>M5$r8+$k$H$$$$$+$b(B
+                         */
+                        break;
+                    }
+                }
+                /* $BJ,N%BP>]0J30$r$U$k$$Mn$H$9(B */
+                code = split_ts(splitter, &buf, &splitbuf);
+                if(code != TSS_SUCCESS) {
+                    fprintf(stderr, "split_ts failed\n");
+                    break;
+                }
+
+                break;
+            } /* while */
+
+            buf.size = splitbuf.size;
+            buf.data = splitbuf.buffer;
+        fin:
+            ;
+        } /* if */
+
+
         if(!fileless) {
             /* write data to output file */
             int size_remain = buf.size;
             int offset = 0;
+
             while(size_remain > 0) {
                 int ws = size_remain < SIZE_CHANK ? size_remain : SIZE_CHANK;
+
                 wc = write(wfd, buf.data + offset, ws);
                 if(wc < 0) {
                     perror("write");
@@ -415,34 +418,14 @@
             }
         }
 
-        if ( qbuf != NULL ) {
-            free(qbuf);
-            qbuf = NULL;
-        }
+        free(qbuf);
+        qbuf = NULL;
 
         /* normal exit */
         if((f_exit && !p_queue->num_used) || file_err) {
 
             buf = sbuf; /* default */
 
-            if ( use_splitter )
-            {
-                /* $BJ,N%BP>]0J30$r$U$k$$Mn$H$9(B */
-                code = split_ts(splitter, &sbuf, &splitbuf);
-                if ( code != TSS_SUCCESS )
-                {
-                    break;
-                }
-                /* $BJ,N%7k2L$,%<%m%P%$%H$G$"$k>l9g$K$O(Bb25$B$K2s$5$J$$(B */
-                if ( splitbuf.size == 0 )
-                {
-                    break;
-                }
-                sbuf.data = splitbuf.buffer;
-                sbuf.size = splitbuf.size;
-                buf = sbuf;
-            }
-
             if(use_b25) {
                 code = b25_finish(dec, &sbuf, &dbuf);
                 if(code < 0)
@@ -451,6 +434,17 @@
                     buf = dbuf;
             }
 
+            if(use_splitter) {
+                /* $BJ,N%BP>]0J30$r$U$k$$Mn$H$9(B */
+                code = split_ts(splitter, &buf, &splitbuf);
+                if(code != TSS_SUCCESS) {
+                    break;
+                }
+
+                buf.data = splitbuf.buffer;
+                buf.size = splitbuf.size;
+            }
+
             if(!fileless && !file_err) {
                 wc = write(wfd, buf.data, buf.size);
                 if(wc < 0) {
--- 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];
--- a/recpt1/tssplitter_lite.h	Wed Feb 10 15:02:25 2010 +0900
+++ b/recpt1/tssplitter_lite.h	Fri Feb 12 21:40:21 2010 +0900
@@ -17,18 +17,10 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifndef _TS_SPLITTER_LITE_H_
 #define _TS_SPLITTER_LITE_H_
-#if defined(WIN32)
-	#include <io.h>
-	#include <windows.h>
-	#include <crtdbg.h>
 
-	#pragma warning(disable: 4996)
-#else
-	#define __STDC_FORMAT_MACROS
-	#include <inttypes.h>
-	#include <unistd.h>
-//	#include "portable.h"
-#endif
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <unistd.h>
 
 #define LENGTH_PACKET		(188)
 #define MAX_PID				(8192)
@@ -52,21 +44,20 @@
 	unsigned char*	pat;
 	char**			sid_list;
 	unsigned char	pat_count;
-	int pmt_drop;
+	int pmt_remain;
 	int pmt_counter;
 } splitter;
 
-char** AnalyzeSid(char* sid);
+/* b25 decoder would hoard up large chank */
+typedef struct _splitbuf_t
+{
+    int size;
+    u_char buffer[1024*1024];
+} splitbuf_t;
+
 splitter* split_startup(char *sid);
 int split_select(splitter *sp, ARIB_STD_B25_BUFFER *sbuf);
-void split_shutdown( splitter* sp);
-int ReadTs( unsigned char** pat, unsigned char* pids, char** sid_list, unsigned char* pmt_pids, ARIB_STD_B25_BUFFER *sbuf, int* pmt_drop, int* pmt_counter);
-//int split_ts( unsigned char** pat, unsigned char* pids, ARIB_STD_B25_BUFFER *sbuf, BUFSZ *dbuf);
-int split_ts( splitter *splitter, ARIB_STD_B25_BUFFER *sbuf, BUFSZ *dbuf);
-int AnalyzePat(unsigned char* buf, unsigned char** pat, unsigned char* pids, char** sid_list, unsigned char* pmt_pids, int* pmt_drop);
-int RecreatePat(unsigned char* buf, unsigned char** pat, unsigned char* pids, int *pos);
-int AnalyzePmt(unsigned char* buf, unsigned char* pids);
+void split_shutdown(splitter *sp);
+int split_ts(splitter *splitter, ARIB_STD_B25_BUFFER *sbuf, splitbuf_t *dbuf);
 
-int GetCrc32(unsigned char* data, int len);
-int GetPid(unsigned char* data);
 #endif