comparison 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
comparison
equal deleted inserted replaced
98:3fd15032fd3a 99:3a3f15b063e1
25 #include <sys/stat.h> 25 #include <sys/stat.h>
26 #include "decoder.h" 26 #include "decoder.h"
27 #include "recpt1.h" 27 #include "recpt1.h"
28 #include "tssplitter_lite.h" 28 #include "tssplitter_lite.h"
29 29
30 /* prototypes */
31 static char** AnalyzeSid(char* sid);
32 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);
33 static int AnalyzePat(unsigned char* buf, unsigned char** pat, unsigned char* pids, char** sid_list, unsigned char* pmt_pids, int* pmt_remain);
34 static int RecreatePat(unsigned char* buf, unsigned char** pat, unsigned char* pids, int *pos);
35 static int AnalyzePmt(unsigned char* buf, unsigned char* pids);
36 static int GetCrc32(unsigned char* data, int len);
37 static int GetPid(unsigned char* data);
30 38
31 /** 39 /**
32 * サービスID解析 40 * サービスID解析
33 */ 41 */
34 char** AnalyzeSid( 42 static char** AnalyzeSid(
35 char* sid) // [in] サービスID(カンマ区切りテキスト) 43 char* sid) // [in] サービスID(カンマ区切りテキスト)
36 { 44 {
37 int i = 0; 45 int i = 0;
38 char** sid_list = NULL; 46 char** sid_list = NULL;
39 char* p; 47 char* p;
146 { 154 {
147 free(sp); 155 free(sp);
148 return NULL; 156 return NULL;
149 } 157 }
150 sp->pat_count = 0xFF; 158 sp->pat_count = 0xFF;
151 sp->pmt_drop = -1; 159 sp->pmt_remain = -1;
152 sp->pmt_counter = 0; 160 sp->pmt_counter = 0;
153 161
154 return sp; 162 return sp;
155 } 163 }
156 164
162 ARIB_STD_B25_BUFFER *sbuf // [in] 入力TS 170 ARIB_STD_B25_BUFFER *sbuf // [in] 入力TS
163 ) 171 )
164 { 172 {
165 int result; 173 int result;
166 // TS解析 174 // TS解析
167 result = ReadTs(&(sp->pat), sp->pids, sp->sid_list, sp->pmt_pids, sbuf, &(sp->pmt_drop), &(sp->pmt_counter)); 175 result = ReadTs(&(sp->pat), sp->pids, sp->sid_list, sp->pmt_pids, sbuf, &(sp->pmt_remain), &(sp->pmt_counter));
168 176
169 return result; 177 return result;
170 } 178 }
171 179
172 /** 180 /**
195 /** 203 /**
196 * TS 解析処理 204 * TS 解析処理
197 * 205 *
198 * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う 206 * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う
199 */ 207 */
200 int ReadTs( 208 static int ReadTs(
201 unsigned char** pat, // [out] PAT 情報(再構築後) 209 unsigned char** pat, // [out] PAT 情報(再構築後)
202 unsigned char* pids, // [out] 出力対象 PID 情報 210 unsigned char* pids, // [out] 出力対象 PID 情報
203 char** sid_list, // [in] 出力対象サービス ID のリスト 211 char** sid_list, // [in] 出力対象サービス ID のリスト
204 unsigned char* pmt_pids, // [in] 出力対象PIDのPMT PID 212 unsigned char* pmt_pids, // [in] 出力対象PIDのPMT PID
205 ARIB_STD_B25_BUFFER *sbuf, // [in] pt1_drvの入力TS 213 ARIB_STD_B25_BUFFER *sbuf, // [in] pt1_drvの入力TS
206 int* pmt_drop, // [in] PMTの落とすべき数 214 int* pmt_remain, // [in] PMTの落とすべき数
207 int* pmt_counter // [out] PMTの落とした数 215 int* pmt_counter // [out] PMTの落とした数
208 ) 216 )
209 { 217 {
210 int length = sbuf->size; 218 int length = sbuf->size;
211 int pid; 219 int pid;
217 { 225 {
218 pid = GetPid(((unsigned char*)sbuf->data)+index+1); 226 pid = GetPid(((unsigned char*)sbuf->data)+index+1);
219 // PAT 227 // PAT
220 if (0x0000 == pid) 228 if (0x0000 == pid)
221 { 229 {
222 result = AnalyzePat(((unsigned char*)sbuf->data)+index, pat, pids, sid_list, pmt_pids, pmt_drop); 230 result = AnalyzePat(((unsigned char*)sbuf->data)+index, pat, pids, sid_list, pmt_pids, pmt_remain);
223 if (TSS_SUCCESS != result) 231 if (TSS_SUCCESS != result)
224 { 232 {
225 /* 下位の関数内部でmalloc error発生 */ 233 /* 下位の関数内部でmalloc error発生 */
226 return result; 234 return result;
227 } 235 }
228 } 236 }
229 237
230 // PMT 238 // PMT
231 /* 落とすpmt_pidである場合には、pmtに書かれている 239 /* 残すpmt_pidである場合には、pmtに書かれている
232 * 落とすべきPCR/AUDIO/VIDEO PIDを取得する */ 240 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */
233 if (pmt_pids[pid] == 1) 241 if (pmt_pids[pid] == 1)
234 { 242 {
243 // fprintf(stderr, "\npmt_pid=%d\n", pid);
235 /* この中にはPMT毎に一度しか入らないようにしておく */ 244 /* この中にはPMT毎に一度しか入らないようにしておく */
236 AnalyzePmt(((unsigned char*)sbuf->data)+index, pids); 245 AnalyzePmt(((unsigned char*)sbuf->data)+index, pids);
237 pmt_pids[pid]++; 246 pmt_pids[pid]++;
238 *pmt_counter = *(pmt_counter)+1; 247 *pmt_counter += 1;
239 } 248 }
240 /* 全ての落とすPMTの中に書かれている、落とすPCR/AUDIO/VIDEOのPIDを得たら処理を抜ける */ 249 /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを
241 /* pmt_counter と pmt_drop が一致する場合に条件は満たされる */ 250 * 得る */
242 if ((*pmt_counter == *pmt_drop)) { 251 /* pmt_counter と pmt_remain が一致する場合に条件は満たされる */
252 if ((*pmt_counter == *pmt_remain)) {
243 result = TSS_SUCCESS; 253 result = TSS_SUCCESS;
244 break; 254 break;
245 } 255 }
246 else 256 else {
247 {
248 result = TSS_ERROR; 257 result = TSS_ERROR;
249 } 258 }
250 index += LENGTH_PACKET; 259 index += LENGTH_PACKET;
251 } 260 }
252 261
257 * TS 分離処理 266 * TS 分離処理
258 */ 267 */
259 int split_ts( 268 int split_ts(
260 splitter *splitter, // [in] splitterパラメータ 269 splitter *splitter, // [in] splitterパラメータ
261 ARIB_STD_B25_BUFFER *sbuf, // [in] 入力TS 270 ARIB_STD_B25_BUFFER *sbuf, // [in] 入力TS
262 BUFSZ *dbuf // [out] 出力TS 271 splitbuf_t *dbuf // [out] 出力TS
263 ) 272 )
264 { 273 {
265 int pid; 274 int pid;
275 unsigned char *sptr, *dptr;
266 int s_offset = 0; 276 int s_offset = 0;
267 int d_offset = 0; 277 int d_offset = 0;
268 278
269 /* 初期化 */ 279 /* 初期化 */
270 dbuf->size = 0; 280 dbuf->size = 0;
271 if ( sbuf->size < 0 ) 281 if (sbuf->size < 0) {
272 {
273 return TSS_ERROR; 282 return TSS_ERROR;
274 } 283 }
275 284
276 while (sbuf->size > s_offset) 285 sptr = sbuf->data;
277 { 286 dptr = dbuf->buffer;
278 pid = GetPid(((unsigned char*)sbuf->data)+s_offset+1); 287
288 while(sbuf->size > s_offset) {
289 pid = GetPid(sptr + s_offset + 1);
290 switch(pid) {
279 291
280 // PAT 292 // PAT
281 if (0x0000 == pid) 293 case 0x0000:
282 {
283 // 巡回カウンタカウントアップ 294 // 巡回カウンタカウントアップ
284 if (0xFF == splitter->pat_count) 295 if(0xFF == splitter->pat_count) {
285 {
286 splitter->pat_count = splitter->pat[3]; 296 splitter->pat_count = splitter->pat[3];
287 } else 297 }
288 { 298 else {
289 splitter->pat_count = (splitter->pat_count)+1; 299 splitter->pat_count = (splitter->pat_count + 1) % 16;
290 if (0 == splitter->pat_count % 0x10)
291 {
292 splitter->pat_count = splitter->pat_count - 0x10;
293 }
294 } 300 }
295 splitter->pat[3] = splitter->pat_count; 301 splitter->pat[3] = splitter->pat_count;
296 302
297 memcpy(((unsigned char*)dbuf->buffer)+d_offset, splitter->pat, LENGTH_PACKET); 303 memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET);
298 d_offset += LENGTH_PACKET; 304 d_offset += LENGTH_PACKET;
299 dbuf->size = dbuf->size + LENGTH_PACKET; 305 dbuf->size += LENGTH_PACKET;
300 } 306 break;
301 307 default:
302 // その他 PID 308 /* pids[pid] が 1 は残すパケットなので書き込む */
303 else 309 if(1 == splitter->pids[pid]) {
304 { 310 memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET);
305 /* pids[pid] が 0 は落とさないパケットなので書き込む */
306 if (0 == splitter->pids[pid])
307 {
308 memcpy(((unsigned char*)dbuf->buffer)+d_offset, ((unsigned char*)sbuf->data)+s_offset, LENGTH_PACKET);
309 d_offset += LENGTH_PACKET; 311 d_offset += LENGTH_PACKET;
310 dbuf->size = dbuf->size + LENGTH_PACKET; 312 dbuf->size += LENGTH_PACKET;
311 } 313 }
312 } 314 break;
313 s_offset = s_offset + LENGTH_PACKET; 315 } /* switch */
316
317 s_offset += LENGTH_PACKET;
314 } 318 }
315 319
316 return(TSS_SUCCESS); 320 return(TSS_SUCCESS);
317 } 321 }
318 322
319 /** 323 /**
320 * PAT 解析処理 324 * PAT 解析処理
321 * 325 *
322 * PAT を解析し、出力対象チャンネルが含まれているかチェックを行い、PAT を再構築する 326 * PAT を解析し、出力対象チャンネルが含まれているかチェックを行い、PAT を再構築する
323 */ 327 */
324 int AnalyzePat( 328 static int AnalyzePat(
325 unsigned char* buf, // [in] 読み込んだバッファ 329 unsigned char* buf, // [in] 読み込んだバッファ
326 unsigned char** pat, // [out] PAT 情報(再構築後) 330 unsigned char** pat, // [out] PAT 情報(再構築後)
327 unsigned char* pids, // [out] 出力対象 PID 情報 331 unsigned char* pids, // [out] 出力対象 PID 情報
328 char** sid_list, // [in] 出力対象サービス ID のリスト 332 char** sid_list, // [in] 出力対象サービス ID のリスト
329 unsigned char* pmt_pids, // [out] サービス ID に対応する PMT の PID 333 unsigned char* pmt_pids, // [out] サービス ID に対応する PMT の PID
330 int* pmt_drop 334 int* pmt_remain
331 ) // [out] 落とすPMTの数 335 ) // [out] 落とすPMTの数
332 { 336 {
333 int pos[MAX_PID]; 337 int pos[MAX_PID];
334 int service_id; 338 int service_id;
335 int i, j=0, k; 339 int i, j=0, k;
338 int result = TSS_SUCCESS; 342 int result = TSS_SUCCESS;
339 char **p; 343 char **p;
340 int sid_found; 344 int sid_found;
341 int avail_sids[MAX_SERVICES]; 345 int avail_sids[MAX_SERVICES];
342 346
343 if (NULL == *pat) 347 if(*pat == NULL) {
344 {
345 /* 初期化 */ 348 /* 初期化 */
346 *pmt_drop = 0; 349 *pmt_remain = 0;
347 memset(pos, 0, sizeof(pos)); 350 memset(pos, 0, sizeof(pos));
348 size = buf[7]; 351 size = buf[7];
349 352
350 // 対象チャンネル判定 353 // 対象チャンネル判定
351 /* size + 8 = パケット全長 */ 354 /* size + 8 = パケット全長 */
352 /* 最終 4 バイトはCRCなので飛ばす */ 355 /* 最終 4 バイトはCRCなので飛ばす */
353 for (i = 17; i < (size + 8) - 4; i = i + 4) 356 for(i = 17; i < (size + 8) - 4; i = i + 4) {
354 { 357
355 sid_found = 0; 358 sid_found = 0;
356 service_id = (buf[i] << 8) + buf[i + 1]; 359 service_id = (buf[i] << 8) + buf[i + 1];
357 avail_sids[j] = service_id; 360 avail_sids[j] = service_id;
358 p = sid_list; 361 p = sid_list;
359 while(*p != NULL) 362
360 { 363 while(*p) {
361 if (service_id == atoi(*p)) 364 if(service_id == atoi(*p)) {
362 {
363 /* 録画対象 = 落とす対象とはしないものなので、基本的に何もしない */ 365 /* 録画対象 = 落とす対象とはしないものなので、基本的に何もしない */
364 /* 録画対象の pmt_pids は 0 とする */ 366 /* 録画対象の pmt_pids は 1 とする */
365 /* 録画対象の pmt の pids は 0 とする */ 367 /* 録画対象の pmt の pids は 1 とする */
366 pid = GetPid(&buf[i + 2]); 368 pid = GetPid(&buf[i + 2]);
367 *(pmt_pids+pid) = 0; 369 *(pmt_pids+pid) = 1;
368 *(pids+pid) = 0; 370 *(pids+pid) = 1;
369 pos[pid] = i; 371 pos[pid] = i;
370 sid_found = 1; 372 sid_found = 1;
373 *pmt_remain += 1;
374 // fprintf(stderr, "sid=%d pid=%d\n", service_id, pid);
371 break; 375 break;
372 } 376 }
373 else if (strstr(*p, "all") != NULL ) 377 else if(strstr(*p, "all")) {
374 {
375 /* all指定時には全保存する */ 378 /* all指定時には全保存する */
376 pid = GetPid(&buf[i + 2]); 379 pid = GetPid(&buf[i + 2]);
377 *(pmt_pids+pid) = 0; 380 *(pmt_pids+pid) = 1;
378 *(pids+pid) = 0; 381 *(pids+pid) = 1;
379 pos[pid] = i; 382 pos[pid] = i;
380 sid_found = 1; 383 sid_found = 1;
384 *pmt_remain += 1;
385 // fprintf(stderr, "sid=%d pid=%d\n", service_id, pid);
381 break; 386 break;
382 } 387 }
388
383 p++; 389 p++;
384 } 390 } /* while */
385 if ( ! sid_found ) 391
386 {
387 /* sid_list を全部なめたが録画対象であると判定されないものを落とす */
388 /* 削除対象の pmt_pids は 1 とする */
389 /* 削除対象の pmt の pids は 1 とする */
390 pid = GetPid(&buf[i + 2]);
391 *(pmt_pids+pid) = 1;
392 *(pids+pid) = 1;
393 pos[pid] = i;
394 *(pmt_drop) = *(pmt_drop)+1;
395 }
396 j++; 392 j++;
397 } 393 }
394
395 /* print SIDs */
398 fprintf(stderr, "Available sid = "); 396 fprintf(stderr, "Available sid = ");
399 for(k=0; k<j; k++) 397 for(k=0; k<j; k++)
400 fprintf(stderr, "%d ", avail_sids[k]); 398 fprintf(stderr, "%d ", avail_sids[k]);
401 fprintf(stderr, "\n"); 399 fprintf(stderr, "\n");
402 400
408 } 406 }
409 fprintf(stderr, "\n"); 407 fprintf(stderr, "\n");
410 408
411 // PAT 再構築 409 // PAT 再構築
412 result = RecreatePat(buf, pat, pids, pos); 410 result = RecreatePat(buf, pat, pids, pos);
411 #if 0
412 int tc;
413 for(tc=0; tc<188; tc++)
414 fprintf(stderr, "%02x ", *(*pat+tc));
415 #endif
413 } 416 }
414 417
415 return(result); 418 return(result);
416 } 419 }
417 420
418 /** 421 /**
419 * PAT 再構築処理 422 * PAT 再構築処理
420 * 423 *
421 * PMT から出力対象チャンネル以外のチャンネル情報を削除し、PAT を再構築する 424 * PMT から出力対象チャンネル以外のチャンネル情報を削除し、PAT を再構築する
422 */ 425 */
423 int RecreatePat( 426 static int RecreatePat(
424 unsigned char* buf, // [in] 読み込んだバッファ 427 unsigned char* buf, // [in] 読み込んだバッファ
425 unsigned char** pat, // [out] PAT 情報(再構築後) 428 unsigned char** pat, // [out] PAT 情報(再構築後)
426 unsigned char* pids, // [out] 出力対象 PID 情報 429 unsigned char* pids, // [out] 出力対象 PID 情報
427 int *pos) // [in] 取得対象 PMT のバッファ中の位置 430 int *pos) // [in] 取得対象 PMT のバッファ中の位置
428 { 431 {
484 } 487 }
485 488
486 /** 489 /**
487 * PMT 解析処理 490 * PMT 解析処理
488 * 491 *
489 * PMT を解析し、削除対象の PID を特定する 492 * PMT を解析し、保存対象の PID を特定する
490 */ 493 */
491 int AnalyzePmt( 494 static int AnalyzePmt(
492 unsigned char* buf, // [in] 読み込んだバッファ 495 unsigned char* buf, // [in] 読み込んだバッファ
493 unsigned char* pids) // [out] 出力対象 PID 情報 496 unsigned char* pids) // [out] 出力対象 PID 情報
494 { 497 {
495 unsigned char Nall; 498 unsigned char Nall;
496 unsigned char N; 499 unsigned char N;
500 Nall = ((buf[6] & 0x0F) << 4) + buf[7]; 503 Nall = ((buf[6] & 0x0F) << 4) + buf[7];
501 504
502 // PCR 505 // PCR
503 pcr = GetPid(&buf[13]); 506 pcr = GetPid(&buf[13]);
504 pids[pcr] = 1; 507 pids[pcr] = 1;
508 // fprintf(stderr, "pcr_pid:%5d", pcr);
505 509
506 N = ((buf[15] & 0x0F) << 4) + buf[16] + 16 + 1; 510 N = ((buf[15] & 0x0F) << 4) + buf[16] + 16 + 1;
507 511
508 // ES PID 512 // ES PID
509 while (N < Nall + 8 - 4) 513 while (N < Nall + 8 - 4)
510 { 514 {
511 epid = GetPid(&buf[N + 1]); 515 // ストリーム種別が 0x0D(type D)は出力対象外
512 516 if (0x0D != buf[N])
513 pids[epid] = 1; 517 {
518 epid = GetPid(&buf[N + 1]);
519
520 pids[epid] = 1;
521 // fprintf(stderr, "%10d", epid);
522 }
514 N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1; 523 N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1;
515 } 524 }
516 525
517 return TSS_SUCCESS; 526 return TSS_SUCCESS;
518 } 527 }
519 528
520 /** 529 /**
521 * CRC 計算 530 * CRC 計算
522 */ 531 */
523 int GetCrc32( 532 static int GetCrc32(
524 unsigned char* data, // [in] CRC 計算対象データ 533 unsigned char* data, // [in] CRC 計算対象データ
525 int len) // [in] CRC 計算対象データ長 534 int len) // [in] CRC 計算対象データ長
526 { 535 {
527 int crc; 536 int crc;
528 int i, j; 537 int i, j;
561 } 570 }
562 571
563 /** 572 /**
564 * PID 取得 573 * PID 取得
565 */ 574 */
566 int GetPid( 575 static int GetPid(
567 unsigned char* data) // [in] 取得対象データのポインタ 576 unsigned char* data) // [in] 取得対象データのポインタ
568 { 577 {
569 return ((data[0] & 0x1F) << 8) + data[1]; 578 return ((data[0] & 0x1F) << 8) + data[1];
570 } 579 }