Mercurial > pt1.oyama
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; }