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