Mercurial > pt1
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