Mercurial > pt1.oyama
comparison recpt1/tssplitter_lite.c @ 122:4009737ea899
add es output arg:
add start_time arg:
author | Naoya OYAMA <naoya.oyama@gmail.com> |
---|---|
date | Wed, 05 May 2010 20:43:43 +0900 |
parents | e915d31c5bd9 |
children |
comparison
equal
deleted
inserted
replaced
121:e915d31c5bd9 | 122:4009737ea899 |
---|---|
46 | 46 |
47 #ifndef AV_RB16 | 47 #ifndef AV_RB16 |
48 #define AV_RB16(x) ((((const uint8_t*)(x))[0] << 8) | ((const uint8_t*)(x))[1]) | 48 #define AV_RB16(x) ((((const uint8_t*)(x))[0] << 8) | ((const uint8_t*)(x))[1]) |
49 #endif | 49 #endif |
50 #define MAX_SERVICE_ID ( 0xffff ) | 50 #define MAX_SERVICE_ID ( 0xffff ) |
51 #define LIST_DECIMAL "0123456789" | |
52 #define TSS_STREAM_TYPE_AUDIO (1) | |
53 #define TSS_STREAM_TYPE_VIDEO (2) | |
51 | 54 |
52 /* prototypes */ | 55 /* prototypes */ |
53 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); | 56 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); |
54 static int AnalyzePat(splitter *sp, unsigned char *buf); | 57 static int AnalyzePat(splitter *sp, unsigned char *buf); |
55 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); | 58 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); |
56 static char** AnalyzeSid(char *sid); | 59 static char** AnalyzeSid(char *sid); |
57 static int AnalyzePmt(splitter *sp, const uint8_t *buf, int sid, const int size); | 60 static int AnalyzePmt(splitter *sp, const uint8_t *buf, int sid, const int size); |
58 static int GetCrc32(unsigned char *data, int len); | 61 static int GetCrc32(unsigned char *data, int len); |
59 static int GetPid(unsigned char *data); | 62 static int GetPid(unsigned char *data); |
60 static int parse_tot( const unsigned char* packet, time_t *t ); | 63 static int parse_tot( const unsigned char* packet, time_t *t ); |
61 void dump_packet( const uint8_t *packet ); | 64 //void dump_packet( const uint8_t *packet ); |
62 static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet); | 65 static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet); |
63 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access); | 66 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid); |
64 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator); | 67 //static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator); |
68 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid); | |
65 static int64_t get_pts(const uint8_t *p); | 69 static int64_t get_pts(const uint8_t *p); |
66 void search_mpeg_system_header(const uint8_t *p); | 70 //void search_mpeg_system_header(const uint8_t *p); |
67 int esbuf_write(splitesbuf_t *esbuf); | 71 static int esbuf_write(splitesbuf_t *esbuf); |
68 //void forward_stc(timespec *stc, timespec offset); | |
69 static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); | 72 static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); |
70 static int pesbuf_empty(splitpesbuf_t *pesbuf); | 73 static int pesbuf_empty(splitpesbuf_t *pesbuf); |
71 void pesbuf_clear(splitpesbuf_t *pesbuf); | 74 void pesbuf_clear(splitpesbuf_t *pesbuf); |
72 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); | 75 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); |
73 static int esbuf_empty(splitesbuf_t *esbuf); | 76 static int esbuf_empty(splitesbuf_t *esbuf); |
74 void esbuf_clear(splitesbuf_t *esbuf); | 77 void esbuf_clear(splitesbuf_t *esbuf, uint64_t pts, uint64_t dts); |
75 static int esbuf_add(splitesbuf_t *esbuf, const uint8_t *data, int len); | 78 static int esbuf_add(splitesbuf_t *esbuf, const uint8_t *data, int len); |
76 static int get_pmt_version(const uint8_t *p); | 79 static int get_pmt_version(const uint8_t *p); |
77 static int esbuf_adts_start_code_prefix(splitesbuf_t *esbuf, int offset); | 80 static int next_adts_start_code(splitesbuf_t *esbuf, int offset); |
78 static int is_video_stream(const int pid, splitesbuf_t *esbuf); | 81 static int is_video_stream(const int pid, splitesbuf_t *esbuf); |
79 static int is_audio_stream(const int pid, splitesbuf_t *esbuf); | 82 static int is_audio_stream(const int pid, splitesbuf_t *esbuf); |
80 static int AnalyzeAdifHeader(splitesbuf_t *esbuf); | 83 static int AnalyzeAdifHeader(splitesbuf_t *esbuf); |
81 static int get_adif_id(uint8_t *p); | 84 static int get_adif_id(uint8_t *p); |
82 static int get_adif_layer(uint8_t *p); | 85 static int get_adif_layer(uint8_t *p); |
90 static int get_adif_copyright_idication_bit(uint8_t *p); | 93 static int get_adif_copyright_idication_bit(uint8_t *p); |
91 static int get_adif_copyright_idication_start(uint8_t *p); | 94 static int get_adif_copyright_idication_start(uint8_t *p); |
92 static int get_adif_aac_frame_length(uint8_t *p); | 95 static int get_adif_aac_frame_length(uint8_t *p); |
93 static int get_adts_buffer_fullness(uint8_t *p); | 96 static int get_adts_buffer_fullness(uint8_t *p); |
94 static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p); | 97 static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p); |
95 static int search_pmt_program(splitter *sp, int pid); | 98 //static int search_pmt_program(splitter *sp, int pid); |
96 static int search_gop_start_code(splitesbuf_t *esbuf); | 99 static int search_gop_start_code(splitesbuf_t *esbuf); |
97 //static int creat_filename(char *base, char *filename, int sid, int epid, int av_flag ,splitesbuf_t *esbuf); | 100 static int creat_es_file(splitter *sp, int sid, int pid, int av_flag); |
98 static int creat_filename(splitter *sp, int sid, int pid, int av_flag); | 101 static time_t cue2time(char *yyyymmddhhmiss); |
102 static int search_pcr_pid(splitter *sp, int pid); | |
99 | 103 |
100 /** | 104 /** |
101 * サービスID解析 | 105 * サービスID解析 |
102 */ | 106 */ |
103 static char** AnalyzeSid( | 107 static char** AnalyzeSid( |
194 /** | 198 /** |
195 * 初期化処理 | 199 * 初期化処理 |
196 */ | 200 */ |
197 splitter* split_startup( | 201 splitter* split_startup( |
198 char *sid, // [in] サービスID(引数で指定した文字列) | 202 char *sid, // [in] サービスID(引数で指定した文字列) |
199 char *filename // [in] 出力ESファイル名(引数で指定したファイル名) | 203 char *filename, // [in] 出力ESファイル名(引数で指定したファイル名) |
204 char *arg_cue // [in] 録画開始時刻(引数で指定した文字列 YYYYMMDDHHMISS) | |
200 ) | 205 ) |
201 { | 206 { |
202 splitter* sp; | 207 splitter* sp; |
203 int i; | 208 int i; |
204 sp = malloc(sizeof(splitter)); | 209 sp = malloc(sizeof(splitter)); |
213 fprintf(stderr, "split_startup malloc error.\n"); | 218 fprintf(stderr, "split_startup malloc error.\n"); |
214 return NULL; | 219 return NULL; |
215 } | 220 } |
216 memset(sp->pids, 0, sizeof(sp->pids)); | 221 memset(sp->pids, 0, sizeof(sp->pids)); |
217 memset(sp->pmt_pids, 0, sizeof(sp->pmt_pids)); | 222 memset(sp->pmt_pids, 0, sizeof(sp->pmt_pids)); |
223 memset(sp->cat_pids, 0, sizeof(sp->cat_pids)); | |
224 memset(sp->pcr_pids, 0, sizeof(sp->pcr_pids)); | |
225 memset(sp->pcr, 0, sizeof(sp->pcr)); | |
218 | 226 |
219 sp->sid_list = NULL; | 227 sp->sid_list = NULL; |
220 sp->pat = NULL; | 228 sp->pat = NULL; |
221 sp->sid_list = AnalyzeSid(sid); | 229 sp->sid_list = AnalyzeSid(sid); |
222 if ( sp->sid_list == NULL ) | 230 if ( sp->sid_list == NULL ) |
225 return NULL; | 233 return NULL; |
226 } | 234 } |
227 sp->pat_count = 0xFF; | 235 sp->pat_count = 0xFF; |
228 sp->pmt_retain = -1; | 236 sp->pmt_retain = -1; |
229 sp->pmt_counter = 0; | 237 sp->pmt_counter = 0; |
230 // sp->STC_timespec.tv_sec = 0; | 238 sp->time_cue = 0; |
231 // sp->STC_timespec.tv_nsec = 0; | 239 sp->time_tot = 0; |
232 // sp->tot_offset.tv_sec = 0; | 240 sp->pcr_nb = 0; |
233 // sp->tot_offset.tv_nsec = 0; | |
234 sp->cue_time = -1; | |
235 sp->stc = 0; | |
236 sp->status = 1; | |
237 memset(sp->esbuf, 0, sizeof(splitesbuf_t *)*MAX_PID); | 241 memset(sp->esbuf, 0, sizeof(splitesbuf_t *)*MAX_PID); |
238 memset(sp->pesbuf, 0, sizeof(splitpesbuf_t *)*MAX_PID); | 242 memset(sp->pesbuf, 0, sizeof(splitpesbuf_t *)*MAX_PID); |
239 memset(sp->program, 0, sizeof(program_t *)*MAX_SERVICE_ID); | 243 memset(sp->program, 0, sizeof(program_t *)*MAX_SERVICE_ID); |
240 for ( i=0; i < MAX_PID; i++ ) { | 244 for ( i=0; i < MAX_PID; i++ ) { |
241 /* pmt_version は (N%32) の値を取るので、0 で初期化してはならない */ | 245 /* pmt_version は (N%32) の値を取るので、0 で初期化してはならない */ |
242 sp->program[i].pmt_version = -1; | 246 sp->program[i].pmt_version = -1; |
247 /* cue は最大値で初期化(CUE <= STCとなると録画開始するため) */ | |
248 sp->program[i].cue = INT64_MAX; | |
243 } | 249 } |
244 memset(sp->pid_sid_table, 0, sizeof(int)*MAX_PID); | 250 memset(sp->pid_sid_table, 0, sizeof(int)*MAX_PID); |
245 // sp->filename = filename; | |
246 if ( filename != NULL ) { | 251 if ( filename != NULL ) { |
247 sp->esout = 1; | 252 sp->esout = 1; |
248 sp->filename = filename; | 253 sp->filename = filename; |
254 } | |
255 if ( arg_cue != NULL ) { | |
256 sp->arg_cue = arg_cue; | |
257 } else { | |
258 sp->arg_cue = "00000000000000"; /* とりあえず最小値 */ | |
249 } | 259 } |
250 return sp; | 260 return sp; |
251 } | 261 } |
252 | 262 |
253 /** | 263 /** |
268 /** | 278 /** |
269 * 終了処理 | 279 * 終了処理 |
270 */ | 280 */ |
271 void split_shutdown(splitter* sp) | 281 void split_shutdown(splitter* sp) |
272 { | 282 { |
283 int i = 0; | |
273 if ( sp != NULL ) { | 284 if ( sp != NULL ) { |
274 if ( sp->pat != NULL ) | 285 if ( sp->pat != NULL ) |
275 { | 286 { |
276 free(sp->pat); | 287 free(sp->pat); |
277 sp->pat = NULL; | 288 sp->pat = NULL; |
278 } | 289 } |
279 if ( sp->sid_list != NULL ) | 290 if ( sp->sid_list != NULL ) |
280 { | 291 { |
281 free(sp->sid_list); | 292 free(sp->sid_list); |
282 sp->sid_list = NULL; | 293 sp->sid_list = NULL; |
294 } | |
295 for(i=0; i < MAX_PID; i++) { | |
296 if ( sp->esbuf[i] != NULL ) { | |
297 if ( sp->esbuf[i]->fd != -1 ) { | |
298 close(sp->esbuf[i]->fd); | |
299 sp->esbuf[i]->fd = -1; | |
300 } | |
301 free(sp->esbuf[i]); | |
302 sp->esbuf[i] = NULL; | |
303 } | |
304 if ( sp->pesbuf[i] != NULL ) { | |
305 free(sp->pesbuf[i]); | |
306 sp->pesbuf[i] = NULL; | |
307 } | |
283 } | 308 } |
284 free(sp); | 309 free(sp); |
285 sp = NULL; | 310 sp = NULL; |
286 } | 311 } |
287 } | 312 } |
292 * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う | 317 * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う |
293 */ | 318 */ |
294 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf) | 319 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf) |
295 { | 320 { |
296 #if 0 | 321 #if 0 |
297 unsigned char **pat, // [out] PAT 情報(再構築後) | 322 splitter *sp, // [in/out] splitter構造体 |
298 unsigned char* pids, // [out] 出力対象 PID 情報 | 323 ARIB_STD_B25_BUFFER *sbuf, // [in] pt1_drvの入力TS |
299 char** sid_list, // [in] 出力対象サービス ID のリスト | |
300 unsigned char* pmt_pids, // [in] 出力対象PIDのPMT PID | |
301 , // [in] pt1_drvの入力TS | |
302 int* pmt_retain, // [in] PMTの落とすべき数 | |
303 int* pmt_counter // [out] PMTの落とした数 | |
304 #endif | 324 #endif |
305 | 325 |
306 int length = sbuf->size; | 326 int length = sbuf->size; |
307 int pid; | 327 int pid; |
308 int result = TSS_ERROR; | 328 int result = TSS_ERROR; |
311 index = 0; | 331 index = 0; |
312 while(length - index - LENGTH_PACKET > 0) { | 332 while(length - index - LENGTH_PACKET > 0) { |
313 pid = GetPid(sbuf->data + index + 1); | 333 pid = GetPid(sbuf->data + index + 1); |
314 // PAT | 334 // PAT |
315 if(PAT == pid) { | 335 if(PAT == pid) { |
316 dump_packet(sbuf->data + index); | |
317 result = AnalyzePat(sp, sbuf->data + index); | 336 result = AnalyzePat(sp, sbuf->data + index); |
318 if(TSS_SUCCESS != result) { | 337 if(TSS_SUCCESS != result) { |
319 /* 下位の関数内部でmalloc error発生 */ | 338 /* 下位の関数内部でmalloc error発生 */ |
320 return result; | 339 return result; |
321 } | 340 } |
323 | 342 |
324 // PMT | 343 // PMT |
325 /* 残すpmt_pidである場合には、pmtに書かれている | 344 /* 残すpmt_pidである場合には、pmtに書かれている |
326 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */ | 345 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */ |
327 if(sp->pmt_pids[pid] == 1) { | 346 if(sp->pmt_pids[pid] == 1) { |
328 /* | |
329 * program(番組)とServiceID をベースに管理することにしているので、 | |
330 * pmt_pidsとかもう必要ないかも… | |
331 */ | |
332 /* この中にはPMT毎に一度しか入らないようにしておく */ | 347 /* この中にはPMT毎に一度しか入らないようにしておく */ |
333 int random_access; | |
334 //AnalyzePmt(sp, sbuf->data + index, pid); | |
335 //AnalyzePmt(sp, sbuf->data + index +4, pid, LENGTH_PACKET-4); | |
336 sp->pmt_pids[pid]++; | 348 sp->pmt_pids[pid]++; |
337 sp->pmt_counter += 1; | 349 sp->pmt_counter += 1; |
338 DemuxTs(sbuf->data +index, sp, pid, &random_access); /* AnalyzePmt より DemuxTs の方がアダプテーションフィールドの処理が良いので変更 */ | 350 DemuxTs(sbuf->data +index, sp, pid); /* AnalyzePmt より DemuxTs の方がアダプテーションフィールドの処理が良いので変更 */ |
339 } | 351 } |
340 /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを | 352 /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを得る */ |
341 * 得る */ | |
342 /* pmt_counter と pmt_retain が一致する場合に条件は満たされる */ | 353 /* pmt_counter と pmt_retain が一致する場合に条件は満たされる */ |
343 if(sp->pmt_counter == sp->pmt_retain) { | 354 if(sp->pmt_counter == sp->pmt_retain) { |
344 result = TSS_SUCCESS; | 355 result = TSS_SUCCESS; |
345 break; | 356 break; |
346 } | 357 } |
355 | 366 |
356 /** | 367 /** |
357 * TS 分離処理 | 368 * TS 分離処理 |
358 */ | 369 */ |
359 int split_ts( | 370 int split_ts( |
360 splitter *splitter, // [in] splitterパラメータ | 371 splitter *sp, // [in] splitterパラメータ |
361 ARIB_STD_B25_BUFFER *sbuf, // [in] 入力TS | 372 ARIB_STD_B25_BUFFER *sbuf, // [in] 入力TS |
362 splitbuf_t *dbuf // [out] 出力TS | 373 splitbuf_t *dbuf // [out] 出力TS |
363 ) | 374 ) |
364 { | 375 { |
365 int pid; | 376 int pid; |
366 unsigned char *sptr, *dptr; | 377 unsigned char *sptr, *dptr; |
367 int s_offset = 0; | 378 int s_offset = 0; |
368 int d_offset = 0; | 379 int d_offset = 0; |
369 int64_t pcr; | 380 int64_t pcr_h = 0; |
370 int64_t pcr_h; | 381 int pcr_l = 0; |
371 int pcr_l; | 382 int ret = 0; |
372 struct timespec tot_timespec; | 383 int sid = 0; |
373 struct timespec local_timespec; | 384 program_t *program; |
374 int len_pes; | 385 static int packet_nb; /* パケット受信数 */ |
375 int random_access; | 386 int i = 0; |
376 int sid; | |
377 | 387 |
378 /* 初期化 */ | 388 /* 初期化 */ |
379 dbuf->size = 0; | 389 dbuf->size = 0; |
380 if (sbuf->size < 0) { | 390 if (sbuf->size < 0) { |
381 return TSS_ERROR; | 391 return TSS_ERROR; |
382 } | 392 } |
383 | 393 |
384 sptr = sbuf->data; | 394 sptr = sbuf->data; |
385 dptr = dbuf->buffer; | 395 dptr = dbuf->buffer; |
386 #if 0 | |
387 /* TOT受信済みであるなら、STC を成長させる */ | |
388 if ( sp->tot_offset.tv_nsec != 0 && sp->tot_offset.tv_sec != 0) { | |
389 forward_stc(&(sp->STC_timespec), sp->tot_offset); | |
390 } | |
391 #endif | |
392 | 396 |
393 while(sbuf->size > s_offset) { | 397 while(sbuf->size > s_offset) { |
394 pid = GetPid(sptr + s_offset + 1); | 398 pid = GetPid(sptr + s_offset + 1); |
395 sid = splitter->pid_sid_table[pid]; | 399 sid = sp->pid_sid_table[pid]; /* PIDからSIDを取得 */ |
396 switch(pid) { | 400 switch(pid) { |
397 | 401 |
398 // PAT | 402 // PAT |
399 case PAT: | 403 case PAT: |
400 // 巡回カウンタカウントアップ | 404 // 巡回カウンタカウントアップ |
401 if(0xFF == splitter->pat_count) { | 405 if(0xFF == sp->pat_count) { |
402 splitter->pat_count = splitter->pat[3]; | 406 sp->pat_count = sp->pat[3]; |
403 } | 407 } |
404 else { | 408 else { |
405 splitter->pat_count = (splitter->pat_count + 1) % 16; | 409 sp->pat_count += 1; |
410 if(0 == sp->pat_count % 0x10) { | |
411 sp->pat_count -= 0x10; | |
412 } | |
406 } | 413 } |
407 splitter->pat[3] = splitter->pat_count; | 414 sp->pat[3] = sp->pat_count; |
408 | 415 |
409 memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET); | 416 memcpy(dptr + d_offset, sp->pat, LENGTH_PACKET); |
410 d_offset += LENGTH_PACKET; | 417 d_offset += LENGTH_PACKET; |
411 dbuf->size += LENGTH_PACKET; | 418 dbuf->size += LENGTH_PACKET; |
412 break; | 419 break; |
413 case TOT: | 420 case TOT: |
414 /* TOT に TDTの情報全てが含まれており、実放送では TOT しか送信されない */ | 421 /* TOT に TDTの情報全てが含まれており、実放送では TOT しか送信されない */ |
415 /* TOT は 500msec の誤差が保証されている | 422 /* TOT は 500msec の誤差が保証されている |
416 * 閏秒の場合は最大1.5秒の誤差となる | 423 * 閏秒の場合は最大1.5秒の誤差となる |
417 */ | 424 */ |
418 #if 0 | 425 if ( sp->time_tot == 0 ) { |
419 if ( sp->tot_offset.tv_nsec != 0 && sp->tot_offset.tv_sec != 0 ) { | 426 /* splitter構造体の時刻関係(TOT/CUE)のパラメータ初期化 */ |
420 parse_tot(sptr + s_offset, &(tot_timespec.tv_sec)); | 427 parse_tot(sptr + s_offset, &(sp->time_tot)); |
421 clock_gettime(CLOCK_REALTIME, &local_timespec); | 428 sp->time_cue = cue2time(sp->arg_cue); |
422 | 429 sp->tot_packet_nb = packet_nb; |
423 /* TOT をSystem Time Clock(STC)に入れる */ | |
424 sp->STC_timespec.tv_sec = tot_timespec.tv_sec; | |
425 sp->STC_timespec.tv_nsec = tot_timespec.tv_nsec; | |
426 | |
427 /* TOT と localtime の差分を sp->tot_offset に入れる */ | |
428 sp->tot_offset.tv_sec = tot_timespec.tv_sec - local_timespec.tv_sec; | |
429 sp->tot_offset.tv_nsec = tot_timespec.tv_nsec - local_timespec.tv_nsec; | |
430 } | |
431 #endif | |
432 /* STC が既にあるならTOT受信時に頭出し時刻を決定する */ | |
433 /* 59秒9990 あたりを頭出し時刻に設定でよいかな */ | |
434 if ( splitter->stc != 0 && splitter->cue_time == -1) { | |
435 /* TOT から cue_time を計算する */ | |
436 /* えいや。で、59秒9990固定決め打ち */ | |
437 parse_tot(sptr + s_offset, &(tot_timespec.tv_sec)); | |
438 //cue_second = ((tot_timespec.tv_sec % 60) - 59); | |
439 splitter->cue_time = splitter->stc + (((59 - (tot_timespec.tv_sec % 60))*(27*1000*1000)) + floor((27*1000*1000)*0.999)); | |
440 //printf("stc[%lld]. cue_time[%lld].\n", splitter->stc, splitter->cue_time); | |
441 | |
442 } else { | |
443 /* TOT受診時にSTCが存在しないならTOTは捨てる */ | |
444 } | 430 } |
445 break; | 431 break; |
446 default: | 432 default: |
447 /* 時間管理に関しての実装方針 */ | 433 /* ■時間管理に関しての実装方針■ */ |
448 /* | 434 /* |
449 * 時間関係を扱っている変数のまとめ | 435 * ■時間関係を扱っている変数■ |
450 * PCR : 42Bit @27MHz(プログラム毎に独立) | 436 * PCR : 42Bit @27MHz(ServiceID(ProgramID, sid)毎に独立) |
451 * PTS : 42Bit @90KHz(SYSTEM ID(ES)毎に独立) | 437 * PTS : 42Bit @90KHz(ES毎に独立) |
452 * DTS : 42Bit @90KHz(SYSTEM ID(ES)毎に独立) | 438 * DTS : 42Bit @90KHz(ES毎に独立) |
453 * TOT : MJD + 2進化10進数(ストリームに一つだけ) | 439 * TOT : MJD + 2進化10進数(TSに1つだけ) |
454 * STC : 64Bit @27MHz(システムローカル時刻(ソースはTOT)) | 440 * STC : 64Bit @27MHz(ServiceID(ProgramID, sid)の現在時刻(ソースはPCR)) |
441 * CUE : 録画開始時刻 YYYYMMDDHHMISS (引数指定) | |
455 * | 442 * |
456 * STC と TOT の関連だけ計算出来るようにしておいて、 | 443 * ■STCの管理方針■ |
457 * 出力するようにする/しないの判定は全体的に、 | 444 * PCR受信時にSTCに時間情報をコピーする |
458 * STCからTOTを使って出した時刻情報とする。かなぁ。 | 445 * 1パケットを受信すると経過する時間を加算してSTCを管理する |
459 * PCR/PTS/DTSはオーバーフローしたときには34Bit目が立っていると見なすこと | 446 * (ffmpegのmpegts.cと同じ方針) |
447 * | |
448 * ■CUEとTOTとSTC■ | |
449 * TOTからSTCと比較するための情報を作成する。 | |
450 * ・TOTは time_t | |
451 * ・CUEは time_t | |
452 * ・STCは42Bitの27MHz周期の数値 | |
453 * TOT 受信時に各Program(ServiceID)のSTCを変換基準値とする | |
454 * 録画開始時(27MHz)の値の計算式は、 | |
455 * Program->CUE = STCの変換基準値 + 27e6*(ARG_CUE-TOT(秒)) | |
456 * 録画の開始確認として Program->CUE と PTS を比較すればよい | |
457 * | |
458 * ※PCR/PTS/DTSはオーバーフローしたときには34Bit目が立っていると見なすこと※ | |
459 * オーバーフロー時の処理は未実装 | |
460 */ | 460 */ |
461 // if ( 1 == splitter->pmt_pids[pid] ) { | 461 if ( 2 == sp->pmt_pids[pid] ) { |
462 if ( 2 == splitter->pmt_pids[pid] ) { | |
463 /* PMT の追跡 */ | 462 /* PMT の追跡 */ |
464 int random_access; | 463 DemuxTs((sptr+s_offset), sp, pid); |
465 DemuxTs((sptr+s_offset), splitter, pid, &random_access); | |
466 } | 464 } |
467 /* pids[pid] が 1 は残すパケットなので書き込む */ | 465 /* pids[pid] が 1 は残すパケットなので書き込む */ |
468 if ( 1 == splitter->pids[pid] ) { | 466 if ( (1 == sp->pids[pid]) ) { |
469 len_pes = 0; | 467 /* PCRとSTCの処理 */ |
470 random_access = 0; | 468 int pcr_index; |
471 /* PCR 解析テスト */ | 469 pcr_index = search_pcr_pid(sp, pid); |
472 if (parse_pcr(&pcr_h, &pcr_l, (sptr+s_offset)) == 0){ | 470 if ( sp->pcr_pids[pid] == 1 && pcr_index != -1) { /* PCRか否か */ |
473 pcr = pcr_h * 300 + pcr_l; | 471 ret = parse_pcr(&pcr_h, &pcr_l, (sptr+s_offset)); |
474 /* PCR の種にするものは、Program の PCR として指定されたPacketIDのものとすること */ | 472 /* |
475 /* STC は PCR を種にする */ | 473 * PCR は複数 ServiceID(ProgramID)で重複利用される場合がある |
476 splitter->stc = pcr; | 474 * PCR を参照する複数の ServiceID(ProgramID)分ループ |
477 // printf("PID[%d] pcr_h=[%llx] pcr_l=[%d] PCR[%f]\n",pid, pcr_h, pcr_l, ((double)pcr/(90000*300))); | 475 */ |
478 } | 476 for (i=0; i < sp->pcr[pcr_index].sid_nb; i++) { |
479 /* TS処理 */ | 477 sid = sp->pcr[pcr_index].sid[i]; |
480 if (DemuxTs((sptr+s_offset), splitter, pid, &random_access) == 0 ) { | 478 program = &(sp->program[sid]); |
481 #if 0 | 479 /* こっから */ |
482 /* とりあえずやっつけ */ | 480 if ( ret == 0 ) { /* PCR の解析に成功 */ |
483 /* パケットの画面表示時刻(pts) >= 録画開始時刻(cue_time) となった場合に録画開始 */ | 481 program->stc = pcr_h * 300 + pcr_l; /* PCR受信時にSTCを補正*/ |
484 // if ( ((pts*300) >= splitter->cue_time) && (splitter->cue_time != -1)) { | 482 if ( program->pcr1 == 0 ) { |
485 if ( ((splitter->esbuf[pid].pts) >= splitter->program[sid].cue_time) && (splitter->program[sid].cue_time != -1)) { | 483 program->pcr1 = program->stc; |
486 splitter->cue_time = 0; | 484 printf("pcr1 pid[%d] sid[%d] packet_nb[%d] sid_nb[%d] i[%d]\n", |
487 splitter->status = 0; | 485 pid, sid, packet_nb, sp->pcr[pcr_index].sid_nb, i); |
488 clock_gettime(CLOCK_REALTIME, &local_timespec); | 486 } else if ( program->pcr2 == 0 ) { |
489 printf("start recording. time_sec[%d] nsec[%d].\n", local_timespec.tv_sec%60, local_timespec.tv_nsec); | 487 // printf("pcr2 pid[%d] sid[%d] packet_nb[%d], p_packet_nb[%d] sid_nb[%d] i[%d]\n", |
490 } | 488 // pid, sid, packet_nb, program->pcr_packet_nb, sp->pcr[pcr_index].sid_nb, i); |
491 #endif | 489 program->pcr2 = program->stc; |
492 } | 490 program->pcr_incr = (program->pcr2 -program->pcr1) |
493 //search_mpeg_system_header(sptr+s_offset); | 491 /(packet_nb -program->pcr_packet_nb); |
494 /* | 492 printf("pcr2 pid[%d] sid[%d] pcr_incr[%llu]\n", |
495 * STCが cue_time を経過したら録画開始 | 493 pid, sid, program->pcr_incr); |
496 */ | 494 } else { |
497 if ( splitter->cue_time != -1 && splitter->cue_time <= splitter->stc ) { | 495 /* PCR処理済み */ |
498 memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); | 496 ; /* 得に処理無し */ |
499 d_offset += LENGTH_PACKET; | 497 } |
500 dbuf->size += LENGTH_PACKET; | 498 if ( (program->cue == INT64_MAX ) && |
501 if ( splitter->status ) { | 499 (sp->arg_cue != NULL) && |
502 struct timespec local_timespec; | 500 (sp->time_tot != 0) ) { /* 録画開始時刻指定時 */ |
503 clock_gettime(CLOCK_REALTIME, &local_timespec); | 501 /* |
504 printf("start recording. time_sec[%d] nsec[%d].\n", local_timespec.tv_sec%60, local_timespec.tv_nsec); | 502 * 録画開始時刻 = STC +(CUE -TOT)*27MHz |
505 splitter->status = 0; | 503 * +(TOT取得時から現在までのパケット数の増分)*パケットあたりの進む時間 |
504 * -0.49秒(この数字は適当) | |
505 * TOT/STCで時間調整して、GOP先頭から出すので攻めてしまっていい気がする | |
506 */ | |
507 program->cue = program->stc | |
508 +(sp->time_cue -sp->time_tot)*27e6 | |
509 +(packet_nb -sp->tot_packet_nb)*program->pcr_incr | |
510 -(27e6*49/100); | |
511 printf("STC[%llu] CUE[%llu] SID[%d]\n", | |
512 program->stc, program->cue, sid); | |
513 } | |
514 program->pcr_packet_nb = packet_nb; | |
515 program->packet_nb = packet_nb; | |
516 } else if ( program->pcr_incr ) { /* PCRの解析に失敗且つpcr_incr変数の計算済み*/ | |
517 /* STCを成長させる */ | |
518 program->stc += (packet_nb -program->packet_nb)*program->pcr_incr; | |
519 program->packet_nb = packet_nb; | |
520 } else { | |
521 ; /* STCを進める要素が揃ってません */ | |
522 } | |
523 } /* for */ | |
524 } else { /* 処理対象パケットはPCRではない */ | |
525 program = &(sp->program[sid]); | |
526 if ( program->pcr_incr ) { /* PCRを受信しない且つpcr_incr変数の計算済み */ | |
527 /* STCを成長させる */ | |
528 program->stc += (packet_nb -program->packet_nb)*program->pcr_incr; | |
529 program->packet_nb = packet_nb; | |
530 } else { /* それ以外 */ | |
531 ; /* STCを進める要素が揃ってません */ | |
506 } | 532 } |
507 } | 533 } |
534 #if 0 | |
535 // NHK Gを ALL とすると SID 1024 しか出ない...orz.. | |
536 if ( !(packet_nb % 1000) ) { | |
537 program = &(sp->program[sid]); | |
538 printf("STC[%llu] SID[%d]\n", program->stc, sid); | |
539 } | |
540 #endif | |
541 /* TS処理 */ | |
542 DemuxTs((sptr+s_offset), sp, pid); | |
543 memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); | |
544 d_offset += LENGTH_PACKET; | |
545 dbuf->size += LENGTH_PACKET; | |
508 } | 546 } |
509 break; | 547 break; |
510 } /* switch */ | 548 } /* switch */ |
511 | |
512 s_offset += LENGTH_PACKET; | 549 s_offset += LENGTH_PACKET; |
513 } | 550 packet_nb += 1; /* パケット受信数加算 */ |
514 | 551 } |
515 return(TSS_SUCCESS); | 552 return(TSS_SUCCESS); |
516 } | 553 } |
517 | 554 |
518 /** | 555 /** |
519 * PAT 解析処理 | 556 * PAT 解析処理 |
572 | 609 |
573 while(*p) { | 610 while(*p) { |
574 if(service_id == atoi(*p)) { | 611 if(service_id == atoi(*p)) { |
575 /* 録画対象の pmt_pids は 1 とする */ | 612 /* 録画対象の pmt_pids は 1 とする */ |
576 /* 録画対象の pmt の pids は 1 とする */ | 613 /* 録画対象の pmt の pids は 1 とする */ |
614 /* 対応する pid_sid_table に サービスID(ProgramID) を入れる */ | |
577 pid = GetPid(&buf[i + 2]); | 615 pid = GetPid(&buf[i + 2]); |
578 *(pmt_pids+pid) = 1; | 616 *(pmt_pids+pid) = 1; |
579 *(pids+pid) = 1; | 617 *(pids+pid) = 1; |
580 pos[pid] = i; | 618 pos[pid] = i; |
581 sid_found = TRUE; | 619 sid_found = TRUE; |
780 (sp->pat)[8 + LENGTH_PAT_HEADER + pid_num*4] = (crc ) & 0xFF; | 818 (sp->pat)[8 + LENGTH_PAT_HEADER + pid_num*4] = (crc ) & 0xFF; |
781 | 819 |
782 return(TSS_SUCCESS); | 820 return(TSS_SUCCESS); |
783 } | 821 } |
784 | 822 |
823 | |
785 /** | 824 /** |
786 * PMT 解析処理 | 825 * PMT 解析処理 |
787 * | 826 * |
788 * PMT を解析し、保存対象の PID を特定する | 827 * PMT を解析し、保存対象の PID を特定する |
789 * TSヘッダとアダプテーションフィールドの処理は DemuxTs に一任するので、 | 828 * TSヘッダとアダプテーションフィールドの処理は DemuxTs に一任するので、 |
798 unsigned char Nall; | 837 unsigned char Nall; |
799 unsigned char N; | 838 unsigned char N; |
800 int pcr; | 839 int pcr; |
801 int epid; | 840 int epid; |
802 int av_flag = 0; | 841 int av_flag = 0; |
842 int i = 0; | |
843 int j = 0; | |
844 int pcr_found = 0; | |
845 /* デバッグ用 PMT情報表示 */ | |
846 #define PmtDebug (1) | |
847 | |
848 #ifdef PmtDebug | |
849 printf("AnalyzePmt start. Tree List enable.\n"); | |
850 printf("SID[%d][0x%04x]\n", sid, sid); | |
851 #endif | |
803 | 852 |
804 // Nall = ((buf[2] & 0x0F) << 4) + buf[3]; | 853 // Nall = ((buf[2] & 0x0F) << 4) + buf[3]; |
805 Nall = ((buf[2] & 0x0F) << 8) + buf[3]; | 854 Nall = ((buf[2] & 0x0F) << 8) + buf[3]; |
855 // ここで受け取るのはTSパケットではなく、セクションの先頭ポインタであるのでsizeで見る | |
856 // if(Nall > LENGTH_PACKET) | |
857 // Nall = LENGTH_PACKET - 8; /* xxx workaround --yaz */ | |
858 if(Nall > size) | |
859 Nall = size -8; | |
806 | 860 |
807 /* get version */ | 861 /* get version */ |
808 sp->program[sid].pmt_version = get_pmt_version(buf); | 862 sp->program[sid].pmt_version = get_pmt_version(buf); |
863 #ifdef PmtDebug | |
864 printf(" pmt_version[%02x]\n", sp->program[sid].pmt_version); | |
865 #endif | |
809 | 866 |
810 // PCR | 867 // PCR |
811 pcr = GetPid(&buf[9]); | 868 pcr = GetPid(&buf[9]); |
812 sp->pids[pcr] = 1; | 869 sp->pids[pcr] = 1; |
813 sp->program[sid].pcr_packet_id = pcr; | 870 sp->program[sid].pcr_packet_id = pcr; |
871 sp->pid_sid_table[pcr] = sid; /* PCRは重複する可能性があるので方式がよろしくない */ | |
872 sp->pcr_pids[pcr] = 1; | |
873 | |
874 /* PCRの重複チェック(複数ServiceID(ProgramID)) */ | |
875 for( i=0; i < sp->pcr_nb; i++ ) { | |
876 if ( sp->pcr[i].pid == pcr ) { | |
877 /* 発見 */ | |
878 for ( j=0; j < sp->pcr[i].sid_nb; j++ ) { | |
879 /* 同一SIDが既に登録されているか確認 */ | |
880 if ( sp->pcr[i].sid[j] == sid ) { | |
881 pcr_found = 1; | |
882 break; | |
883 } | |
884 } | |
885 if ( pcr_found ) { | |
886 /* 同一SIDが既に登録されている */ | |
887 #ifdef PmtDebug | |
888 printf(" same sid found pcr[%d] sid[%d]\n", pcr, sid); | |
889 #endif | |
890 break; | |
891 } | |
892 /* 重複PCR発見 */ | |
893 #ifdef PmtDebug | |
894 printf(" same pcr found pcr[%d] sid[%d] sid_nb[%d], i[%d]\n", pcr, sid, sp->pcr[i].sid_nb, i); | |
895 #endif | |
896 sp->pcr[i].sid[sp->pcr[i].sid_nb] = sid; | |
897 sp->pcr[i].sid_nb += 1; | |
898 pcr_found = 1; | |
899 break; | |
900 } | |
901 } | |
902 | |
903 if ( ! pcr_found ) { | |
904 /* PCR管理領域更新 */ | |
905 #ifdef PmtDebug | |
906 printf(" new pcr found pcr[%d] sid[%d], pcr_nb[%d]\n", pcr, sid, sp->pcr_nb); | |
907 #endif | |
908 sp->pcr[sp->pcr_nb].pid = pcr; | |
909 sp->pcr[sp->pcr_nb].sid[0] = sid; | |
910 sp->pcr[sp->pcr_nb].sid_nb = 1; | |
911 sp->pcr_nb += 1; | |
912 } | |
913 #ifdef PmtDebug | |
914 printf(" PCR PacketID[%d][0x%04x]\n", pcr, pcr); | |
915 #endif | |
814 | 916 |
815 // N = ((buf[11] & 0x0F) << 4) + buf[12] + 16 + 1; | 917 // N = ((buf[11] & 0x0F) << 4) + buf[12] + 16 + 1; |
816 N = ((buf[11] & 0x0F) << 8) + buf[12] + 12 + 1; | 918 N = ((buf[11] & 0x0F) << 8) + buf[12] + 12 + 1; |
817 // printf("NAll[%d] N[%d]\n", Nall, N); | 919 // printf("NAll[%d] N[%d]\n", Nall, N); |
920 | |
921 // ECM | |
922 //int p = 17; | |
923 int p = 13; | |
924 while(p < N) { | |
925 if ( p > size -4) { | |
926 break; | |
927 } | |
928 uint32_t cat_pid; | |
929 uint32_t tag; | |
930 uint32_t len; | |
931 | |
932 tag = buf[p]; | |
933 len = buf[p+1]; | |
934 p += 2; | |
935 | |
936 if(tag == 0x09 && len >= 4 && p+len <= N) { | |
937 // ca_pid = ((buf[p+2] << 8) | buf[p+3]) & 0x1fff; | |
938 cat_pid = (AV_RB16(buf+p+2)) & 0x1fff; | |
939 sp->pids[cat_pid] = 1; | |
940 sp->cat_pids[cat_pid] = 1; | |
941 sp->pid_sid_table[cat_pid] = sid; /* CATも複数ServiceIDで重複がある */ | |
942 #ifdef PmtDebug | |
943 printf(" CAT PacketID[%d][0x%04x]\n", cat_pid, cat_pid); | |
944 #endif | |
945 } | |
946 p += len; | |
947 } | |
818 | 948 |
819 /* | 949 /* |
820 * ISO/IEC 13818-1:2000(E) Table 2-29 - Stream type assignments | 950 * ISO/IEC 13818-1:2000(E) Table 2-29 - Stream type assignments |
821 * Value Desctiption | 951 * Value Desctiption |
822 * 0x00 ITU-T | ISO/IEC Reserved | 952 * 0x00 ITU-T | ISO/IEC Reserved |
844 * 0x80-0xFF User Private | 974 * 0x80-0xFF User Private |
845 * | 975 * |
846 */ | 976 */ |
847 | 977 |
848 // ES PID | 978 // ES PID |
849 while (N < Nall + 8 - 4) | 979 while (N < Nall + 8 - 4) { |
850 { | |
851 av_flag = 0; | 980 av_flag = 0; |
852 if ( N > size ) { | |
853 break; | |
854 } | |
855 // ストリーム種別が 0x0D(type D)は出力対象外 | 981 // ストリーム種別が 0x0D(type D)は出力対象外 |
856 if (0x0D != buf[N]) | 982 if (0x0D != buf[N]) { |
857 { | |
858 epid = GetPid(&buf[N + 1]); | 983 epid = GetPid(&buf[N + 1]); |
859 sp->pids[epid] = 1; | 984 sp->pids[epid] = 1; |
985 sp->pid_sid_table[epid] = sid; | |
860 if ( buf[N] == 0x02 ) { /* 13818-2 Video */ | 986 if ( buf[N] == 0x02 ) { /* 13818-2 Video */ |
861 sp->program[sid].video[sp->program[sid].video_nb] = epid; | 987 sp->program[sid].video[sp->program[sid].video_nb] = epid; |
862 sp->program[sid].video_nb += 1; | 988 sp->program[sid].video_nb += 1; |
863 av_flag = 1; | 989 av_flag = TSS_STREAM_TYPE_VIDEO; |
990 #ifdef PmtDebug | |
991 printf(" VIDEO PacketID[%d][0x%04x] StreamType[0x%02x]\n", epid, epid, buf[N]); | |
992 #endif | |
864 } else if ( (buf[N] == 0x04) || (buf[N] == 0x0f) ) { | 993 } else if ( (buf[N] == 0x04) || (buf[N] == 0x0f) ) { |
865 /* 13818-3 Audio or 13818-7 Audio with ADTS transport syntax */ | 994 /* 13818-3 Audio or 13818-7 Audio with ADTS transport syntax */ |
866 sp->program[sid].audio[sp->program[sid].audio_nb] = epid; | 995 sp->program[sid].audio[sp->program[sid].audio_nb] = epid; |
867 sp->program[sid].audio_nb += 1; | 996 sp->program[sid].audio_nb += 1; |
868 av_flag = 2; | 997 av_flag = TSS_STREAM_TYPE_AUDIO; |
998 #ifdef PmtDebug | |
999 printf(" AUDIO PacketID[%d][0x%04x] StreamType[0x%02x]\n", epid, epid, buf[N]); | |
1000 #endif | |
869 } else { | 1001 } else { |
1002 #ifdef PmtDebug | |
1003 printf(" OTHER PacketID[%d][0x%04x] StreamType[0x%02x]\n", epid, epid, buf[N]); | |
1004 #endif | |
870 ; /* A/V どちらでもないものはとりあえずスルー */ | 1005 ; /* A/V どちらでもないものはとりあえずスルー */ |
871 } | 1006 } |
872 if ( av_flag ) { | 1007 if ( av_flag && sp->esout ) { |
873 /* ESバッファはNULLか? */ | 1008 /* ESバッファはNULLか? */ |
874 if ( sp->esbuf[epid] == NULL ) { | 1009 if ( sp->esbuf[epid] == NULL ) { |
875 sp->esbuf[epid] = malloc(sizeof(splitesbuf_t)); | 1010 sp->esbuf[epid] = malloc(sizeof(splitesbuf_t)); |
876 if ( sp->esbuf[epid] == NULL ) { | 1011 if ( sp->esbuf[epid] == NULL ) { |
877 fprintf(stderr, "malloc error\n"); | 1012 fprintf(stderr, "malloc error\n"); |
878 return TSS_NULL; | 1013 return TSS_NULL; |
879 } | 1014 } |
880 sp->esbuf[epid]->size = 0; | 1015 sp->esbuf[epid]->size = 0; |
881 sp->esbuf[epid]->Program = &(sp->program[sid]); | 1016 sp->esbuf[epid]->Program = &(sp->program[sid]); |
882 // creat_filename(sp->filename, sp->esbuf[epid]->filename, sid, epid, av_flag, &(sp->esbuf[epid])); | 1017 sp->esbuf[epid]->fd = -1; |
883 creat_filename(sp, sid, epid, av_flag); | 1018 if ( creat_es_file(sp, sid, epid, av_flag) ) { |
1019 return TSS_ERROR; | |
1020 } | |
884 } | 1021 } |
885 /* PESバッファはNULLか? */ | 1022 /* PESバッファはNULLか? */ |
886 if ( sp->pesbuf[epid] == NULL ) { | 1023 if ( sp->pesbuf[epid] == NULL ) { |
887 sp->pesbuf[epid] = malloc(sizeof(splitpesbuf_t)); | 1024 sp->pesbuf[epid] = malloc(sizeof(splitpesbuf_t)); |
888 if ( sp->pesbuf[epid] == NULL ) { | 1025 if ( sp->pesbuf[epid] == NULL ) { |
895 } | 1032 } |
896 } | 1033 } |
897 // N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1; | 1034 // N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1; |
898 N += 4 + (((buf[N + 3]) & 0x0F) << 8) + buf[N + 4] + 1; | 1035 N += 4 + (((buf[N + 3]) & 0x0F) << 8) + buf[N + 4] + 1; |
899 } | 1036 } |
1037 #ifdef PmtDebug | |
1038 printf("AnalyzePmt finish.\n"); | |
1039 #endif | |
900 return TSS_SUCCESS; | 1040 return TSS_SUCCESS; |
901 } | 1041 } |
902 | 1042 |
903 /** | 1043 /** |
904 * CRC 計算 | 1044 * CRC 計算 |
992 } | 1132 } |
993 | 1133 |
994 /* pesbufにデータを追加 (ret. 0:success / -1:error) */ | 1134 /* pesbufにデータを追加 (ret. 0:success / -1:error) */ |
995 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len){ | 1135 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len){ |
996 if(pesbuf->size + len > sizeof pesbuf->buffer){ | 1136 if(pesbuf->size + len > sizeof pesbuf->buffer){ |
997 //assert(0); | |
998 return -1; | 1137 return -1; |
999 } | 1138 } |
1000 memcpy(pesbuf->buffer +pesbuf->size, data, len); | 1139 memcpy(pesbuf->buffer +pesbuf->size, data, len); |
1001 pesbuf->size += len; | 1140 pesbuf->size += len; |
1002 return 0; | 1141 return 0; |
1031 } | 1170 } |
1032 | 1171 |
1033 /** | 1172 /** |
1034 * TSの解析とDemuxを行う | 1173 * TSの解析とDemuxを行う |
1035 */ | 1174 */ |
1036 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access) | 1175 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid) |
1037 { | 1176 { |
1038 /* | 1177 /* |
1039 * PES先頭までの長さは | 1178 * PES先頭までの長さは |
1040 * 4byte : continity counter | 1179 * 4byte : continity counter |
1041 * 27,28bit が adaptation fileld制御 | 1180 * 27,28bit が adaptation fileld制御 |
1047 int payload_offset; /* ペイロードオフセット(=パケット先頭からのバイト数) */ | 1186 int payload_offset; /* ペイロードオフセット(=パケット先頭からのバイト数) */ |
1048 int payload_length; /* ペイロード長 */ | 1187 int payload_length; /* ペイロード長 */ |
1049 int pes_started; | 1188 int pes_started; |
1050 int adaptation_field_control; | 1189 int adaptation_field_control; |
1051 int payload_unit_start_indicator; | 1190 int payload_unit_start_indicator; |
1052 int random_access_indicator = 0; | 1191 // int random_access_indicator = 0; |
1053 int sid = sp->pid_sid_table[pid]; | 1192 int sid = sp->pid_sid_table[pid]; /* SIDをPIDから引いているが、PCRとCATは重複しているので注意*/ |
1054 | 1193 |
1055 payload_offset = LENGTH_TS_HEADER; | 1194 payload_offset = LENGTH_TS_HEADER; |
1056 | 1195 |
1057 if ( sp->pesbuf[pid] == NULL ) { | 1196 if ( sp->pesbuf[pid] == NULL ) { |
1058 pes_started = 0; /* malloc走る前(セクション解析だったら呼んで良い) */ | 1197 pes_started = 0; /* malloc走る前(セクション解析だったら呼んで良い) */ |
1066 /* ペイロードなしの場合 */ | 1205 /* ペイロードなしの場合 */ |
1067 return 0; /* 別にエラーではない */ | 1206 return 0; /* 別にエラーではない */ |
1068 } else if ( adaptation_field_control == 0x03 ) { | 1207 } else if ( adaptation_field_control == 0x03 ) { |
1069 /* アダプテーションフィールド+ペイロードの場合 */ | 1208 /* アダプテーションフィールド+ペイロードの場合 */ |
1070 if ( packet[LENGTH_TS_HEADER] != 0 ) { | 1209 if ( packet[LENGTH_TS_HEADER] != 0 ) { |
1071 random_access_indicator = (packet[5] & 0x40) >> 6; | 1210 // random_access_indicator = (packet[5] & 0x40) >> 6; |
1072 } | 1211 } |
1073 /* ペイロード開始位置 = TSヘッダ長 + アダプテーションフィールド長 + 1 */ | 1212 /* ペイロード開始位置 = TSヘッダ長 + アダプテーションフィールド長 + 1 */ |
1074 payload_offset += packet[LENGTH_TS_HEADER] + 1; | 1213 payload_offset += packet[LENGTH_TS_HEADER] + 1; |
1075 } else { | 1214 } else { |
1076 /* ペイロードのみ */ | 1215 /* ペイロードのみ */ |
1098 AnalyzePmt(sp, packet +payload_offset, sid, payload_length); | 1237 AnalyzePmt(sp, packet +payload_offset, sid, payload_length); |
1099 /* payload 何byte処理したか等管理するべき */ | 1238 /* payload 何byte処理したか等管理するべき */ |
1100 } | 1239 } |
1101 return 0; /* PMT の場合は処理終わり */ | 1240 return 0; /* PMT の場合は処理終わり */ |
1102 } | 1241 } |
1242 if ( !sp->esout ) { | |
1243 /* ES出力しない場合はPES蓄積不要 */ | |
1244 return 0; | |
1245 } | |
1246 if ( sp->cat_pids[pid] == 1 ) { | |
1247 return 0; /* CATは蓄積しない */ | |
1248 } | |
1249 if ( sp->pesbuf[pid] == NULL ) { | |
1250 /* PES蓄積不要である場合も蓄積しない */ | |
1251 return 0; | |
1252 } | |
1103 | 1253 |
1104 /* payload_unit_start_indicatorを処理(2) */ | 1254 /* payload_unit_start_indicatorを処理(2) */ |
1105 /* 必要に応じ、蓄積済みPESの処理と、PES蓄積開始を行う */ | 1255 /* 必要に応じ、蓄積済みPESの処理と、PES蓄積開始を行う */ |
1106 if( payload_unit_start_indicator ){ | 1256 if( payload_unit_start_indicator ){ |
1107 /* PES開始 */ | 1257 /* PES開始 */ |
1108 if ( pes_started ) { | 1258 if ( pes_started ) { |
1109 /* バッファにデータがあればPES終端なので処理してクリア */ | 1259 /* バッファにデータがあればPES終端なので処理してクリア */ |
1110 pes2es(sp->pesbuf[pid], sp->esbuf[pid], pid, random_access_indicator); | 1260 // pes2es(sp->pesbuf[pid], sp->esbuf[pid], pid, random_access_indicator); |
1261 pes2es(sp->pesbuf[pid], sp->esbuf[pid], pid); | |
1111 pesbuf_clear(sp->pesbuf[pid]); | 1262 pesbuf_clear(sp->pesbuf[pid]); |
1112 } | 1263 } |
1113 else { | 1264 else { |
1114 pes_started = 1; | 1265 pes_started = 1; |
1115 } | 1266 } |
1122 } | 1273 } |
1123 /* おつかれさまでした */ | 1274 /* おつかれさまでした */ |
1124 return 0; | 1275 return 0; |
1125 } | 1276 } |
1126 | 1277 |
1278 #if 0 | |
1279 未使用なため削除 | |
1127 /* PMT_PID から Program(Service ID)を確定させる */ | 1280 /* PMT_PID から Program(Service ID)を確定させる */ |
1128 static int search_pmt_program(splitter *sp, int pid) | 1281 static int search_pmt_program(splitter *sp, int pid) |
1129 { | 1282 { |
1130 /* この関数は大変遅いのでなるべく使用しない */ | 1283 /* この関数は大変遅いのでなるべく使用しない */ |
1131 int i; | 1284 int i; |
1134 return i; | 1287 return i; |
1135 } | 1288 } |
1136 } | 1289 } |
1137 return -1; | 1290 return -1; |
1138 } | 1291 } |
1292 #endif | |
1139 | 1293 |
1140 /* esbufが空か判定 (ret. 0:not empty / 1: empty) */ | 1294 /* esbufが空か判定 (ret. 0:not empty / 1: empty) */ |
1141 static int esbuf_empty(splitesbuf_t *esbuf){ | 1295 static int esbuf_empty(splitesbuf_t *esbuf){ |
1142 return esbuf->size == 0; | 1296 return esbuf->size == 0; |
1143 } | 1297 } |
1144 | 1298 |
1145 /* esbufをクリア */ | 1299 /* esbufをクリア */ |
1146 void esbuf_clear(splitesbuf_t *esbuf){ | 1300 void esbuf_clear(splitesbuf_t *esbuf, uint64_t pts, uint64_t dts){ |
1147 esbuf->random_access_indicator = 0; | |
1148 esbuf->size = 0; | 1301 esbuf->size = 0; |
1302 esbuf->pts = pts; | |
1303 esbuf->dts = dts; | |
1149 } | 1304 } |
1150 | 1305 |
1151 /* esbufにデータを追加 (ret. 0:success / -1:error) */ | 1306 /* esbufにデータを追加 (ret. 0:success / -1:error) */ |
1152 static int esbuf_add(splitesbuf_t *esbuf, const uint8_t *data, int len){ | 1307 static int esbuf_add(splitesbuf_t *esbuf, const uint8_t *data, int len){ |
1153 if(esbuf->size + len > sizeof esbuf->buffer){ | 1308 if(esbuf->size + len > sizeof esbuf->buffer){ |
1159 } | 1314 } |
1160 | 1315 |
1161 /* | 1316 /* |
1162 * PESを解析してESを出力する | 1317 * PESを解析してESを出力する |
1163 */ | 1318 */ |
1164 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator) | 1319 //static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator) |
1320 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) | |
1165 { | 1321 { |
1166 int len_pesh = 0; | 1322 int len_pesh = 0; |
1167 int code = 0; | 1323 int code = 0; |
1168 int flags = 0; | 1324 int flags = 0; |
1169 int len_pes = 0; | 1325 int len_pes = 0; |
1182 int audio_lipsync_offset = 0; | 1338 int audio_lipsync_offset = 0; |
1183 int i = 0; | 1339 int i = 0; |
1184 int64_t audio_pts = 0; | 1340 int64_t audio_pts = 0; |
1185 int adts_freq = 0; | 1341 int adts_freq = 0; |
1186 int64_t adts_frame_time = 0; | 1342 int64_t adts_frame_time = 0; |
1187 int audio_accumulation = 0; | 1343 int gop_start = -1; |
1344 | |
1188 /* ありがとう */ | 1345 /* ありがとう */ |
1189 /* ありがとうとコメントを書くと、 | 1346 /* ありがとうとコメントを書くと、 |
1190 * 動作がよくなる | 1347 * 動作がよくなる |
1191 * バグが減る | 1348 * バグが減る |
1192 * バイナリサイズが小さくなる | 1349 * バイナリサイズが小さくなる |
1395 | 1552 |
1396 p += pes_extension_flags2; | 1553 p += pes_extension_flags2; |
1397 len_pesh_supposed += pes_extension_flags2; | 1554 len_pesh_supposed += pes_extension_flags2; |
1398 } | 1555 } |
1399 } | 1556 } |
1557 if ( pid != 6417 && pid != 6418 ) { | |
1558 // printf("es start? pid[%d]\n", pid); | |
1559 } | |
1560 /* ES蓄積管理処理 */ | |
1400 payload_length = pesbuf->size -payload_offset; | 1561 payload_length = pesbuf->size -payload_offset; |
1401 if ( data_alignment_indicator ) { | 1562 // if ( data_alignment_indicator ) { /* data_alignment_indicator 区切りでESを出力する */ |
1402 if ( es_started ) { /* ES にデータが蓄積されている */ | 1563 if ( es_started ) { /* ES にデータが蓄積されている */ |
1403 if ( is_video_stream(pid, esbuf) && !(esbuf->started) ) { /* VIDEO である場合 */ | 1564 /* |
1404 /* random_access ビットが立っている場合は、GOP先頭である */ | 1565 * ビデオをファイル出力し始める条件(1. 2. を満たすこと) |
1405 if ( random_access_indicator ) { /* TS の random_access ビットが立ったものがきているか? */ | 1566 * 1. ESにGOP先頭を含む |
1406 /* 該当ストリームを蓄積開始する */ | 1567 * 2. PTSがCUEの時刻を過ぎていること( CUE <= PTS ) |
1568 */ | |
1569 if ( (is_video_stream(pid, esbuf) == 0) && !(esbuf->started) ) { | |
1570 /* VIDEO0 を同期の基準とする */ | |
1571 gop_start = search_gop_start_code(esbuf); | |
1572 if ( (gop_start != -1) && /* ESバッファにGOP_START_CODEが存在するか? */ | |
1573 (esbuf->Program->cue <= esbuf->pts*300) ) { /* CUEを過ぎている? */ | |
1574 /* 該当ストリームをファイル出力開始する */ | |
1407 esbuf->started = 1; | 1575 esbuf->started = 1; |
1408 esbuf->Program->video_start = 1; | 1576 esbuf->Program->video_start = 1; |
1409 esbuf->Program->video_pts = esbuf->pts; | 1577 esbuf->Program->video_pts = esbuf->pts; |
1410 printf("video stream. pid[%d] v_pts[%llu].\n", pid, esbuf->pts); | 1578 printf("video stream. pid[%d] v_pts[%llu].\n", pid, esbuf->pts); |
1411 } else { | 1579 } else { |
1412 /* TS の random_access ビットが立ったものがきていない */ | 1580 /* GOP先頭を含まないものはクリア */ |
1413 /* 蓄積開始しない */ | 1581 esbuf_clear(esbuf, pesbuf->pts, pesbuf->dts); |
1414 esbuf_clear(esbuf); | 1582 } |
1415 esbuf->pts = pesbuf->pts; | 1583 } else if ( (is_video_stream(pid, esbuf) != -1) && !(esbuf->started) ) { |
1416 esbuf->dts = pesbuf->dts; | 1584 /* VIDEO0 以外のものはVIDEO0 が開始するまでクリア */ |
1585 if ( !(esbuf->Program->video_start) ) { | |
1586 /* | |
1587 * VIDEO0 が始まってない場合、 | |
1588 * VIDEON は常にクリア | |
1589 */ | |
1590 esbuf_clear(esbuf, pesbuf->pts, pesbuf->dts); | |
1591 } else { | |
1592 /* | |
1593 * VIDEO0 が始まっている場合、 | |
1594 * VIDEON の録画を開始 | |
1595 */ | |
1596 esbuf->started = 1; | |
1417 } | 1597 } |
1418 } | 1598 } |
1419 /* AAC の実験コードここから */ | |
1420 /* | 1599 /* |
1421 * オーディオを出力し始める条件(1. 2. を満たすこと) | 1600 * オーディオをファイル出力し始める条件(1. 2. を満たすこと) |
1422 * 1. 動画の蓄積は開始されている | 1601 * 1. 動画の蓄積は開始されている |
1423 * 2. 動画のGOPの1番目のIピクチャのPTSとオーディオのPTSを比較して以下のどちらかを満たすこと | 1602 * 2. 動画のGOPの1番目のIピクチャのPTSとオーディオのPTSを比較して以下のどちらかを満たすこと |
1424 * 2.1. 差分が11msec以内 | 1603 * 2.1. 差分が11msec以内(1000*90k/AACのサンプリング周波数) |
1604 * 1000 : ADTSデータの1フレームのサンプル数 | |
1605 * 90k : PTSの周波数 | |
1425 * 2.2. 過ぎている(過ぎている場合はオーディオESの蓄積の継続と次のGOP狙いにする?) | 1606 * 2.2. 過ぎている(過ぎている場合はオーディオESの蓄積の継続と次のGOP狙いにする?) |
1426 * #GOP先頭にこだわり過ぎると録画を逃すという線もあるので、適当に手を打つのも手 | 1607 * #動画よりオーディオ側の方が先にESバッファの蓄積を始めるハズなので気にすること無いかなぁ… |
1427 */ | 1608 */ |
1428 else if ( (is_audio_stream(pid, esbuf) != -1 ) && !(esbuf->started) ) { | 1609 else if ( (is_audio_stream(pid, esbuf) != -1) && !(esbuf->started) ) { |
1429 if ( !(esbuf->Program->video_start) ) { | 1610 if ( !(esbuf->Program->video_start) ) { |
1430 /* | 1611 /* |
1431 * VIDEO が始まってない場合、 | 1612 * VIDEO が始まってない場合、 |
1432 * ESバッファの余裕がある限り蓄積続けちゃえばいいんでない? | 1613 * ESバッファの余裕がある限り、オーディオをESバッファに蓄積し続ける |
1433 */ | 1614 */ |
1434 audio_accumulation = 1; /* ESバッファにオーディオを追記する */ | 1615 if ( esbuf->size + payload_length > sizeof esbuf->buffer ){ |
1435 if ( esbuf->size > sizeof esbuf->buffer -payload_length ){ | |
1436 /* 溢れそうになったらクリア */ | 1616 /* 溢れそうになったらクリア */ |
1437 esbuf_clear(esbuf); | 1617 esbuf_clear(esbuf, pesbuf->pts, pesbuf->dts); |
1438 esbuf->pts = pesbuf->pts; | |
1439 esbuf->dts = pesbuf->dts; | |
1440 audio_accumulation = 0; | |
1441 } | 1618 } |
1442 } | 1619 } else if ( esbuf->Program->video_start ) { /* video 蓄積が開始されている?*/ |
1443 else if ( esbuf->Program->video_start ) { /* video 蓄積が開始されているので音声側の頭を揃える */ | 1620 printf("audio stream. pid[%d] a_pts[%llu] v_pts[%llu] size[%d].\n", pid, esbuf->pts, esbuf->Program->video_pts, esbuf->size); |
1444 printf("audio stream. pid[%d] a_pts[%llu] v_pts[%llu].\n", pid, esbuf->pts, esbuf->Program->video_pts); | |
1445 audio_lipsync_offset = 0; | 1621 audio_lipsync_offset = 0; |
1446 audio_pts = esbuf->pts; | 1622 audio_pts = esbuf->pts; |
1447 adts_freq = AnalyzeAdifHeader(esbuf); | 1623 adts_freq = AnalyzeAdifHeader(esbuf); |
1448 adts_frame_time = (int64_t)((float)1000*90000/adts_freq); /* PTSは90KHz */ | 1624 adts_frame_time = (int64_t)((float)1000*90000/adts_freq); /* PTSは90KHz */ |
1625 /* オーディオをフレーム単位で捨ててPTSを進める */ | |
1449 while ( (esbuf->Program->video_pts > audio_pts +adts_frame_time/2) ) { | 1626 while ( (esbuf->Program->video_pts > audio_pts +adts_frame_time/2) ) { |
1450 /* オーディオデータを捨てると audio_pts は1フレーム分大きくなる */ | 1627 /* オーディオデータを捨てると audio_pts は1フレーム分大きくなる */ |
1451 i = esbuf_adts_start_code_prefix(esbuf, audio_lipsync_offset); /* 次のAACのデータを取得 */ | 1628 i = next_adts_start_code(esbuf, audio_lipsync_offset); /* 次のAACのデータを取得 */ |
1452 if ( i != -1 ) { /* AACデータの終端か? */ | 1629 if ( i != -1 ) { /* AACデータの終端か? */ |
1453 audio_lipsync_offset += i; | 1630 audio_lipsync_offset += i; |
1454 } else { | 1631 } else { |
1632 /* バッファ終端まで進めたが、オーディオPTSの方が古い場合ESバッファはクリアする */ | |
1633 esbuf_clear(esbuf, pesbuf->pts, pesbuf->dts); | |
1455 break; | 1634 break; |
1456 } | 1635 } |
1457 printf("audio stream drop. pid[%d] pts[%llu].\n", pid, audio_pts); | 1636 printf("audio stream drop. pid[%d] pts[%llu].\n", pid, audio_pts); |
1458 audio_pts += adts_frame_time; /* AACの1フレーム分、時間を進める */ | 1637 audio_pts += adts_frame_time; /* AACの1フレーム分、時間を進める */ |
1459 } | 1638 } |
1461 printf("lipsync start. v_pts[%llu] a_pts[%llu].\n", esbuf->Program->video_pts, audio_pts); | 1640 printf("lipsync start. v_pts[%llu] a_pts[%llu].\n", esbuf->Program->video_pts, audio_pts); |
1462 memmove(esbuf->buffer +audio_lipsync_offset, | 1641 memmove(esbuf->buffer +audio_lipsync_offset, |
1463 esbuf->buffer, | 1642 esbuf->buffer, |
1464 esbuf->size -audio_lipsync_offset); | 1643 esbuf->size -audio_lipsync_offset); |
1465 esbuf->size -= audio_lipsync_offset; | 1644 esbuf->size -= audio_lipsync_offset; |
1466 esbuf->started = 1; | 1645 esbuf->started = 1; /* オーディオのファイル出力を有効化 */ |
1467 } | 1646 } |
1468 } | 1647 } else { |
1469 else { | |
1470 ; /* 該当するものは無いはず */ | 1648 ; /* 該当するものは無いはず */ |
1471 } | 1649 } |
1650 } else { | |
1651 /* 得に処理なし */ | |
1652 ; | |
1472 } | 1653 } |
1473 /* AAC の実験コードここまで */ | |
1474 /* バッファをファイルに出力してクリア */ | 1654 /* バッファをファイルに出力してクリア */ |
1475 if ( esbuf->started ) { | 1655 if ( esbuf->started ) { /* 該当ストリームはファイル出力の有効化をされている? */ |
1476 esbuf_write(esbuf); | 1656 esbuf_write(esbuf); |
1477 esbuf_clear(esbuf); | 1657 esbuf_clear(esbuf, pesbuf->pts, pesbuf->dts); |
1478 esbuf->pts = pesbuf->pts; | |
1479 esbuf->dts = pesbuf->dts; | |
1480 } | 1658 } |
1481 } else { | 1659 } else { |
1482 /* ES蓄積を新たに開始 */ | 1660 /* ES蓄積を新たに開始 */ |
1483 es_started = 1; | 1661 es_started = 1; |
1484 } | 1662 esbuf->pts = pesbuf->pts; |
1485 } | 1663 esbuf->dts = pesbuf->dts; |
1664 } | |
1665 //} | |
1486 | 1666 |
1487 /* ES蓄積処理 */ | 1667 /* ES蓄積処理 */ |
1488 if ( es_started ) { | 1668 if ( es_started ) { |
1489 if ( ! audio_accumulation ) { /* オーディオのESバッファへの蓄積をしていない */ | |
1490 esbuf->pts = pesbuf->pts; | |
1491 esbuf->dts = pesbuf->dts; | |
1492 } | |
1493 /* ES蓄積開始済み(これからES蓄積開始を含む)なら、payloadをESとして追加 */ | 1669 /* ES蓄積開始済み(これからES蓄積開始を含む)なら、payloadをESとして追加 */ |
1494 esbuf_add(esbuf, pesbuf->buffer +payload_offset, payload_length); | 1670 esbuf_add(esbuf, pesbuf->buffer +payload_offset, payload_length); |
1495 } | 1671 } |
1496 /* お疲れさまでした */ | 1672 /* お疲れさまでした */ |
1497 return 0; | 1673 return 0; |
1498 } | 1674 } |
1499 | 1675 |
1500 /* PIDはesbufのAUDIO STREAMの一つであるか? */ | 1676 /* Program の N 番目の AUDIO STREAM であるかを返却する */ |
1501 static int is_audio_stream(const int pid, splitesbuf_t *esbuf) | 1677 static int is_audio_stream(const int pid, splitesbuf_t *esbuf) |
1502 { | 1678 { |
1503 int i = 0; | 1679 int i = 0; |
1504 int found = 0; | |
1505 program_t* program = esbuf->Program; | 1680 program_t* program = esbuf->Program; |
1506 while (i < program->audio_nb) | 1681 while (i < program->audio_nb) |
1507 { | 1682 { |
1508 if (program->audio[i] == pid) { | 1683 if (program->audio[i] == pid) { |
1509 found = 1; | 1684 return i; |
1510 break; | |
1511 } | 1685 } |
1512 i++; | 1686 i++; |
1513 } | 1687 } |
1514 return found; | 1688 return -1; |
1515 } | 1689 } |
1516 | 1690 |
1517 /* PIDはesbufのVIDEO STREAMの一つであるか? */ | 1691 /* Program の N 番目の VIDEO STREAM であるかを返却する */ |
1518 static int is_video_stream(const int pid, splitesbuf_t *esbuf) | 1692 static int is_video_stream(const int pid, splitesbuf_t *esbuf) |
1519 { | 1693 { |
1520 int i = 0; | 1694 int i = 0; |
1521 int found = 0; | |
1522 program_t* program = esbuf->Program; | 1695 program_t* program = esbuf->Program; |
1523 while (i < program->video_nb) | 1696 while (i < program->video_nb) |
1524 { | 1697 { |
1525 if (program->video[i] == pid) { | 1698 if (program->video[i] == pid) { |
1526 found = 1; | 1699 return i; |
1527 break; | |
1528 } | 1700 } |
1529 i++; | 1701 i++; |
1530 } | 1702 } |
1531 return found; | 1703 return -1; |
1532 } | 1704 } |
1533 | 1705 |
1534 /* | 1706 /* |
1535 * ESをファイル出力する | 1707 * ESをファイル出力する |
1708 * エラーハンドリングしてないね… | |
1536 */ | 1709 */ |
1537 //int esbuf_write(splitesbuf_t *esbuf, int pid) | 1710 static int esbuf_write(splitesbuf_t *esbuf) |
1538 int esbuf_write(splitesbuf_t *esbuf) | |
1539 { | 1711 { |
1540 int remain = esbuf->size; | 1712 int remain = esbuf->size; |
1541 //#define ES_FILE "/tmp/es.%d" | |
1542 // char filename[1024]; | |
1543 // filename[0] = '\0'; | |
1544 // umask(0133); | |
1545 // snprintf(filename, sizeof(filename), ES_FILE, pid); | |
1546 // fd = open(filename, O_CREAT|O_APPEND|O_RDWR, 00644); | |
1547 while(remain > 0) | 1713 while(remain > 0) |
1548 { | 1714 { |
1549 remain -= write(esbuf->fd, esbuf->buffer+(esbuf->size-remain), remain); | 1715 remain -= write(esbuf->fd, esbuf->buffer+(esbuf->size-remain), remain); |
1550 } | 1716 } |
1551 // close(fd); | |
1552 return 0; | 1717 return 0; |
1553 } | 1718 } |
1554 | 1719 |
1720 #if 0 | |
1721 未使用なため駆除 | |
1555 /* | 1722 /* |
1556 * packet dump | 1723 * packet dump |
1557 */ | 1724 */ |
1558 void dump_packet( const uint8_t *packet ) | 1725 void dump_packet( const uint8_t *packet ) |
1559 { | 1726 { |
1579 } | 1746 } |
1580 i++; | 1747 i++; |
1581 } | 1748 } |
1582 putchar('\n'); | 1749 putchar('\n'); |
1583 } | 1750 } |
1751 #endif | |
1584 | 1752 |
1585 /* | 1753 /* |
1586 * TOT の JST_time を解析する | 1754 * TOT の JST_time を解析する |
1587 */ | 1755 */ |
1588 static int parse_tot( const unsigned char* packet, time_t *t ) | 1756 static int parse_tot( const unsigned char* packet, time_t *t ) |
1644 static int get_pmt_version(const uint8_t *p) | 1812 static int get_pmt_version(const uint8_t *p) |
1645 { | 1813 { |
1646 return ((p[6] >> 1) & 0x1f); | 1814 return ((p[6] >> 1) & 0x1f); |
1647 } | 1815 } |
1648 | 1816 |
1649 | |
1650 #if 0 | 1817 #if 0 |
1651 void forward_stc(timespec *stc, timespec offset) | 1818 未使用なため駆除 |
1652 { | |
1653 struct timespec local_timespec; | |
1654 | |
1655 clock_gettime(CLOCK_REALTIME, &local_timespec); | |
1656 | |
1657 stc->tv_sec = local_timespec.tv_sec + offset.tv_sec; | |
1658 stc->tv_nsec = local_timespec.tv_nsec + offset.tv_nsec; | |
1659 if ( stc->tv_nsec >= 1 * 1000 * 1000 * 1000 ) { | |
1660 stc->tv_nsec -= 1 * 1000 * 1000 * 1000; | |
1661 stc->tv_sec += 1; | |
1662 } else if ( stc->tv_nsec < 0 ) { | |
1663 stc->tv_nsec = 1 * 1000 * 1000 * 1000 + stc->tv_nsec; | |
1664 stc->tv_sec -= 1; | |
1665 } | |
1666 } | |
1667 #endif | |
1668 void search_mpeg_system_header(const uint8_t *packet) | 1819 void search_mpeg_system_header(const uint8_t *packet) |
1669 { | 1820 { |
1670 int i; | 1821 int i; |
1671 uint8_t *p = (uint8_t*)packet; | 1822 uint8_t *p = (uint8_t*)packet; |
1672 i = 0; | 1823 i = 0; |
1674 if( p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01 && p[i+3] == 0xb8 ){ | 1825 if( p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01 && p[i+3] == 0xb8 ){ |
1675 dump_packet(packet ); | 1826 dump_packet(packet ); |
1676 } | 1827 } |
1677 } | 1828 } |
1678 } | 1829 } |
1830 #endif | |
1679 | 1831 |
1680 /* | 1832 /* |
1681 * この関数では、現在の仕様では、先頭位置の「次の」ADTS start codeまでの長さを返却する | 1833 * この関数では、現在の仕様では、先頭位置の「次の」ADTS start codeまでの長さを返却する |
1682 * ret == 0 : 仕様上あり得ない | 1834 * ret == 0 : 仕様上あり得ない(esbuf先頭はヘッダ先頭であるため) |
1683 * ret > 0 : 見つかった場合 | 1835 * ret > 0 : 見つかった場合 |
1684 * ret == -1 : 見つからなかった場合 | 1836 * ret == -1 : 見つからなかった場合 |
1685 */ | 1837 */ |
1686 static int esbuf_adts_start_code_prefix(splitesbuf_t *esbuf, int offset) | 1838 static int next_adts_start_code(splitesbuf_t *esbuf, int offset) |
1687 { | 1839 { |
1688 /* | 1840 /* |
1689 * start code prefix のうち、先頭12bit は 1 固定であるが、13bit 目は id に該当 | 1841 * start code prefix のうち、先頭12bit は 1 固定 |
1690 * MPEG4なオーディオが来た場合に対応出来ないので、13bit 目は見ないように改造するべき | |
1691 */ | 1842 */ |
1692 uint8_t adts_start_code_prefix[2] = {0xFF, 0xF8}; /* とりあえず決め打ち */ | 1843 uint16_t adts_start_code = 0xfff0; |
1693 int i = offset +1; | 1844 int i = offset +1; |
1845 uint16_t startcode = 0; | |
1694 | 1846 |
1695 /* 小さすぎる */ | 1847 /* 小さすぎる */ |
1696 if(esbuf->size -offset < sizeof adts_start_code_prefix){ | 1848 if(esbuf->size -offset < sizeof(adts_start_code)){ |
1697 return -1; | 1849 return -1; |
1698 } | 1850 } |
1699 for(; i < esbuf->size - sizeof adts_start_code_prefix; i++) { | 1851 for(; i < esbuf->size - sizeof(adts_start_code); i++) { |
1700 if(!memcmp(esbuf->buffer + i ,adts_start_code_prefix, sizeof adts_start_code_prefix)){ | 1852 startcode = AV_RB16(esbuf->buffer+i); |
1853 if( startcode == adts_start_code ) { /* 該当位置から12bit連続1が立っているか? */ | |
1701 #if 0 | 1854 #if 0 |
1702 printf("adts start code found.i[%d]. 0[%02x] 1[%02x] 2[%02x] 3[%02x] 4[%02x] 5[%02x] 6[%02x]\n", | 1855 printf("adts start code found.i[%d]. 0[%02x] 1[%02x] 2[%02x] 3[%02x] 4[%02x] 5[%02x] 6[%02x]\n", |
1703 i, *(esbuf->buffer+i+0), *(esbuf->buffer+i+1), *(esbuf->buffer+i+2), *(esbuf->buffer+i+3), *(esbuf->buffer+i+4), *(esbuf->buffer+i+5), *(esbuf->buffer+i+6) ); | 1856 i, *(esbuf->buffer+i+0), *(esbuf->buffer+i+1), *(esbuf->buffer+i+2), *(esbuf->buffer+i+3), *(esbuf->buffer+i+4), *(esbuf->buffer+i+5), *(esbuf->buffer+i+6) ); |
1704 #endif | 1857 #endif |
1705 return (i-offset); | 1858 return (i-offset); |
1709 } | 1862 } |
1710 | 1863 |
1711 /* ADIF HEADER解析 */ | 1864 /* ADIF HEADER解析 */ |
1712 static int AnalyzeAdifHeader(splitesbuf_t *esbuf) | 1865 static int AnalyzeAdifHeader(splitesbuf_t *esbuf) |
1713 { | 1866 { |
1714 int id = 0; /* 0:MPEG-4 1:MPEG-2 */ | 1867 int id = 0; /* 0:MPEG-4 1:MPEG-2 */ |
1715 int layer = 0; /* 常に 0x00 */ | 1868 int layer = 0; /* 常に 0x00 */ |
1716 int protection_absent = 0; /*保護属性 0:保護なし 1:保護あり */ | 1869 int protection_absent = 0; /* 保護属性 0:保護なし 1:保護あり */ |
1717 int profile = 0; /* 00:MAIN 01:LC 10:SSR 11:(reserved) */ | 1870 int profile = 0; /* 00:MAIN 01:LC 10:SSR 11:(reserved) */ |
1718 int sampling_frequency_index = 0; /* サンプリング周波数テーブル値 */ | 1871 int sampling_frequency_index = 0; /* サンプリング周波数テーブル値 */ |
1719 int private_bit = 0; /* private bit */ | 1872 int private_bit = 0; /* private bit */ |
1720 int channel_configuration = 0; /* チャンネル数 */ | 1873 int channel_configuration = 0; /* チャンネル数 */ |
1721 int original_copy = 0; | 1874 int original_copy = 0; |
1722 int home = 0; /* homeってなに? */ | 1875 int home = 0; /* homeってなに? */ |
1723 int copyright_identification_bit = 0; /* 著作権証明ビット */ | 1876 int copyright_identification_bit = 0; /* 著作権証明ビット */ |
1724 int copyright_identification_start = 0; /* 著作権証明開始ビット */ | 1877 int copyright_identification_start = 0; /* 著作権証明開始ビット */ |
1725 int aac_frame_length = 0; /* AACフレーム長 */ | 1878 int aac_frame_length = 0; /* AACフレーム長 */ |
1726 int adts_buffer_fullness = 0; /* ADTSバッファ残量 */ | 1879 int adts_buffer_fullness = 0; /* ADTSバッファ残量 */ |
1727 int no_raw_data_blocks_in_frame = 0; /* データブロックまでの残量 */ | 1880 int no_raw_data_blocks_in_frame = 0; /* データブロックまでの残量 */ |
1728 /* | 1881 /* |
1729 * サンプリング周波数テーブル(ヘッダのINDEXが添字) | 1882 * サンプリング周波数テーブル(ヘッダのsampling_frequency_indexが添字) |
1730 * 単位:Hz | 1883 * 単位:Hz |
1731 */ | 1884 */ |
1732 int sampling_frequency_table[16] = | 1885 int sampling_frequency_table[16] = |
1733 { | 1886 { |
1734 96000, | 1887 96000, |
1845 static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p) | 1998 static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p) |
1846 { | 1999 { |
1847 return (*p & 0x03); | 2000 return (*p & 0x03); |
1848 } | 2001 } |
1849 | 2002 |
2003 #define GOP_START_CODE (0x000001b8) | |
1850 /* GOP START CODE を検索する */ | 2004 /* GOP START CODE を検索する */ |
1851 static int search_gop_start_code(splitesbuf_t *esbuf) | 2005 static int search_gop_start_code(splitesbuf_t *esbuf) |
1852 { | 2006 { |
1853 uint8_t gop_start_code[4] = {0x00, 0x00, 0x01, 0xb8}; | 2007 uint32_t gop_start_code = GOP_START_CODE; |
1854 int i; | 2008 int i; |
1855 | 2009 |
1856 /* 小さすぎる */ | 2010 /* 小さすぎる */ |
1857 if ( esbuf->size < sizeof gop_start_code ){ | 2011 if ( esbuf->size < sizeof gop_start_code ){ |
1858 return -1; | 2012 return -1; |
1859 } | 2013 } |
1860 for(i = 0; i < esbuf->size - sizeof gop_start_code; i++) { | 2014 for(i = 0; i < esbuf->size - sizeof gop_start_code; i++) { |
1861 if(!memcmp(esbuf->buffer +i ,gop_start_code, sizeof gop_start_code)){ | 2015 if ( (AV_RB32(esbuf->buffer +i)) == gop_start_code ) { |
1862 return i; | 2016 return i; |
1863 } | 2017 } |
1864 } | 2018 } |
1865 return -1; | 2019 return -1; |
1866 } | 2020 } |
1867 | 2021 |
1868 /* ES 出力するファイル名を決定する */ | 2022 /* ES 出力するファイルを作成する */ |
1869 //static int creat_filename(char *base, char *filename, int sid, int pid, int av_flag ,splitesbuf_t *esbuf) | 2023 static int creat_es_file(splitter *sp, int sid, int pid, int av_flag) |
1870 static int creat_filename(splitter *sp, int sid, int pid, int av_flag) | |
1871 { | 2024 { |
1872 /* | 2025 /* |
1873 * 出力ESファイルの命名規則は以下とする | 2026 * 出力ESファイルの命名規則は以下とする |
1874 * | 2027 * |
1875 * ファイル名のベースは出力TSファイル名 | 2028 * ファイル名のベースは --es オプションの引数 |
1876 * 出力先パスも出力TSファイル名から取得 | 2029 * 以下の形式で命名して、ファイルオープンまで実施する。 |
1877 * ファイル名のうち、「.ts」を削除して、sidとepidをつけて、「.es」とする | 2030 * ファイル名prefix_SID_AVのプログラム内番号.m2v |
1878 * .m2v とか .m2a とかそういう名前って好きではないのだけど...ISOに既定ないし | 2031 * ファイル名prefix_SID_AVのプログラム内番号.aac |
1879 * オーディオなのか、ビデオなのかって情報はあるけど | 2032 * |
2033 * !!注意!! | |
2034 * MPEG-2/MPEG-4 AAC 以外のオーディオが来た場合の処理が未実装 | |
1880 */ | 2035 */ |
1881 | 2036 |
1882 char filename[PATH_MAX]; | 2037 char filename[PATH_MAX]; |
1883 int size = 0; | 2038 int size = 0; |
1884 char *suffix = NULL; | 2039 char *suffix = NULL; |
1885 int av_nb = 0; | 2040 int av_nb = 0; |
1886 char suffix_a[] = "aac"; | 2041 char suffix_a[] = "aac"; |
1887 char suffix_v[] = "m2v"; | 2042 char suffix_v[] = "m2v"; |
1888 filename[0] = '\0'; | 2043 filename[0] = '\0'; |
1889 | 2044 |
1890 if ( av_flag == 1 ) { | 2045 /* ちょっとこの辺のコードイケてないので後から直すかも */ |
2046 if ( av_flag == TSS_STREAM_TYPE_VIDEO ) { | |
1891 suffix = suffix_v; | 2047 suffix = suffix_v; |
1892 av_nb = sp->program[sid].video_nb -1; | 2048 av_nb = sp->program[sid].video_nb -1; |
1893 } else if ( av_flag == 2 ){ | 2049 } else if ( av_flag == TSS_STREAM_TYPE_AUDIO ){ |
1894 suffix = suffix_a; | 2050 suffix = suffix_a; |
1895 av_nb = sp->program[sid].audio_nb -1; | 2051 av_nb = sp->program[sid].audio_nb -1; |
1896 } else { | 2052 } else { |
1897 /* ここはありえない */ | 2053 /* ここはありえない */ |
1898 return -1; | 2054 return -1; |
1899 } | 2055 } |
1900 size = strlen(sp->filename); | 2056 size = strlen(sp->filename); |
1901 | 2057 |
1902 if ( size +16 < sizeof(filename) ) { | 2058 if ( size +16 < sizeof(filename) ) { |
1903 snprintf(filename, sizeof(filename), "%s_%04d_%02d.%s", sp->filename, sid, av_nb, suffix); | 2059 snprintf(filename, sizeof(filename), "%s_%05d_%02d.%s", sp->filename, sid, av_nb, suffix); |
1904 filename[PATH_MAX-1] = '\0'; | 2060 filename[PATH_MAX-1] = '\0'; |
1905 } else { | 2061 } else { |
1906 /* ファイル名つけられなくて困るでござるの巻 */ | 2062 /* ファイル名つけられなくて困るでござるの巻 */ |
1907 return -1; | 2063 return -1; |
1908 } | 2064 } |
1909 umask(0133); | 2065 umask(0133); |
1910 if ( !(sp->esbuf[pid]->fd = open(filename, O_CREAT|O_APPEND|O_RDWR, 00644)) ) { | 2066 if ( !(sp->esbuf[pid]->fd = open(filename, O_CREAT|O_APPEND|O_RDWR, 00644)) ) { |
1911 fprintf("cannot open es out file. file[%s].\n", filename); | 2067 fprintf(stderr, "cannot open es out file. file[%s].\n", filename); |
1912 return -1; | 2068 return -1; |
1913 } | 2069 } |
1914 return 0; | 2070 return 0; |
1915 } | 2071 } |
2072 | |
2073 static time_t cue2time(char *yyyymmddhhmiss) | |
2074 { | |
2075 struct tm cue_tm; | |
2076 time_t cue_time; | |
2077 char *p; | |
2078 int i, j; | |
2079 char str_yyyy[5]; | |
2080 char str_mm[3]; | |
2081 char str_dd[3]; | |
2082 char str_hh[3]; | |
2083 char str_mi[3]; | |
2084 char str_ss[3]; | |
2085 str_yyyy[0] = '\0'; | |
2086 str_mm[0] = '\0'; | |
2087 str_dd[0] = '\0'; | |
2088 str_hh[0] = '\0'; | |
2089 str_mi[0] = '\0'; | |
2090 str_ss[0] = '\0'; | |
2091 | |
2092 p = yyyymmddhhmiss; | |
2093 i = strlen(p); | |
2094 j = strspn(p, LIST_DECIMAL); | |
2095 if ( i != j && i != 14 ) { | |
2096 /* 数字以外混ぜるな */ | |
2097 return -1; | |
2098 } | |
2099 strncpy(str_yyyy, yyyymmddhhmiss, 4); | |
2100 strncpy(str_mm, yyyymmddhhmiss+4, 2); | |
2101 strncpy(str_dd, yyyymmddhhmiss+6, 2); | |
2102 strncpy(str_hh, yyyymmddhhmiss+8, 2); | |
2103 strncpy(str_mi, yyyymmddhhmiss+10, 2); | |
2104 strncpy(str_ss, yyyymmddhhmiss+12, 2); | |
2105 str_yyyy[4] = '\0'; | |
2106 str_mm[2] = '\0'; | |
2107 str_dd[2] = '\0'; | |
2108 str_hh[2] = '\0'; | |
2109 str_mi[2] = '\0'; | |
2110 str_ss[2] = '\0'; | |
2111 | |
2112 cue_tm.tm_sec = atoi(str_ss); | |
2113 cue_tm.tm_min = atoi(str_mi); | |
2114 cue_tm.tm_hour = atoi(str_hh); | |
2115 cue_tm.tm_mday = atoi(str_dd); | |
2116 cue_tm.tm_mon = atoi(str_mm)-1; | |
2117 cue_tm.tm_year = atoi(str_yyyy)-1900; | |
2118 cue_tm.tm_isdst = -1; | |
2119 cue_time = mktime(&cue_tm); | |
2120 return cue_time; | |
2121 } | |
2122 | |
2123 /* PCR の PID を検索する */ | |
2124 static int search_pcr_pid(splitter *sp, int pid) | |
2125 { | |
2126 int i; | |
2127 for ( i=0; i < MAX_SERVICES; i++ ) { | |
2128 if ( sp->pcr[i].pid == pid ) { | |
2129 return i; | |
2130 } | |
2131 } | |
2132 return -1; | |
2133 } |