Mercurial > pt1.oyama
comparison recpt1/tssplitter_lite.c @ 121:e915d31c5bd9
add --es option
author | Naoya OYAMA <naoya.oyama@gmail.com> |
---|---|
date | Thu, 29 Apr 2010 02:02:42 +0900 |
parents | 8e438d2a1529 |
children | 4009737ea899 |
comparison
equal
deleted
inserted
replaced
120:8e438d2a1529 | 121:e915d31c5bd9 |
---|---|
45 #endif | 45 #endif |
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 | 50 #define MAX_SERVICE_ID ( 0xffff ) |
51 | 51 |
52 /* prototypes */ | 52 /* prototypes */ |
53 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); | 53 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); |
54 static int AnalyzePat(splitter *sp, unsigned char *buf); | 54 static int AnalyzePat(splitter *sp, unsigned char *buf); |
55 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); | 55 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); |
62 static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet); | 62 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); | 63 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access); |
64 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator); | 64 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator); |
65 static int64_t get_pts(const uint8_t *p); | 65 static int64_t get_pts(const uint8_t *p); |
66 void search_mpeg_system_header(const uint8_t *p); | 66 void search_mpeg_system_header(const uint8_t *p); |
67 int esbuf_write(splitesbuf_t *esbuf, int pid); | 67 int esbuf_write(splitesbuf_t *esbuf); |
68 //void forward_stc(timespec *stc, timespec offset); | 68 //void forward_stc(timespec *stc, timespec offset); |
69 static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); | 69 static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); |
70 static int pesbuf_empty(splitpesbuf_t *pesbuf); | 70 static int pesbuf_empty(splitpesbuf_t *pesbuf); |
71 void pesbuf_clear(splitpesbuf_t *pesbuf); | 71 void pesbuf_clear(splitpesbuf_t *pesbuf); |
72 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); | 72 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); |
92 static int get_adif_aac_frame_length(uint8_t *p); | 92 static int get_adif_aac_frame_length(uint8_t *p); |
93 static int get_adts_buffer_fullness(uint8_t *p); | 93 static int get_adts_buffer_fullness(uint8_t *p); |
94 static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p); | 94 static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p); |
95 static int search_pmt_program(splitter *sp, int pid); | 95 static int search_pmt_program(splitter *sp, int pid); |
96 static int search_gop_start_code(splitesbuf_t *esbuf); | 96 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); | |
98 static int creat_filename(splitter *sp, int sid, int pid, int av_flag); | |
97 | 99 |
98 /** | 100 /** |
99 * サービスID解析 | 101 * サービスID解析 |
100 */ | 102 */ |
101 static char** AnalyzeSid( | 103 static char** AnalyzeSid( |
191 | 193 |
192 /** | 194 /** |
193 * 初期化処理 | 195 * 初期化処理 |
194 */ | 196 */ |
195 splitter* split_startup( | 197 splitter* split_startup( |
196 char *sid // [in] サービスID(引数で指定した文字列) | 198 char *sid, // [in] サービスID(引数で指定した文字列) |
199 char *filename // [in] 出力ESファイル名(引数で指定したファイル名) | |
197 ) | 200 ) |
198 { | 201 { |
199 splitter* sp; | 202 splitter* sp; |
200 int i; | 203 int i; |
201 sp = malloc(sizeof(splitter)); | 204 sp = malloc(sizeof(splitter)); |
202 if ( sp == NULL ) | 205 if ( sp == NULL ) |
203 { | 206 { |
204 fprintf(stderr, "split_startup malloc error.\n"); | 207 fprintf(stderr, "split_startup malloc error.\n"); |
205 return NULL; | 208 return NULL; |
206 } | 209 } |
207 #define MAX_SERVICE_ID ( 0xffff ) | |
208 sp->program = malloc( sizeof(program_t) * MAX_SERVICE_ID ); | 210 sp->program = malloc( sizeof(program_t) * MAX_SERVICE_ID ); |
209 if ( sp->program == NULL ) | 211 if ( sp->program == NULL ) |
210 { | 212 { |
211 fprintf(stderr, "split_startup malloc error.\n"); | 213 fprintf(stderr, "split_startup malloc error.\n"); |
212 return NULL; | 214 return NULL; |
238 for ( i=0; i < MAX_PID; i++ ) { | 240 for ( i=0; i < MAX_PID; i++ ) { |
239 /* pmt_version は (N%32) の値を取るので、0 で初期化してはならない */ | 241 /* pmt_version は (N%32) の値を取るので、0 で初期化してはならない */ |
240 sp->program[i].pmt_version = -1; | 242 sp->program[i].pmt_version = -1; |
241 } | 243 } |
242 memset(sp->pid_sid_table, 0, sizeof(int)*MAX_PID); | 244 memset(sp->pid_sid_table, 0, sizeof(int)*MAX_PID); |
243 | 245 // sp->filename = filename; |
246 if ( filename != NULL ) { | |
247 sp->esout = 1; | |
248 sp->filename = filename; | |
249 } | |
244 return sp; | 250 return sp; |
245 } | 251 } |
246 | 252 |
247 /** | 253 /** |
248 * 落とすPIDを確定させる | 254 * 落とすPIDを確定させる |
857 av_flag = 1; | 863 av_flag = 1; |
858 } else if ( (buf[N] == 0x04) || (buf[N] == 0x0f) ) { | 864 } else if ( (buf[N] == 0x04) || (buf[N] == 0x0f) ) { |
859 /* 13818-3 Audio or 13818-7 Audio with ADTS transport syntax */ | 865 /* 13818-3 Audio or 13818-7 Audio with ADTS transport syntax */ |
860 sp->program[sid].audio[sp->program[sid].audio_nb] = epid; | 866 sp->program[sid].audio[sp->program[sid].audio_nb] = epid; |
861 sp->program[sid].audio_nb += 1; | 867 sp->program[sid].audio_nb += 1; |
862 av_flag = 1; | 868 av_flag = 2; |
863 } else { | 869 } else { |
864 ; /* A/V どちらでもないものはとりあえずスルー */ | 870 ; /* A/V どちらでもないものはとりあえずスルー */ |
865 } | 871 } |
866 if ( av_flag ) { | 872 if ( av_flag ) { |
867 /* ESバッファはNULLか? */ | 873 /* ESバッファはNULLか? */ |
871 fprintf(stderr, "malloc error\n"); | 877 fprintf(stderr, "malloc error\n"); |
872 return TSS_NULL; | 878 return TSS_NULL; |
873 } | 879 } |
874 sp->esbuf[epid]->size = 0; | 880 sp->esbuf[epid]->size = 0; |
875 sp->esbuf[epid]->Program = &(sp->program[sid]); | 881 sp->esbuf[epid]->Program = &(sp->program[sid]); |
882 // creat_filename(sp->filename, sp->esbuf[epid]->filename, sid, epid, av_flag, &(sp->esbuf[epid])); | |
883 creat_filename(sp, sid, epid, av_flag); | |
876 } | 884 } |
877 /* PESバッファはNULLか? */ | 885 /* PESバッファはNULLか? */ |
878 if ( sp->pesbuf[epid] == NULL ) { | 886 if ( sp->pesbuf[epid] == NULL ) { |
879 sp->pesbuf[epid] = malloc(sizeof(splitpesbuf_t)); | 887 sp->pesbuf[epid] = malloc(sizeof(splitpesbuf_t)); |
880 if ( sp->pesbuf[epid] == NULL ) { | 888 if ( sp->pesbuf[epid] == NULL ) { |
1415 * 2. 動画のGOPの1番目のIピクチャのPTSとオーディオのPTSを比較して以下のどちらかを満たすこと | 1423 * 2. 動画のGOPの1番目のIピクチャのPTSとオーディオのPTSを比較して以下のどちらかを満たすこと |
1416 * 2.1. 差分が11msec以内 | 1424 * 2.1. 差分が11msec以内 |
1417 * 2.2. 過ぎている(過ぎている場合はオーディオESの蓄積の継続と次のGOP狙いにする?) | 1425 * 2.2. 過ぎている(過ぎている場合はオーディオESの蓄積の継続と次のGOP狙いにする?) |
1418 * #GOP先頭にこだわり過ぎると録画を逃すという線もあるので、適当に手を打つのも手 | 1426 * #GOP先頭にこだわり過ぎると録画を逃すという線もあるので、適当に手を打つのも手 |
1419 */ | 1427 */ |
1420 else if ( is_audio_stream(pid, esbuf) && !(esbuf->started) ) { | 1428 else if ( (is_audio_stream(pid, esbuf) != -1 ) && !(esbuf->started) ) { |
1421 if ( !(esbuf->Program->video_start) ) { | 1429 if ( !(esbuf->Program->video_start) ) { |
1422 /* | 1430 /* |
1423 * VIDEO が始まってない場合、 | 1431 * VIDEO が始まってない場合、 |
1424 * ESバッファの余裕がある限り蓄積続けちゃえばいいんでない? | 1432 * ESバッファの余裕がある限り蓄積続けちゃえばいいんでない? |
1425 */ | 1433 */ |
1463 } | 1471 } |
1464 } | 1472 } |
1465 /* AAC の実験コードここまで */ | 1473 /* AAC の実験コードここまで */ |
1466 /* バッファをファイルに出力してクリア */ | 1474 /* バッファをファイルに出力してクリア */ |
1467 if ( esbuf->started ) { | 1475 if ( esbuf->started ) { |
1468 esbuf_write(esbuf, pid); | 1476 esbuf_write(esbuf); |
1469 esbuf_clear(esbuf); | 1477 esbuf_clear(esbuf); |
1470 esbuf->pts = pesbuf->pts; | 1478 esbuf->pts = pesbuf->pts; |
1471 esbuf->dts = pesbuf->dts; | 1479 esbuf->dts = pesbuf->dts; |
1472 } | 1480 } |
1473 } else { | 1481 } else { |
1524 } | 1532 } |
1525 | 1533 |
1526 /* | 1534 /* |
1527 * ESをファイル出力する | 1535 * ESをファイル出力する |
1528 */ | 1536 */ |
1529 int esbuf_write(splitesbuf_t *esbuf, int pid) | 1537 //int esbuf_write(splitesbuf_t *esbuf, int pid) |
1530 { | 1538 int esbuf_write(splitesbuf_t *esbuf) |
1531 int fd; | 1539 { |
1532 int remain = esbuf->size; | 1540 int remain = esbuf->size; |
1533 #define ES_FILE "/tmp/es.%d" | 1541 //#define ES_FILE "/tmp/es.%d" |
1534 char filename[1024]; | 1542 // char filename[1024]; |
1535 filename[0] = '\0'; | 1543 // filename[0] = '\0'; |
1536 umask(0133); | 1544 // umask(0133); |
1537 snprintf(filename, sizeof(filename), ES_FILE, pid); | 1545 // snprintf(filename, sizeof(filename), ES_FILE, pid); |
1538 fd = open(filename, O_CREAT|O_APPEND|O_RDWR, 00644); | 1546 // fd = open(filename, O_CREAT|O_APPEND|O_RDWR, 00644); |
1539 while(remain > 0) | 1547 while(remain > 0) |
1540 { | 1548 { |
1541 remain -= write(fd, esbuf->buffer+(esbuf->size-remain), remain); | 1549 remain -= write(esbuf->fd, esbuf->buffer+(esbuf->size-remain), remain); |
1542 } | 1550 } |
1543 close(fd); | 1551 // close(fd); |
1544 return 0; | 1552 return 0; |
1545 } | 1553 } |
1546 | 1554 |
1547 /* | 1555 /* |
1548 * packet dump | 1556 * packet dump |
1854 return i; | 1862 return i; |
1855 } | 1863 } |
1856 } | 1864 } |
1857 return -1; | 1865 return -1; |
1858 } | 1866 } |
1867 | |
1868 /* ES 出力するファイル名を決定する */ | |
1869 //static int creat_filename(char *base, char *filename, int sid, int pid, int av_flag ,splitesbuf_t *esbuf) | |
1870 static int creat_filename(splitter *sp, int sid, int pid, int av_flag) | |
1871 { | |
1872 /* | |
1873 * 出力ESファイルの命名規則は以下とする | |
1874 * | |
1875 * ファイル名のベースは出力TSファイル名 | |
1876 * 出力先パスも出力TSファイル名から取得 | |
1877 * ファイル名のうち、「.ts」を削除して、sidとepidをつけて、「.es」とする | |
1878 * .m2v とか .m2a とかそういう名前って好きではないのだけど...ISOに既定ないし | |
1879 * オーディオなのか、ビデオなのかって情報はあるけど | |
1880 */ | |
1881 | |
1882 char filename[PATH_MAX]; | |
1883 int size = 0; | |
1884 char *suffix = NULL; | |
1885 int av_nb = 0; | |
1886 char suffix_a[] = "aac"; | |
1887 char suffix_v[] = "m2v"; | |
1888 filename[0] = '\0'; | |
1889 | |
1890 if ( av_flag == 1 ) { | |
1891 suffix = suffix_v; | |
1892 av_nb = sp->program[sid].video_nb -1; | |
1893 } else if ( av_flag == 2 ){ | |
1894 suffix = suffix_a; | |
1895 av_nb = sp->program[sid].audio_nb -1; | |
1896 } else { | |
1897 /* ここはありえない */ | |
1898 return -1; | |
1899 } | |
1900 size = strlen(sp->filename); | |
1901 | |
1902 if ( size +16 < sizeof(filename) ) { | |
1903 snprintf(filename, sizeof(filename), "%s_%04d_%02d.%s", sp->filename, sid, av_nb, suffix); | |
1904 filename[PATH_MAX-1] = '\0'; | |
1905 } else { | |
1906 /* ファイル名つけられなくて困るでござるの巻 */ | |
1907 return -1; | |
1908 } | |
1909 umask(0133); | |
1910 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); | |
1912 return -1; | |
1913 } | |
1914 return 0; | |
1915 } |