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 }