Mercurial > pt1.oyama
changeset 119:4e7aaa72e158
ES out early release version.
author | Naoya OYAMA <naoya.oyama@gmail.com> |
---|---|
date | Mon, 19 Apr 2010 00:30:09 +0900 |
parents | caecbba2a76f |
children | 8e438d2a1529 |
files | recpt1/configure.ac recpt1/tssplitter_lite.c recpt1/tssplitter_lite.h |
diffstat | 3 files changed, 1453 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/recpt1/configure.ac Mon Apr 19 00:17:57 2010 +0900 +++ b/recpt1/configure.ac Mon Apr 19 00:30:09 2010 +0900 @@ -18,6 +18,7 @@ # Checks for libraries. AC_CHECK_LIB([m], [log10]) AC_CHECK_LIB([pthread], [pthread_kill]) +AC_CHECK_LIB([rt], [log10]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT
--- a/recpt1/tssplitter_lite.c Mon Apr 19 00:17:57 2010 +0900 +++ b/recpt1/tssplitter_lite.c Mon Apr 19 00:30:09 2010 +0900 @@ -25,18 +25,79 @@ #include <fcntl.h> #include <sys/stat.h> +#include <math.h> +#include <time.h> #include "decoder.h" #include "recpt1.h" #include "tssplitter_lite.h" +#ifndef AV_RB32 +#define AV_RB32(x) ((((const uint8_t*)(x))[0] << 24) | \ + (((const uint8_t*)(x))[1] << 16) | \ + (((const uint8_t*)(x))[2] << 8) | \ + ((const uint8_t*)(x))[3]) +#endif + +#ifndef AV_RB24 +#define AV_RB24(x) ((((const uint8_t*)(x))[0] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[2]) +#endif + +#ifndef AV_RB16 +#define AV_RB16(x) ((((const uint8_t*)(x))[0] << 8) | ((const uint8_t*)(x))[1]) +#endif + + /* prototypes */ static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); static int AnalyzePat(splitter *sp, unsigned char *buf); static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); static char** AnalyzeSid(char *sid); -static int AnalyzePmt(splitter *sp, unsigned char *buf); +static int AnalyzePmt(splitter *sp, const uint8_t *buf, int sid, const int size); static int GetCrc32(unsigned char *data, int len); static int GetPid(unsigned char *data); +static int parse_tot( const unsigned char* packet, time_t *t ); +void dump_packet( const uint8_t *packet ); +static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet); +//static int parse_pts(int64_t *ppts, int64_t *pdts, const uint8_t *packet, int *len_pes, splitesbuf_t *esbuf, const int pid); +//static int ts2pes(int64_t *ppts, int64_t *pdts, const uint8_t *packet, splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid); +static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access); +static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid); +static int64_t get_pts(const uint8_t *p); +void search_mpeg_system_header(const uint8_t *p); +int esbuf_write(splitesbuf_t *esbuf, int pid); +//void forward_stc(timespec *stc, timespec offset); +// + +static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); +static int pesbuf_empty(splitpesbuf_t *pesbuf); +void pesbuf_clear(splitpesbuf_t *pesbuf); +static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); +static int esbuf_empty(splitesbuf_t *esbuf); +void esbuf_clear(splitesbuf_t *esbuf); +static int esbuf_add(splitesbuf_t *esbuf, const uint8_t *data, int len); +static int get_pmt_version(const uint8_t *p); +static int esbuf_adts_start_code_prefix(splitesbuf_t *esbuf, int offset); +static int is_video_stream(const int pid, splitesbuf_t *esbuf); +static int is_audio_stream(const int pid, splitesbuf_t *esbuf); +static int AnalyzeAdifHeader(splitesbuf_t *esbuf); +static int get_adif_id(uint8_t *p); +static int get_adif_layer(uint8_t *p); +static int get_adif_protection_absent(uint8_t *p); +static int get_adif_profile(uint8_t *p); +static int get_adif_sampling_frequency_index(uint8_t *p); +static int get_adif_private_bit(uint8_t *p); +static int get_adif_channel_configuration(uint8_t *p); +static int get_adif_original_copy(uint8_t *p); +static int get_adif_home(uint8_t *p); +static int get_adif_copyright_idication_bit(uint8_t *p); +static int get_adif_copyright_idication_start(uint8_t *p); +static int get_adif_aac_frame_length(uint8_t *p); +static int get_adts_buffer_fullness(uint8_t *p); +static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p); +static int search_pmt_program(splitter *sp, int pid); +static int search_gop_start_code(splitesbuf_t *esbuf); /** * ¥µ¡¼¥Ó¥¹ID²òÀÏ @@ -140,12 +201,20 @@ ) { splitter* sp; + int i; sp = malloc(sizeof(splitter)); if ( sp == NULL ) { fprintf(stderr, "split_startup malloc error.\n"); return NULL; } +#define MAX_SERVICE_ID ( 0xffff ) + sp->program = malloc( sizeof(program_t) * MAX_SERVICE_ID ); + if ( sp->program == NULL ) + { + fprintf(stderr, "split_startup malloc error.\n"); + return NULL; + } memset(sp->pids, 0, sizeof(sp->pids)); memset(sp->pmt_pids, 0, sizeof(sp->pmt_pids)); @@ -160,6 +229,21 @@ sp->pat_count = 0xFF; sp->pmt_retain = -1; sp->pmt_counter = 0; +// sp->STC_timespec.tv_sec = 0; +// sp->STC_timespec.tv_nsec = 0; +// sp->tot_offset.tv_sec = 0; +// sp->tot_offset.tv_nsec = 0; + sp->cue_time = -1; + sp->stc = 0; + sp->status = 1; + memset(sp->esbuf, 0, sizeof(splitesbuf_t *)*MAX_PID); + memset(sp->pesbuf, 0, sizeof(splitpesbuf_t *)*MAX_PID); + memset(sp->program, 0, sizeof(program_t *)*MAX_SERVICE_ID); + for ( i=0; i < MAX_PID; i++ ) { + /* pmt_version ¤Ï (N%32) ¤ÎÃͤò¼è¤ë¤Î¤Ç¡¢0 ¤Ç½é´ü²½¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤ */ + sp->program[i].pmt_version = -1; + } + memset(sp->pid_sid_table, 0, sizeof(int)*MAX_PID); return sp; } @@ -213,8 +297,8 @@ char** sid_list, // [in] ½ÐÎÏÂоݥµ¡¼¥Ó¥¹ ID ¤Î¥ê¥¹¥È unsigned char* pmt_pids, // [in] ½ÐÎÏÂоÝPID¤ÎPMT PID , // [in] pt1_drv¤ÎÆþÎÏTS - int* pmt_retain, // [in] »Ä¤¹¤Ù¤PMT¤Î¿ô - int* pmt_counter // [out] »Ä¤·¤¿PMT¤Î¿ô + int* pmt_retain, // [in] PMT¤ÎÍî¤È¤¹¤Ù¤¿ô + int* pmt_counter // [out] PMT¤ÎÍî¤È¤·¤¿¿ô #endif int length = sbuf->size; @@ -226,7 +310,8 @@ while(length - index - LENGTH_PACKET > 0) { pid = GetPid(sbuf->data + index + 1); // PAT - if(0x0000 == pid) { + if(PAT == pid) { + dump_packet(sbuf->data + index); result = AnalyzePat(sp, sbuf->data + index); if(TSS_SUCCESS != result) { /* ²¼°Ì¤Î´Ø¿ôÆâÉô¤Çmalloc errorȯÀ¸ */ @@ -238,10 +323,17 @@ /* »Ä¤¹pmt_pid¤Ç¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢pmt¤Ë½ñ¤«¤ì¤Æ¤¤¤ë * »Ä¤¹¤Ù¤PCR/AUDIO/VIDEO PID¤ò¼èÆÀ¤¹¤ë */ if(sp->pmt_pids[pid] == 1) { + /* + * program(ÈÖÁÈ)¤ÈServiceID ¤ò¥Ù¡¼¥¹¤Ë´ÉÍý¤¹¤ë¤³¤È¤Ë¤·¤Æ¤¤¤ë¤Î¤Ç¡¢ + * pmt_pids¤È¤«¤â¤¦É¬Íפʤ¤¤«¤â¡Ä + */ /* ¤³¤ÎÃæ¤Ë¤ÏPMTËè¤Ë°ìÅÙ¤·¤«Æþ¤é¤Ê¤¤¤è¤¦¤Ë¤·¤Æ¤ª¤¯ */ - AnalyzePmt(sp, sbuf->data + index); + int random_access; + //AnalyzePmt(sp, sbuf->data + index, pid); + //AnalyzePmt(sp, sbuf->data + index +4, pid, LENGTH_PACKET-4); sp->pmt_pids[pid]++; sp->pmt_counter += 1; + DemuxTs(sbuf->data +index, sp, pid, &random_access); /* AnalyzePmt ¤è¤ê DemuxTs ¤ÎÊý¤¬¥¢¥À¥×¥Æ¡¼¥·¥ç¥ó¥Õ¥£¡¼¥ë¥É¤Î½èÍý¤¬Îɤ¤¤Î¤ÇÊѹ¹ */ } /* Ï¿²è¤¹¤ëÁ´¤Æ¤ÎPMT¤Ë¤Ä¤¤¤Æ¡¢Ãæ¤Ë¤¢¤ëPCR/AUDIO/VIDEO¤ÎPID¤ò * ÆÀ¤ë */ @@ -272,6 +364,14 @@ unsigned char *sptr, *dptr; int s_offset = 0; int d_offset = 0; + int64_t pcr; + int64_t pcr_h; + int pcr_l; + struct timespec tot_timespec; + struct timespec local_timespec; + int len_pes; + int random_access; + int sid; /* ½é´ü²½ */ dbuf->size = 0; @@ -281,22 +381,26 @@ sptr = sbuf->data; dptr = dbuf->buffer; +#if 0 + /* TOT¼õ¿®ºÑ¤ß¤Ç¤¢¤ë¤Ê¤é¡¢STC ¤òÀ®Ä¹¤µ¤»¤ë */ + if ( sp->tot_offset.tv_nsec != 0 && sp->tot_offset.tv_sec != 0) { + forward_stc(&(sp->STC_timespec), sp->tot_offset); + } +#endif while(sbuf->size > s_offset) { pid = GetPid(sptr + s_offset + 1); + sid = splitter->pid_sid_table[pid]; switch(pid) { // PAT - case 0x0000: + case PAT: // ½ä²ó¥«¥¦¥ó¥¿¥«¥¦¥ó¥È¥¢¥Ã¥× if(0xFF == splitter->pat_count) { splitter->pat_count = splitter->pat[3]; } else { - splitter->pat_count += 1; - if(0 == splitter->pat_count % 0x10) { - splitter->pat_count -= 0x10; - } + splitter->pat_count = (splitter->pat_count + 1) % 16; } splitter->pat[3] = splitter->pat_count; @@ -304,12 +408,101 @@ d_offset += LENGTH_PACKET; dbuf->size += LENGTH_PACKET; break; + case TOT: + /* TOT ¤Ë TDT¤Î¾ðÊóÁ´¤Æ¤¬´Þ¤Þ¤ì¤Æ¤ª¤ê¡¢¼ÂÊüÁ÷¤Ç¤Ï TOT ¤·¤«Á÷¿®¤µ¤ì¤Ê¤¤ */ + /* TOT ¤Ï 500msec ¤Î¸íº¹¤¬Êݾڤµ¤ì¤Æ¤¤¤ë + * ±¼Éäξì¹ç¤ÏºÇÂç1.5ÉÃ¤Î¸íº¹¤È¤Ê¤ë + */ +#if 0 + if ( sp->tot_offset.tv_nsec != 0 && sp->tot_offset.tv_sec != 0 ) { + parse_tot(sptr + s_offset, &(tot_timespec.tv_sec)); + clock_gettime(CLOCK_REALTIME, &local_timespec); + + /* TOT ¤òSystem Time Clock(STC)¤ËÆþ¤ì¤ë */ + sp->STC_timespec.tv_sec = tot_timespec.tv_sec; + sp->STC_timespec.tv_nsec = tot_timespec.tv_nsec; + + /* TOT ¤È localtime ¤Îº¹Ê¬¤ò sp->tot_offset ¤ËÆþ¤ì¤ë */ + sp->tot_offset.tv_sec = tot_timespec.tv_sec - local_timespec.tv_sec; + sp->tot_offset.tv_nsec = tot_timespec.tv_nsec - local_timespec.tv_nsec; + } +#endif + /* STC ¤¬´û¤Ë¤¢¤ë¤Ê¤éTOT¼õ¿®»þ¤ËƬ½Ð¤·»þ¹ï¤ò·èÄꤹ¤ë */ + /* 59ÉÃ9990 ¤¢¤¿¤ê¤òƬ½Ð¤·»þ¹ï¤ËÀßÄê¤Ç¤è¤¤¤«¤Ê */ + if ( splitter->stc != 0 && splitter->cue_time == -1) { + /* TOT ¤«¤é cue_time ¤ò·×»»¤¹¤ë */ + /* ¤¨¤¤¤ä¡£¤Ç¡¢59ÉÃ9990¸ÇÄê·è¤áÂǤÁ */ + parse_tot(sptr + s_offset, &(tot_timespec.tv_sec)); + //cue_second = ((tot_timespec.tv_sec % 60) - 59); + splitter->cue_time = splitter->stc + (((59 - (tot_timespec.tv_sec % 60))*(27*1000*1000)) + floor((27*1000*1000)*0.999)); + //printf("stc[%lld]. cue_time[%lld].\n", splitter->stc, splitter->cue_time); + + } else { + /* TOT¼õ¿Ç»þ¤ËSTC¤¬Â¸ºß¤·¤Ê¤¤¤Ê¤éTOT¤Ï¼Î¤Æ¤ë */ + } + break; default: + /* »þ´Ö´ÉÍý¤Ë´Ø¤·¤Æ¤Î¼ÂÁõÊý¿Ë */ + /* + * »þ´Ö´Ø·¸¤ò°·¤Ã¤Æ¤¤¤ëÊÑ¿ô¤Î¤Þ¤È¤á + * PCR : 42Bit @27MHz(¥×¥í¥°¥é¥àËè¤ËÆÈΩ) + * PTS : 42Bit @90KHz(SYSTEM ID(ES)Ëè¤ËÆÈΩ) + * DTS : 42Bit @90KHz(SYSTEM ID(ES)Ëè¤ËÆÈΩ) + * TOT : MJD + 2¿Ê²½10¿Ê¿ô(¥¹¥È¥ê¡¼¥à¤Ë°ì¤Ä¤À¤±) + * STC : 64Bit @27MHz(¥·¥¹¥Æ¥à¥í¡¼¥«¥ë»þ¹ï(¥½¡¼¥¹¤ÏTOT)) + * + * STC ¤È TOT ¤Î´ØÏ¢¤À¤±·×»»½ÐÍè¤ë¤è¤¦¤Ë¤·¤Æ¤ª¤¤¤Æ¡¢ + * ½ÐÎϤ¹¤ë¤è¤¦¤Ë¤¹¤ë/¤·¤Ê¤¤¤ÎȽÄê¤ÏÁ´ÂÎŪ¤Ë¡¢ + * STC¤«¤éTOT¤ò»È¤Ã¤Æ½Ð¤·¤¿»þ¹ï¾ðÊó¤È¤¹¤ë¡£¤«¤Ê¤¡¡£ + * PCR/PTS/DTS¤Ï¥ª¡¼¥Ð¡¼¥Õ¥í¡¼¤·¤¿¤È¤¤Ë¤Ï34BitÌܤ¬Î©¤Ã¤Æ¤¤¤ë¤È¸«¤Ê¤¹¤³¤È + */ +// if ( 1 == splitter->pmt_pids[pid] ) { + if ( 2 == splitter->pmt_pids[pid] ) { + /* PMT ¤ÎÄÉÀ× */ + int random_access; + DemuxTs((sptr+s_offset), splitter, pid, &random_access); + } /* pids[pid] ¤¬ 1 ¤Ï»Ä¤¹¥Ñ¥±¥Ã¥È¤Ê¤Î¤Ç½ñ¤¹þ¤à */ - if(1 == splitter->pids[pid]) { - memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); - d_offset += LENGTH_PACKET; - dbuf->size += LENGTH_PACKET; + if ( 1 == splitter->pids[pid] ) { + len_pes = 0; + random_access = 0; + /* PCR ²òÀϥƥ¹¥È */ + if (parse_pcr(&pcr_h, &pcr_l, (sptr+s_offset)) == 0){ + pcr = pcr_h * 300 + pcr_l; + /* PCR ¤Î¼ï¤Ë¤¹¤ë¤â¤Î¤Ï¡¢Program ¤Î PCR ¤È¤·¤Æ»ØÄꤵ¤ì¤¿PacketID¤Î¤â¤Î¤È¤¹¤ë¤³¤È */ + /* STC ¤Ï PCR ¤ò¼ï¤Ë¤¹¤ë */ + splitter->stc = pcr; +// printf("PID[%d] pcr_h=[%llx] pcr_l=[%d] PCR[%f]\n",pid, pcr_h, pcr_l, ((double)pcr/(90000*300))); + } + /* TS½èÍý */ + if (DemuxTs((sptr+s_offset), splitter, pid, &random_access) == 0 ) { +#if 0 + /* ¤È¤ê¤¢¤¨¤º¤ä¤Ã¤Ä¤± */ + /* ¥Ñ¥±¥Ã¥È¤Î²èÌÌɽ¼¨»þ¹ï(pts) >= Ï¿²è³«»Ï»þ¹ï(cue_time) ¤È¤Ê¤Ã¤¿¾ì¹ç¤ËÏ¿²è³«»Ï */ +// if ( ((pts*300) >= splitter->cue_time) && (splitter->cue_time != -1)) { + if ( ((splitter->esbuf[pid].pts) >= splitter->program[sid].cue_time) && (splitter->program[sid].cue_time != -1)) { + splitter->cue_time = 0; + splitter->status = 0; + clock_gettime(CLOCK_REALTIME, &local_timespec); + printf("start recording. time_sec[%d] nsec[%d].\n", local_timespec.tv_sec%60, local_timespec.tv_nsec); + } +#endif + } + //search_mpeg_system_header(sptr+s_offset); + /* + * STC¤¬ cue_time ¤ò·Ð²á¤·¤¿¤éÏ¿²è³«»Ï + */ + if ( splitter->cue_time != -1 && splitter->cue_time <= splitter->stc ) { + memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); + d_offset += LENGTH_PACKET; + dbuf->size += LENGTH_PACKET; + if ( splitter->status ) { + struct timespec local_timespec; + clock_gettime(CLOCK_REALTIME, &local_timespec); + printf("start recording. time_sec[%d] nsec[%d].\n", local_timespec.tv_sec%60, local_timespec.tv_nsec); + splitter->status = 0; + } + } } break; } /* switch */ @@ -385,6 +578,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); p++; continue; @@ -398,6 +593,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); } p++; @@ -412,6 +609,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); } p++; @@ -426,6 +625,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); } p++; @@ -440,6 +641,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); } p++; @@ -453,6 +656,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); break; } @@ -471,6 +676,8 @@ pos[pid] = i; sid_found = TRUE; sp->pmt_retain += 1; + sp->program[service_id].pmt_packet_id = pid; + sp->pid_sid_table[pid] = service_id; sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); } } @@ -577,10 +784,12 @@ * PMT ²òÀϽèÍý * * PMT ¤ò²òÀϤ·¡¢ÊݸÂоݤΠPID ¤òÆÃÄꤹ¤ë + * TS¥Ø¥Ã¥À¤È¥¢¥À¥×¥Æ¡¼¥·¥ç¥ó¥Õ¥£¡¼¥ë¥É¤Î½èÍý¤Ï DemuxTs ¤Ë°ìǤ¤¹¤ë¤Î¤Ç¡¢ + * ¤³¤ÎÆâÉô¤Ç¤Ï¡¢¥»¥¯¥·¥ç¥ó¥Ç¡¼¥¿¤ÎÀèƬ¥Ý¥¤¥ó¥¿¤ò¤â¤é¤Ã¤Æ¤¯¤ë */ -static int AnalyzePmt(splitter *sp, unsigned char *buf) +static int AnalyzePmt(splitter *sp, const uint8_t *buf, int sid, const int size) #if 0 - unsigned char* buf, // [in] Æɤ߹þ¤ó¤À¥Ð¥Ã¥Õ¥¡ + unsigned char* buf, // [in] ¥»¥¯¥·¥ç¥óÀèƬ unsigned char* pids) // [out] ½ÐÎÏÂÐ¾Ý PID ¾ðÊó #endif { @@ -588,48 +797,102 @@ unsigned char N; int pcr; int epid; + int av_flag = 0; - Nall = ((buf[6] & 0x0F) << 4) + buf[7]; - if(Nall > LENGTH_PACKET) - Nall = LENGTH_PACKET - 8; /* xxx workaround --yaz */ +// Nall = ((buf[2] & 0x0F) << 4) + buf[3]; + Nall = ((buf[2] & 0x0F) << 8) + buf[3]; + + /* get version */ + sp->program[sid].pmt_version = get_pmt_version(buf); // PCR - pcr = GetPid(&buf[13]); + pcr = GetPid(&buf[9]); sp->pids[pcr] = 1; + sp->program[sid].pcr_packet_id = pcr; - N = ((buf[15] & 0x0F) << 4) + buf[16] + 16 + 1; +// N = ((buf[11] & 0x0F) << 4) + buf[12] + 16 + 1; + N = ((buf[11] & 0x0F) << 8) + buf[12] + 12 + 1; +// printf("NAll[%d] N[%d]\n", Nall, N); - // ECM - int p = 17; - while(p < N) { - uint32_t ca_pid; - uint32_t tag; - uint32_t len; - - tag = buf[p]; - len = buf[p+1]; - p += 2; - - if(tag == 0x09 && len >= 4 && p+len <= N) { - ca_pid = ((buf[p+2] << 8) | buf[p+3]) & 0x1fff; - sp->pids[ca_pid] = 1; - } - p += len; - } + /* + * ISO/IEC 13818-1:2000(E) Table 2-29 - Stream type assignments + * Value Desctiption + * 0x00 ITU-T | ISO/IEC Reserved + * 0x01 ISO/IEC 11172 Video + * 0x02 ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrained parameter video stream + * 0x03 ISO/IEC 11172 Audio + * 0x04 ISO/IEC 13818-3 Audio + * 0x05 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections + * 0x06 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing private data + * 0x07 ISO/IEC 13522 MHEG + * 0x08 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A DSM-CC + * 0x09 ITU-T Rec. H.222.1 + * 0x0A ISO/IEC 13818-6 type A + * 0x0B ISO/IEC 13818-6 type B + * 0x0C ISO/IEC 13818-6 type C + * 0x0D ISO/IEC 13818-6 type D + * 0x0E ITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary + * 0x0F ISO/IEC 13818-7 Audio with ADTS transport syntax + * 0x10 ISO/IEC 14496-2 Visual + * 0x11 ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3 / AMD 1 + * 0x12 ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets + * 0x13 ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC14496_sections. + * 0x14 ISO/IEC 13818-6 Synchronized Download Protocol + * 0x15-0x7F ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved + * 0x80-0xFF User Private + * + */ // ES PID while (N < Nall + 8 - 4) { + av_flag = 0; + if ( N > size ) { + break; + } // ¥¹¥È¥ê¡¼¥à¼ïÊ̤¬ 0x0D¡Êtype D¡Ë¤Ï½ÐÎÏÂоݳ° if (0x0D != buf[N]) { epid = GetPid(&buf[N + 1]); - sp->pids[epid] = 1; + if ( buf[N] == 0x02 ) { /* 13818-2 Video */ + sp->program[sid].video[sp->program[sid].video_nb] = epid; + sp->program[sid].video_nb += 1; + av_flag = 1; + } else if ( (buf[N] == 0x04) || (buf[N] == 0x0f) ) { + /* 13818-3 Audio or 13818-7 Audio with ADTS transport syntax */ + sp->program[sid].audio[sp->program[sid].audio_nb] = epid; + sp->program[sid].audio_nb += 1; + av_flag = 1; + } else { + ; /* A/V ¤É¤Á¤é¤Ç¤â¤Ê¤¤¤â¤Î¤Ï¤È¤ê¤¢¤¨¤º¥¹¥ë¡¼ */ + } + if ( av_flag ) { + /* ES¥Ð¥Ã¥Õ¥¡¤ÏNULL¤«¡© */ + if ( sp->esbuf[epid] == NULL ) { + sp->esbuf[epid] = malloc(sizeof(splitesbuf_t)); + if ( sp->esbuf[epid] == NULL ) { + fprintf(stderr, "malloc error\n"); + return TSS_NULL; + } + sp->esbuf[epid]->size = 0; + sp->esbuf[epid]->Program = &(sp->program[sid]); + } + /* PES¥Ð¥Ã¥Õ¥¡¤ÏNULL¤«¡© */ + if ( sp->pesbuf[epid] == NULL ) { + sp->pesbuf[epid] = malloc(sizeof(splitpesbuf_t)); + if ( sp->pesbuf[epid] == NULL ) { + fprintf(stderr, "malloc error\n"); + return TSS_NULL; + } + sp->pesbuf[epid]->size = 0; + sp->pesbuf[epid]->Program = &(sp->program[sid]); + } + } } - N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1; +// N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1; + N += 4 + (((buf[N + 3]) & 0x0F) << 8) + buf[N + 4] + 1; } - return TSS_SUCCESS; } @@ -684,3 +947,1019 @@ { return ((data[0] & 0x1F) << 8) + data[1]; } + +/* return the 90kHz PCR and the extension for the 27MHz PCR. return + (-1) if not available */ +static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, + const uint8_t *packet) +{ + int afc, len, flags; + const uint8_t *p; + unsigned int v; + + afc = (packet[3] >> 4) & 3; + if (afc <= 1) + return -1; + p = packet + 4; + len = p[0]; + p++; + if (len == 0) + return -1; + flags = *p++; + len--; + if (!(flags & 0x10)) + return -1; + if (len < 6) + return -1; + v = AV_RB32(p); + *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7); + *ppcr_low = ((p[4] & 1) << 8) | p[5]; + return 0; +} + +#if 0 +/** + * TS¤ò²òÀϤ·¤ÆPES¤ò½ÐÎϤ¹¤ë + */ +static int ts2pes(int64_t *ppts, int64_t *pdts, const uint8_t *packet, splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) +{ + /* Á´ÂÎŪ¤Ë length ¤¬packetĹ±Û¤¨¤¿»þ¤Î½èÍý¤òÄɵ¤¹¤ë¤³¤È */ + /* + * PESÀèƬ¤Þ¤Ç¤ÎŤµ¤Ï + * 4byte : continity counter + * 27,28bit ¤¬ adaptation fileldÀ©¸æ + * (01:¥Ú¥¤¥í¡¼¥É¤Î¤ß, 10:adaptation fileld¤Î¤ß¡¢11:adaptation fileld+payload¡¢00:reserved) + * ¥Ú¥¤¥í¡¼¥ÉĹ = 188 - TS header(4byte) -adaptation fieldĹ -1 + */ + int len_afh = 0; + *ppts = -1; + *pdts = -1; + int flags = 0; + const uint8_t *p; + p = (uint8_t*)packet; + + flags = (p[3] & 0x30) >> 4; + if ( flags == 0x02 || flags == 0x00) { + /* ¥Ú¥¤¥í¡¼¥É¤Ê¤· */ + return -1; + } else if ( flags == 0x03 ) { + /* ¥¢¥À¥×¥Æ¡¼¥·¥ç¥ó¥Õ¥£¡¼¥ë¥É¡Ü¥Ú¥¤¥í¡¼¥É */ + /* ¥¢¥À¥×¥Æ¡¼¥·¥ç¥ó¥Õ¥£¡¼¥ë¥ÉĹ */ + len_afh = *(p+LENGTH_TS_HEADER) & 0xff; + if ( len_afh > LENGTH_PACKET -LENGTH_TS_HEADER ) { + return -1; + } + if (!(p[1] & 0x40)) { + /* payload start unit indicator ȯ¸« */ + if ( pesbuf->size != 0 ) { + pes2es(ppts, pdts, pesbuf, esbuf, pid); + pesbuf->size = 0; + } + memcpy(pesbuf->buffer + pesbuf->size, + packet +LENGTH_TS_HEADER +len_afh +1, + LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1); + pesbuf->size += LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1; + } + /* PESÀèƬ¥Ñ¥±¥Ã¥È¤Ç¤Ï¤Ê¤¤¤Î¤Ç¥Ð¥Ã¥Õ¥¡¤Ë½ñ¤¹þ¤ß */ + if ( pesbuf->size != 0 ) { + memcpy(pesbuf->buffer + pesbuf->size, + packet +LENGTH_TS_HEADER +len_afh +1, + LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1); + pesbuf->size += LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1; + } + } else { + /* ¥Ú¥¤¥í¡¼¥É¤Î¤ß */ + /* TS¥Ø¥Ã¥À¤ò¼è¤ê½ü¤¤¤ÆPES¥Ð¥Ã¥Õ¥¡½ñ¤¹þ¤ß */ + if ( pesbuf->size != 0 ) { + memcpy(pesbuf->buffer +pesbuf->size, + packet +LENGTH_TS_HEADER, + LENGTH_PACKET -LENGTH_TS_HEADER); + pesbuf->size += LENGTH_PACKET -LENGTH_TS_HEADER; + } + } + return 0; +} +#endif + +/* pesbuf¤¬¶õ¤«È½Äê (ret. 0:not empty / 1: empty) */ +static int pesbuf_empty(splitpesbuf_t *pesbuf){ + return pesbuf->size == 0; +} + +/* pesbuf¤ò¥¯¥ê¥¢ */ +void pesbuf_clear(splitpesbuf_t *pesbuf){ + pesbuf->size = 0; +} + +/* pesbuf¤Ë¥Ç¡¼¥¿¤òÄɲà (ret. 0:success / -1:error) */ +static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len){ + if(pesbuf->size + len > sizeof pesbuf->buffer){ + //assert(0); + return -1; + } + memcpy(pesbuf->buffer +pesbuf->size, data, len); + pesbuf->size += len; + return 0; +} + +/* pesbuf¤«¤é¡¢PES¤ÎÀèƬ(packet_start_code_prefix)¤òõ¤¹ */ +/* (ret. >=0:offset / -1: error) */ +static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf){ + uint8_t packet_start_code_prefix[3] = {0x00, 0x00, 0x01}; + int i = 0; + + /* ¾®¤µ¤¹¤®¤ë */ + if(pesbuf->size < sizeof packet_start_code_prefix){ + return -1; + } + /* ÀèƬ¤Çõ¤¹ */ + if(!memcmp(pesbuf->buffer + i, packet_start_code_prefix, sizeof packet_start_code_prefix)){ + return 0; + } + +#if 0 + /* ÀèƬ°Ê³°¤«¤é¤âõ¤¹¾ì¹ç¤Ï¡¢¤³¤³¤Î¥³¡¼¥É¤ò͸ú²½¤¹¤ë¡£ */ + /* ¤¿¤À¤·¡¢MPEG-Video¤Îstart_code¤ÈƱ¤¸¤Ê¤Î¤Ç¡¢¿¼Äɤ¤¤·¤Ê¤¤Êý¤¬¤¤¤¤¤È»×¤¦... */ + for(i = 0; i < pesbuf->size - sizeof packet_start_code_prefix; i++){ + if(!memcmp(pesbuf->buffer + i, packet_start_code_prefix, sizeof packet_start_code_prefix)){ + return i; + } + } +#endif + + return -1; +} + +/** + * TS¤Î²òÀϤÈDemux¤ò¹Ô¤¦ + */ +//static int ts2pes(int64_t *ppts, int64_t *pdts, const uint8_t *packet, splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) +static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access) +{ + /* + * PESÀèƬ¤Þ¤Ç¤ÎŤµ¤Ï + * 4byte : continity counter + * 27,28bit ¤¬ adaptation fileldÀ©¸æ + * (01:¥Ú¥¤¥í¡¼¥É¤Î¤ß, 10:adaptation fileld¤Î¤ß¡¢11:adaptation fileld+payload¡¢00:reserved) + * ¥Ú¥¤¥í¡¼¥ÉĹ = 188 - TS header(4byte) -adaptation fieldĹ -1 + */ + /* ¤¢¤ê¤¬¤È¤¦ */ + + int payload_offset; /* ¥Ú¥¤¥í¡¼¥É¥ª¥Õ¥»¥Ã¥È(=¥Ñ¥±¥Ã¥ÈÀèƬ¤«¤é¤Î¥Ð¥¤¥È¿ô) */ + int payload_length; /* ¥Ú¥¤¥í¡¼¥ÉĹ */ + int pes_started; + int adaptation_field_control; + int payload_unit_start_indicator; + int random_access_indicator = 0; + int sid = sp->pid_sid_table[pid]; + + payload_offset = LENGTH_TS_HEADER; + + if ( sp->pesbuf[pid] == NULL ) { + pes_started = 0; /* mallocÁö¤ëÁ°(¥»¥¯¥·¥ç¥ó²òÀϤÀ¤Ã¤¿¤é¸Æ¤ó¤ÇÎɤ¤) */ + } else { + pes_started = !pesbuf_empty(sp->pesbuf[pid]); /* PESÃßÀѳ«»ÏºÑ¤ß */ + } + + /* adaptation_field_control¤ª¤è¤Óadaptation_field¤ò½èÍý¤¹¤ë */ + adaptation_field_control = (packet[3] & 0x30) >> 4; + if ( adaptation_field_control == 0x02 || adaptation_field_control == 0x00) { + /* ¥Ú¥¤¥í¡¼¥É¤Ê¤·¤Î¾ì¹ç */ + return 0; /* Ê̤˥¨¥é¡¼¤Ç¤Ï¤Ê¤¤ */ + } else if ( adaptation_field_control == 0x03 ) { + /* ¥¢¥À¥×¥Æ¡¼¥·¥ç¥ó¥Õ¥£¡¼¥ë¥É¡Ü¥Ú¥¤¥í¡¼¥É¤Î¾ì¹ç */ + if ( packet[LENGTH_TS_HEADER] != 0 ) { + random_access_indicator = (packet[5] & 0x40) >> 6; + sp->pesbuf[pid]->random_access_indicator = 1; + sp->esbuf[pid]->random_access_indicator = 1; + } + /* ¥Ú¥¤¥í¡¼¥É³«»Ï°ÌÃÖ = TS¥Ø¥Ã¥ÀĹ + ¥¢¥À¥×¥Æ¡¼¥·¥ç¥ó¥Õ¥£¡¼¥ë¥ÉĹ + 1 */ + payload_offset += packet[LENGTH_TS_HEADER] + 1; + } else { + /* ¥Ú¥¤¥í¡¼¥É¤Î¤ß */ + ; /* Æä˽èÍý¤Ê¤· */ + } + + /* ¥Ú¥¤¥í¡¼¥ÉŤò½Ð¤¹ */ + payload_length = LENGTH_PACKET - payload_offset; + if( payload_length <= 0 ){ /* payloadŤ¬0°Ê²¼¤Î¾ì¹ç */ + return -1; /* ¥¨¥é¡¼¤Ë¤¹¤Ù¤¤«¤ÏÈù̯¤Ê¤È¤³¤í */ + } + + /* payload_unit_start_indicator¤ò½èÍý(1) */ + payload_unit_start_indicator = (packet[1] & 0x40) >> 6; + /* (section¤Î¾ì¹ç¤Ï¡¢¤³¤³¤Çpointer_field¤Î½èÍý¤Ê¤É¤ò¹Ô¤¤¡¢payload_offset¤ËÈ¿±Ç¤¹¤ë) */ +// if ( sp->pmt_pids[pid] == 2 ) { /* PID ¤¬Ï¿²èÂоݤΠPMT ¤Ç¤¢¤ë¤«¡© */ +// int sid = search_pmt_program(sp, pid); /* PID ¤¬Ï¿²èÂоݤΠPMT ¤Ç¤¢¤ë¤«¡© */ + if ( sp->pmt_pids[pid] == 2 ) { /* PID ¤¬Ï¿²èÂоݤΠPMT ¤Ç¤¢¤ë¤«¡© */ + if ( get_pmt_version(packet+payload_offset) != sp->program[sid].pmt_version ) { + /* pmt version¤Ëº¹Ê¬¤¢¤ê */ + fprintf(stderr, "pmt version diff found pmt_pid[%d]" + " old_version[0x%02x]" + " new_version[0x%02x].\n", + pid, + sp->program[sid].pmt_version, + get_pmt_version(packet+payload_offset)); + AnalyzePmt(sp, packet +payload_offset, sid, payload_length); + /* payload ²¿byte½èÍý¤·¤¿¤«Åù´ÉÍý¤¹¤ë¤Ù¤ */ + } + return 0; /* PMT ¤Î¾ì¹ç¤Ï½èÍý½ª¤ï¤ê */ + } + + /* payload_unit_start_indicator¤ò½èÍý(2) */ + /* ɬÍפ˱þ¤¸¡¢ÃßÀѺѤßPES¤Î½èÍý¤È¡¢PESÃßÀѳ«»Ï¤ò¹Ô¤¦ */ + if( payload_unit_start_indicator ){ + /* PES³«»Ï */ + if ( pes_started ) { + /* ¥Ð¥Ã¥Õ¥¡¤Ë¥Ç¡¼¥¿¤¬¤¢¤ì¤ÐPES½ªÃ¼¤Ê¤Î¤Ç½èÍý¤·¤Æ¥¯¥ê¥¢ */ + pes2es(sp->pesbuf[pid], sp->esbuf[pid], pid); + pesbuf_clear(sp->pesbuf[pid]); + } + else { + /* random_access_indicator ¤«¤éPES ¤ÎÃßÀѤò³«»Ï¤¹¤ë¤È + * CS¡§Æ°²è¤¬GOPÀèƬ¤«¤éÃßÀѤµ¤ì¤ë¤¬¡¢ + * ²»À¼¤Ë¤Ï random_access_indicator ¤¬É½¤ì¤Ê¤¤¤Î¤Ç¥À¥á + */ + pes_started = 1; + } + } + + /* PESÃßÀѽèÍý */ + if ( pes_started ){ + /* PESÃßÀѳ«»ÏºÑ¤ß(¤³¤ì¤«¤éPESÃßÀѳ«»Ï¤ò´Þ¤à)¤Ê¤é¡¢payload¤òPES¤È¤·¤ÆÄɲà */ + pesbuf_add(sp->pesbuf[pid], packet + payload_offset, payload_length); + } + /* ¤ª¤Ä¤«¤ì¤µ¤Þ¤Ç¤·¤¿ */ + return 0; +} + +/* PMT_PID ¤«¤é Program(Service ID)¤ò³ÎÄꤵ¤»¤ë */ +static int search_pmt_program(splitter *sp, int pid) +{ + int i; + for ( i = 0; i < MAX_SERVICE_ID; i++ ) { + if ( sp->program[i].pmt_packet_id == pid ) { + return i; + } + } + return -1; +} + +/* esbuf¤¬¶õ¤«È½Äê (ret. 0:not empty / 1: empty) */ +static int esbuf_empty(splitesbuf_t *esbuf){ + return esbuf->size == 0; +} + +/* esbuf¤ò¥¯¥ê¥¢ */ +void esbuf_clear(splitesbuf_t *esbuf){ + esbuf->random_access_indicator = 0; + esbuf->size = 0; +} + +/* esbuf¤Ë¥Ç¡¼¥¿¤òÄɲà (ret. 0:success / -1:error) */ +static int esbuf_add(splitesbuf_t *esbuf, const uint8_t *data, int len){ + if(esbuf->size + len > sizeof esbuf->buffer){ + return -1; + } + memcpy(esbuf->buffer +esbuf->size, data, len); + esbuf->size += len; + return 0; +} + +/* + * PES¤ò²òÀϤ·¤ÆES¤ò½ÐÎϤ¹¤ë + */ +static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) +{ + int len_pesh = 0; + int code = 0; + int flags = 0; + int len_pes = 0; + int len_pesh_supposed = 0; + int pes_extension_flags = 0; + int pes_extension_flags2 = 0; + int program_packet_sequence_counter_flag = 0; + int es_rate = 0; + const uint8_t *p = pesbuf->buffer; + const uint8_t *p_end = pesbuf->buffer +pesbuf->size; + int original_stuffing_length = 0; + int data_alignment_indicator = false; + int es_started; + int payload_offset = 0; + int payload_length = 0; + /* ¤¢¤ê¤¬¤È¤¦ */ + /* ¤¢¤ê¤¬¤È¤¦¤È¥³¥á¥ó¥È¤ò½ñ¤¯¤È¡¢ + * Æ°ºî¤¬¤è¤¯¤Ê¤ë + * ¥Ð¥°¤¬¸º¤ë + * ¥Ð¥¤¥Ê¥ê¥µ¥¤¥º¤¬¾®¤µ¤¯¤Ê¤ë + * ²è¼Á¤¬¤è¤¯¤Ê¤ë + * ²»¼Á¤¬¤è¤¯¤Ê¤ë + */ + if ( esbuf == NULL ) { + return -1; /* mallocÁö¤ëÁ°¤³¤Î´Ø¿ô¤Ï¸Æ¤ó¤¸¤ã¥À¥á¤Ç¤¹ */ + } else { + es_started = !esbuf_empty(esbuf); /* ESÃßÀѳ«»ÏºÑ¤ß */ + } + + payload_offset = pesbuf_packet_start_code_prefix(pesbuf); + if ( payload_offset == -1 ) { + return -1; + } + p += payload_offset; +#if 0 + while( p < p_end -LENGTH_PES_HEADER -2) { + /* PES PREFIX¤¬½Ð¸½¤¹¤ë¤Þ¤ÇÆɤ߼ΤƤë */ + if ( (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x01) ) { + break; + } else { + offset++; + p++; + } + } + if ( p >= p_end -LENGTH_PES_HEADER -2) { + return -1; + } +#endif + /* http://dvd.sourceforge.net/dvdinfo/pes-hdr.html + * + * Stream ID : type : extension present? + * (1011 1101) 0xBD : Private stream 1 (non MPEG audio, subpictures) : YES + * (1011 1110) 0xBE : Padding stream : NO + * (1011 1111) 0xBF : Private stream 2 (navigation data) : NO + * (110x xxxx) 0xC0 - 0xDF : MPEG-1 or MPEG-2 audio stream number x xxxx : YES + * (1110 xxxx) 0xE0 - 0xEF : MPEG-1 or MPEG-2 video stream number xxxx : YES + * note: DVD allows only 8 audio streams/DVD allows only 1 video stream + */ + /* http://www2.arib.or.jp/johomem/pdf/2009/2009_0088.pdf + * + * 0xBC : ¥×¥í¥°¥é¥à¥¹¥È¥ê¡¼¥à¥Þ¥Ã¥× + * 0xBD : ¥×¥é¥¤¥Ù¡¼¥È¥¹¥È¥ê¡¼¥à1 + * 0xBE : ¥Ñ¥Ç¥£¥ó¥°¥¹¥È¥ê¡¼¥à + * 0xBF : ¥×¥é¥¤¥Ù¡¼¥È¥¹¥È¥ê¡¼¥à2 + * 0xC0 - 0xDF : ISO/IEC 13318 3¡¢ISO/IEC 11172 3¡¢ISO/IEC 13318 7 or ISO/IEC 14496 3 audio xxxx + * 0xE0 - 0xEF : ITU-T H.262¡¢ISO/IEC 11172 2¡¢ISO/IEC 14496 2 or ITU-T H264±ÇÁü¥¹¥È¥ê¡¼¥à + * 0xF0 : ECM¥¹¥È¥ê¡¼¥à + * 0xF1 : EMM¥¹¥È¥ê¡¼¥à + * 0xF2 : ITU-T´«¹ðH.222.0 Annex A Ëô¤Ï ISO/IEC 13318 6 ¤ÎDSMCC¥¹¥È¥ê¡¼¥à + * 0xF3 : ISO/IEC 13522¥¹¥È¥ê¡¼¥à + * 0xF4 : ITU-T´«¹ð H.222.1 type A + * 0xF5 : ITU-T´«¹ð H.222.1 type B + * 0xF6 : ITU-T´«¹ð H.222.1 type C + * 0xF7 : ITU-T´«¹ð H.222.1 type D + * 0xF8 : ITU-T´«¹ð H.222.1 type E + * 0xF9 : Êä½õ¥¹¥È¥ê¡¼¥à + * 0xFA : ISO/IEC 14496 1SL¥Ñ¥±¥Ã¥È²½¥¹¥È¥ê¡¼¥à + * 0xFB : ISO/IEC 14496 1¥Õ¥ì¥Ã¥¯¥¹¥Þ¥Ã¥¯¥¹¥¹¥È¥ê¡¼¥à + * 0xFC : ¥á¥¿¥Ç¡¼¥¿¥¹¥È¥ê¡¼¥à + * 0xFD : ³ÈÄ¥¥¹¥È¥ê¡¼¥àID + * 0xFE : ̤ÄêµÁ + * 0xFF : ¥×¥í¥°¥é¥à¥¹¥È¥ê¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê + */ + /* ¾åµ¤è¤ê¡¢¤³¤³¤Ç¤Ï + * MPEG-1 or MPEG-2 audio stream ¤È + * MPEG-1 or MPEG-2 video stream ¤È + * Private stream 1 ¤È + * 0xFD(³ÈÄ¥¥¹¥È¥ê¡¼¥àID)¤òÃê½Ð¤¹¤ë + * ¡©0xBF Private stream 2 Íî¤È¤·¤Æ¤ë¤±¤É¤è¤¤¤Î¡© + * ¡ä¿ʬ¤è¤¯¤Ê¤¤¡£ffmpeg¤Ç¤Ï¤³¤³¤ËÆþ¤ëÁ°¤Ë PRIVATE_STREAM2 ¤Î¥³¡¼¥É¤¬Æþ¤Ã¤Æ¤¤¤ë + */ + code = (p[3] &0xff) | 0x100; + if ( !((code >= 0x1c0 && code <= 0x1df) || + (code >= 0x1e0 && code <= 0x1ef) || + (code == 0x1bd) || (code == 0x1fd))) { + return -1; + } + /* PES ¤Î¥Ç¡¼¥¿Ä¹ */ + /* Æ°²è¤Î¥¹¥È¥ê¡¼¥à¤Ç¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢ESŤÏÉÔÄê¤È¤Ê¤ë¤Î¤Ç0¤¬µöÍƤµ¤ì¤ë */ + len_pes = AV_RB16(p+4); + /* PES¥Ø¥Ã¥À³ÈÄ¥Éô(byte 6) */ + flags = p[6] & 0xff; + if ( flags & 0x04 ) { + data_alignment_indicator = true; + /* data alignment indicator */ + /* video start code or audio syncword. */ + /* ¤ª¤½¤é¤¯¤³¤³¤Ç¶èÀÚ¤ë¤È¥Ô¥¯¥Á¥ãñ°Ì */ + //printf("data alignment indicator found pid[%d].\n", pid); + } + flags = p[7] & 0xff; + /* PES¥Ø¥Ã¥À¥Ç¡¼¥¿Ä¹(byte 8) */ + /* + * PES¥Ø¥Ã¥À¥Ç¡¼¥¿Ä¹ = PES¥Ø¥Ã¥À³ÈÄ¥Éô¤ÎŤµ + stuffing byte¤ÎŤµ + */ + /* + *len_pesh = flags(byte 7)¤Î¥Ç¡¼¥¿¹ç·×(24) + * ¡ÜPES Extension flag¤Î¥Ç¡¼¥¿¹ç·×(23) + * ¡ÜPES Extension flag2¤Î¥Ç¡¼¥¿¹ç·×(127) + * ¡Üstuffing byte(32) <- ¤³¤ì¤âlen_pesh¤ÎŤµ¤Ëº®¤¼¤Æ¤¤¤¤¤Î¡© + * MAX=206(¡©) + */ + len_pesh = p[8] & 0xff; + p += LENGTH_PES_HEADER; + payload_offset += LENGTH_PES_HEADER +len_pesh; + if ( p +payload_offset >= p_end ) { + /* PES¥Ø¥Ã¥ÀŤ¹¤®¤Þ¤¹ */ + return -1; + } + + /* flags + * +---------------------------------------------------+ + * name |byte 7(flags) | + * +-----+-----+-----+------+----------+----+----------+ + * Bit |76 |5 |4 |3 |2 |1 |0 | + * +-----+-----+-----+------+----------+----+----------+ + * field|PTS |ESCR |ES |DSM |additional|PES |PES | + * name |DTS |FLAG |RATE |Trick |copy info |CRC |Extension | + * |flag | |flag |mode |flag |flag|flag | + * +-----+-----+-----+------+----------+----+----------+ + * Data |5,5 |6 |3 |1 |1 |2 |1 |(24) + * byte | | | | | | | | + * +-----+-----+-----+------+----------+----+----------+ + */ + if ( flags & PTS_FLAG ) { + if ( p +LENGTH_PTS >= p_end ) { + return -1; + } + esbuf->pts = get_pts(p); + p += LENGTH_PTS; + len_pesh_supposed += LENGTH_PTS; + } + if ( flags & DTS_FLAG ) { + if ( p +LENGTH_PTS >= p_end ) { + return -1; + } + esbuf->dts = get_pts(p); + p += LENGTH_PTS; + len_pesh_supposed += LENGTH_PTS; + } + if ( flags & ESCR_FLAG ) { + p += 6; + len_pesh_supposed += 6; + } + if ( flags & ES_RATE_FLAG ) { + es_rate = AV_RB24(p); + es_rate = (es_rate >>1) & 0x3fffff; + es_rate = es_rate * 50; + printf("pid[%d] es_rate[%d]Byte/Sec.\n", pid, es_rate); + p += 3; + len_pesh_supposed += 3; + } + if ( flags & DSM_TRICK_MODE_FLAG ) { + p += 1; + len_pesh_supposed += 1; + } + if ( flags & COPY_INFO_FLAG ) { + p += 1; + len_pesh_supposed += 1; + } + if ( flags & CRC_FLAG ) { + p += 2; + len_pesh_supposed += 2; + } + if ( flags & EXTENSION_FLAG ) { + /* PES Extension flag + * +------------------------------------------------------------------+ + * name |PES Extension flag | + * +-----------+-----------+----------------+------+---+--------------+ + * bit |7 |6 |5 |4 |321|0 | + * +-----------+-----------+----------------+------+---+--------------+ + * field|PES private|pack header|program |P-STD |111|PES extension | + * name |data flag |field flag |packet |buffer| |flag2 | + * | | |sequence counter|flag | | | + * +-----------+-----------+----------------+------+---+--------------+ + * Data |16 |1 |2 |2 | |1 |(23) + * byte | | | | | | | + * +-----------+-----------+----------------+------+---+--------------+ + */ + if ( p >= p_end ) { + return -1; + } + pes_extension_flags = *p & 0xff; + p += 1; + len_pesh_supposed += 1; + if ( pes_extension_flags & PES_PRIVATE_DATA_FLAG ) { + p += 16; + len_pesh_supposed += 16; + } + if ( pes_extension_flags & PACK_HEADER_FIELD_FLAG ) { + p += 1; + len_pesh_supposed += 1; + } + if ( pes_extension_flags & PROGRAM_PACKET_SEQUENCE_COUNTER ) { + if ( p >= p_end ) { + return -1; + } + program_packet_sequence_counter_flag = *p & 0xff; + original_stuffing_length = program_packet_sequence_counter_flag & 0x3f; + p += 2; + len_pesh_supposed += 2; + } + if ( pes_extension_flags & PSTD_BUFFER_FLAG ) { + p += 2; + len_pesh_supposed += 2; + } + if ( pes_extension_flags & PES_EXTENSION_FLAG2 ) { + /* PES Extension flag2 + * +------------------------------------------------------------------+ + * name |PES Extension flag2 | + * +------+-----------------------------------------------------------+ + * bit |7 |6543210 | + * +------+-----------------------------------------------------------+ + * field|marker|PES_extension_field_length | + * name |bit | | + * |'1' | | + * +------+-----------------------------------------------------------+ + * Data |- |0 <= N <= 127 |(127) + * byte | | | + * +------+-----------------------------------------------------------+ + */ + if ( p >= p_end ) { + return -1; + } + pes_extension_flags2 = *p & 0x7f; + p += 1; + len_pesh_supposed += 1; + + p += pes_extension_flags2; + len_pesh_supposed += pes_extension_flags2; + } + } +#if 0 + /* + * ²èÁü¤Ç¤¢¤ì¤Ð¡¢PTS/DTS¤¬Î©¤Ã¤Æ¤¤¤¿¾ì¹ç¤Ë½ÐÎϤ·¤Æ¡¢ + * ¤½¤ì°Ê³°¤Ç¤¢¤ì¤Ð¡¢PTS¤¬Î©¤Ã¤Æ¤¤¤¿¾ì¹ç¤Ë¤Î¤ß½ÐÎϤˤ¹¤ë¤È¡¢ + * GOPŪ¤Ê¤Þ¤È¤Þ¤ê¤Ç½ÐÎϤǤ¤ë¡© + */ + /* esbuf->size ¤¬ 0 ¤Ç¤¢¤ë¤Î¤Ï¤Ï½é´ü²½¸å¡¢½é¤á¤Æ¤³¤³¤ËÅþ㤷¤¿¾ì¹ç */ + if ((have_data_alignment_indicator) && (esbuf->size != 0)) { + /* ¤³¤³¤Î¥¿¥¤¥ß¥ó¥°¤Ç¥Ñ¥Ã¥¯¥Ø¥Ã¥À¤Ä¤±¤Æ¤¢¤²¤ì¤ÐPS¤Ë¤Ê¤ë¤Ï¤º */ + /* ¥Ô¥¯¥Á¥ãÀèƬ¥Ñ¥±¥Ã¥È */ + write_es(esbuf, pid); + memcpy(esbuf->buffer, + pesbuf->buffer +offset +LENGTH_PES_HEADER +len_pesh, + pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh); + esbuf->size = pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh; + } else if (have_data_alignment_indicator && (esbuf->size == 0)) { + /* ¥×¥í¥»¥¹µ¯Æ°¤·¤Æ¤«¤éºÇ½é¤Î¥Ô¥¯¥Á¥ãÀèƬ¥Ç¡¼¥¿ */ + memcpy(esbuf->buffer, + pesbuf->buffer +offset +LENGTH_PES_HEADER +len_pesh, + pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh); + esbuf->size = pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh; + } else if(esbuf->size != 0) { + /* ¤½¤ì°Ê³°¤ÎPES¥Ç¡¼¥¿ */ + memcpy(esbuf->buffer + esbuf->size, + pesbuf->buffer +offset +LENGTH_PES_HEADER +len_pesh, + pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh); + esbuf->size += pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh; + } else { + /* ÆÉ¤ß¼Î¤Æ */ + /* ¥×¥í¥»¥¹µ¯Æ°Ä¾¸å¤Î¥Ç¡¼¥¿¤Ï¼Î¤Æ¤ë(GOP¶³¦¤ò¤Þ¤¿¤¤¤À¥Ñ¥±¥Ã¥È¤«¤é½ñ¤»Ï¤á¤Ê¤¤°Ù) */ } + printf("len_pesh_supposed[%d], len_pesh[%d].\n", len_pesh_supposed, len_pesh); +#endif + if ( data_alignment_indicator ) { + if ( es_started ) { /* ES ¤Ë¥Ç¡¼¥¿¤¬ÃßÀѤµ¤ì¤Æ¤¤¤ë */ + if ( is_video_stream(pid, esbuf) ) { /* VIDEO ¤Ç¤¢¤ë¾ì¹ç */ + /* + * ES¤Ë¤Ï¥Ô¥¯¥Á¥ãñ°Ì¤Ç¥Ç¡¼¥¿¤¬ÃßÀѤµ¤ì¤Æ¤¤¤ë + * ES¤ËGOP¤Î³«»Ï¥³¡¼¥É¤¬´Þ¤Þ¤ì¤Æ¤¤¤ë¤«Ä´¤Ù¤Æ¡¢ + * ´Þ¤Þ¤ì¤Æ¤¤¤¿¤é¡¢ÃßÀѳ«»Ï¤Î¥Õ¥é¥°¤òΩ¤Æ¤ë¤Î¤¬¤¤¤¤¤«¤â¡Ä + */ + if ( esbuf->random_access_indicator ) { /* TS ¤Î random_access ¥Ó¥Ã¥È¤¬Î©¤Ã¤¿¤â¤Î¤¬¤¤Æ¤¤¤ë¤«¡© */ + /* ³ºÅö¥¹¥È¥ê¡¼¥à¤òÃßÀѤ¹¤ë */ + esbuf->started = 1; + esbuf->Program->video_start = 1; + esbuf->Program->video_pts = esbuf->pts; + } else { + /* TS ¤Î random_access ¥Ó¥Ã¥È¤¬Î©¤Ã¤¿¤â¤Î¤¬¤¤Æ¤¤¤Ê¤¤ */ + /* ÃßÀѤ·¤Ê¤¤ */ + esbuf_clear(esbuf); + } + } + /* AAC ¤Î¼Â¸³¥³¡¼¥É¤³¤³¤«¤é */ + /* + * ¥ª¡¼¥Ç¥£¥ª¤ò½ÐÎϤ·»Ï¤á¤ë¾ò·ï(1. 2. ¤òËþ¤¿¤¹¤³¤È) + * 1. Æ°²è¤ÎÃßÀѤϳ«»Ï¤µ¤ì¤Æ¤¤¤ë + * 2. Æ°²è¤ÎGOP¤Î1ÈÖÌܤÎI¥Ô¥¯¥Á¥ã¤ÎPTS¤È¥ª¡¼¥Ç¥£¥ª¤ÎPTS¤òÈæ³Ó¤·¤Æ°Ê²¼¤Î¤É¤Á¤é¤«¤òËþ¤¿¤¹¤³¤È + * 2.1. º¹Ê¬¤¬11msec°ÊÆâ + * 2.2. ²á¤®¤Æ¤¤¤ë(²á¤®¤Æ¤¤¤ë¾ì¹ç¤Ï¥ª¡¼¥Ç¥£¥ªES¤ÎÃßÀѤηѳ¤È¼¡¤ÎGOPÁÀ¤¤¤Ë¤¹¤ë¡©) + * ¡ôGOPÀèƬ¤Ë¤³¤À¤ï¤ê²á¤®¤ë¤ÈÏ¿²è¤òƨ¤¹¤È¤¤¤¦Àþ¤â¤¢¤ë¤Î¤Ç¡¢Å¬Åö¤Ë¼ê¤òÂǤĤΤâ¼ê + */ + else { + esbuf->started = 1; + } +#if 0 + if ( is_audio_stream(pid, esbuf) && esbuf->Program->video_start ) { + int audio_lipsync_offset = 0; + int i; + int64_t audio_pts = esbuf->pts; + int adts_freq = AnalyzeAdifHeader(esbuf); + int64_t adts_frame_time = ((1000/adts_freq) *27e6); /* PTS¤Ï27MHz */ + /* ¥ª¡¼¥Ç¥£¥ª³î¤Ä¡¢Program¤Î¥Ó¥Ç¥ªÃßÀѤ¬³«»Ï¤µ¤ì¤Æ¤¤¤ì¤Ð¥ª¡¼¥Ç¥£¥ª¤ÎÃßÀѤò¹Ô¤¦ */ + while ( (esbuf->Program->video_pts > audio_pts +adts_frame_time/2) ) { + /* ¥ª¡¼¥Ç¥£¥ª¥Ç¡¼¥¿¤ò¼Î¤Æ¤ë¤È audio_pts ¤Ï1¥Õ¥ì¡¼¥àʬÂ礤¯¤Ê¤ë */ + i = esbuf_adts_start_code_prefix(esbuf, audio_lipsync_offset); /* ¼¡¤ÎAAC¤Î¥Ç¡¼¥¿¤ò¼èÆÀ */ + if ( i != -1 ) { /* AAC¥Ç¡¼¥¿¤Î½ªÃ¼¤«¡© */ + audio_lipsync_offset += i; + } else { + break; + } + audio_pts += adts_frame_time; /* AAC¤Î1¥Õ¥ì¡¼¥àʬ¡¢»þ´Ö¤ò¿Ê¤á¤ë */ + } + if ( esbuf->size != audio_lipsync_offset ) { /* °ìÃפ·¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï¥³¥Ô¡¼ */ + memmove(esbuf->buffer +audio_lipsync_offset, + esbuf->buffer, + esbuf->size -audio_lipsync_offset); + esbuf->size -= audio_lipsync_offset; + esbuf->started = 1; + } + } +#endif + /* AAC ¤Î¼Â¸³¥³¡¼¥É¤³¤³¤Þ¤Ç */ + /* ¥Ð¥Ã¥Õ¥¡¤ò¥Õ¥¡¥¤¥ë¤Ë½ÐÎϤ·¤Æ¥¯¥ê¥¢ */ + if ( esbuf->started ) { + esbuf_write(esbuf, pid); + esbuf_clear(esbuf); + } + } else { + /* ESÃßÀѤò¿·¤¿¤Ë³«»Ï */ + es_started = 1; + } + } + + payload_length = pesbuf->size -payload_offset; + /* ESÃßÀѽèÍý */ + if ( es_started ) { + /* ESÃßÀѳ«»ÏºÑ¤ß(¤³¤ì¤«¤éESÃßÀѳ«»Ï¤ò´Þ¤à)¤Ê¤é¡¢payload¤òES¤È¤·¤ÆÄɲà */ + esbuf_add(esbuf, pesbuf->buffer +payload_offset, payload_length); + } + /* ¤ªÈè¤ì¤µ¤Þ¤Ç¤·¤¿ */ + return 0; +} + +/* PID¤Ïesbuf¤ÎAUDIO STREAM¤Î°ì¤Ä¤Ç¤¢¤ë¤«¡© */ +static int is_audio_stream(const int pid, splitesbuf_t *esbuf) +{ + int i = 0; + int found = 0; + program_t* program = esbuf->Program; + while (i < program->audio_nb) + { + if (program->audio[i] == pid) { + found = 1; + break; + } + i++; + } + return found; +} + +/* PID¤Ïesbuf¤ÎVIDEO STREAM¤Î°ì¤Ä¤Ç¤¢¤ë¤«¡© */ +static int is_video_stream(const int pid, splitesbuf_t *esbuf) +{ + int i = 0; + int found = 0; + program_t* program = esbuf->Program; + while (i < program->video_nb) + { + if (program->video[i] == pid) { + found = 1; + break; + } + i++; + } + return found; +} + +/* + * ES¤ò¥Õ¥¡¥¤¥ë½ÐÎϤ¹¤ë + */ +int esbuf_write(splitesbuf_t *esbuf, int pid) +{ + int fd; + int remain = esbuf->size; +#define ES_FILE "/tmp/es.%d" + char filename[1024]; + filename[0] = '\0'; + umask(0133); + snprintf(filename, sizeof(filename), ES_FILE, pid); + fd = open(filename, O_CREAT|O_APPEND|O_RDWR, 00644); + while(remain > 0) + { + remain -= write(fd, esbuf->buffer+(esbuf->size-remain), remain); + } + close(fd); + return 0; +} + + +/* + * packet dump + */ +void dump_packet( const uint8_t *packet ) +{ + int i = 0; + uint8_t *p = (uint8_t*)packet; + char tmp[17]; + + printf("HEADER 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <ASCII>\n"); + while(i < LENGTH_PACKET) { + if ( (i%16) == 0 ) { + printf("0x%04X ", i); + } + printf("%02x ", *(p+i)); + if ( isprint(*(p+i)) ){ + tmp[i%16] = *(p+i); + } + else { + tmp[i%16] = '.'; + } + if ((i%16) == 15) { + tmp[sizeof(tmp)-1] = '\0'; + printf(" %s\n", tmp); + } + i++; + } + putchar('\n'); +} + +/* + * TOT ¤Î JST_time ¤ò²òÀϤ¹¤ë + */ +static int parse_tot( const unsigned char* packet, time_t *t ) +{ + /* Ãí°Õ»ö¹à + * ËÜÅö¤Ï TOT ¤¬Í¸ú¤«¤É¤¦¤«¤ò¥Á¥§¥Ã¥¯¤¹¤ë¤Ù¤¤Ç¤¹¤¬¤·¤Æ¤¤¤Þ¤»¤ó + * ¥µ¥Þ¡¼¥¿¥¤¥à´Ø·¸¤Ï̵»ë¤·¤Æ¤¤¤Þ¤¹ + */ + struct tm tm; + time_t t2; + int k; + uint8_t *p = (uint8_t*)packet; + unsigned int MJD; + tm.tm_wday = 0; + tm.tm_yday = 0; + tm.tm_isdst = 0; + + p += 8; + MJD = (*(p) & 0xff) <<8; + p++; + MJD |= *(p) & 0xff; + printf("MJD[%x].\n", MJD); + + /* ARIB STD-B10 Âè2Éô ÉÕÏ¿C ¤Î¸ø¼°¤è¤ê MJD to YYYYMMDD */ + tm.tm_year = (int)floor((MJD - 15078.2)/365.25); + tm.tm_mon = (int)floor((MJD - 14956.1 - floor(tm.tm_year * 365.25))/30.6001); + tm.tm_mday = MJD - 14956 - floor(tm.tm_year * 365.25) - floor(tm.tm_mon * 30.6001); + if ( tm.tm_mon == 14 || tm.tm_mon == 15 ) + k = 1; + else + k = 0; + tm.tm_year += k; + tm.tm_mon = tm.tm_mon -1 - k * 12; + tm.tm_mon--; + + /* HHMISS¤Ï2¿Ê²½10¿Ê¿ô */ + p++; + tm.tm_hour = ((*p & 0xf0) >>4)*10 + (*p & 0x0f); + p++; + tm.tm_min = ((*p & 0xf0) >>4)*10 + (*p & 0x0f); + p++; + tm.tm_sec = ((*p & 0xf0) >>4)*10 + (*p & 0x0f); + + *t = mktime(&tm); + time(&t2); +// printf("time[%d] TOT[%d].\n", t2, *t); + + return TRUE; +} + +static int64_t get_pts(const uint8_t *p) +{ + int64_t pts = (int64_t)((p[0] >> 1) & 0x07) << 30; + pts |= (AV_RB16(p + 1) >> 1) << 15; + pts |= AV_RB16(p + 3) >> 1; + return pts; +} + +static int get_pmt_version(const uint8_t *p) +{ + return ((p[6] >> 1) & 0x1f); +} + + +#if 0 +void forward_stc(timespec *stc, timespec offset) +{ + struct timespec local_timespec; + + clock_gettime(CLOCK_REALTIME, &local_timespec); + + stc->tv_sec = local_timespec.tv_sec + offset.tv_sec; + stc->tv_nsec = local_timespec.tv_nsec + offset.tv_nsec; + if ( stc->tv_nsec >= 1 * 1000 * 1000 * 1000 ) { + stc->tv_nsec -= 1 * 1000 * 1000 * 1000; + stc->tv_sec += 1; + } else if ( stc->tv_nsec < 0 ) { + stc->tv_nsec = 1 * 1000 * 1000 * 1000 + stc->tv_nsec; + stc->tv_sec -= 1; + } +} +#endif +void search_mpeg_system_header(const uint8_t *packet) +{ + int i; + uint8_t *p = (uint8_t*)packet; + i = 0; + for( i=0; i < LENGTH_PACKET-4; i++) { + if( p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01 && p[i+3] == 0xb8 ){ + dump_packet(packet ); + } + } +} + +/* + * ¤³¤Î´Ø¿ô¤Ç¤Ï¡¢¸½ºß¤Î»ÅÍͤǤϡ¢ÀèƬ°ÌÃ֤Ρּ¡¤Î¡×ADTS start code¤Þ¤Ç¤ÎŤµ¤òÊֵѤ·¤Þ¤¹ + * ret == 0 : »ÅÍ;夢¤êÆÀ¤Ê¤¤ + * ret > 0 : ¸«¤Ä¤«¤Ã¤¿¾ì¹ç + * ret == -1 : ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç + */ +static int esbuf_adts_start_code_prefix(splitesbuf_t *esbuf, int offset) +{ + /* + * start code prefix ¤Î¤¦¤Á¡¢ÀèƬ12bit ¤Ï 1 ¸ÇÄê¤Ç¤¢¤ë¤¬¡¢13bit ÌÜ¤Ï id ¤Ë³ºÅö + * MPEG4¤Ê¥ª¡¼¥Ç¥£¥ª¤¬Í褿¾ì¹ç¤ËÂбþ½ÐÍè¤Ê¤¤¤Î¤Ç¡¢13bit Ìܤϸ«¤Ê¤¤¤è¤¦¤Ë²þ¤¤¹¤ë¤Ù¤ + */ + uint8_t adts_start_code_prefix[2] = {0xFF, 0xF8}; /* ¤È¤ê¤¢¤¨¤º·è¤áÂǤÁ */ + int i = offset +1; + + /* ¾®¤µ¤¹¤®¤ë */ + if(esbuf->size -offset < sizeof adts_start_code_prefix){ + return -1; + } + for(i = 1; i < esbuf->size -offset - sizeof adts_start_code_prefix; i++) { + if(!memcmp(esbuf->buffer +offset + i ,adts_start_code_prefix, sizeof adts_start_code_prefix)){ +#if 0 + printf("adts start code found.i[%d]. 0[%02x] 1[%02x] 2[%02x] 3[%02x] 4[%02x] 5[%02x] 6[%02x]\n", + 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) ); +#endif + return i; + } + } + return -1; +} + +/* ADIF HEADER²òÀÏ */ +static int AnalyzeAdifHeader(splitesbuf_t *esbuf) +{ + int id = 0; /* 0:MPEG-4 1:MPEG-2 */ + int layer = 0; /* ¾ï¤Ë 0x00 */ + int protection_absent = 0; /*Êݸî°À 0:Êݸî¤Ê¤· 1:Êݸ¤ê */ + int profile = 0; /* 00:MAIN 01:LC 10:SSR 11:(reserved) */ + int sampling_frequency_index = 0; /* ¥µ¥ó¥×¥ê¥ó¥°¼þÇÈ¿ô¥Æ¡¼¥Ö¥ëÃÍ */ + int private_bit = 0; /* private bit */ + int channel_configuration = 0; /* ¥Á¥ã¥ó¥Í¥ë¿ô */ + int original_copy = 0; + int home = 0; /* home¤Ã¤Æ¤Ê¤Ë¡© */ + int copyright_identification_bit = 0; /* Ãøºî¸¢¾ÚÌÀ¥Ó¥Ã¥È */ + int copyright_identification_start = 0; /* Ãøºî¸¢¾ÚÌÀ³«»Ï¥Ó¥Ã¥È */ + int aac_frame_length = 0; /* AAC¥Õ¥ì¡¼¥àĹ */ + int adts_buffer_fullness = 0; /* ADTS¥Ð¥Ã¥Õ¥¡»ÄÎÌ */ + int no_raw_data_blocks_in_frame = 0; /* ¥Ç¡¼¥¿¥Ö¥í¥Ã¥¯¤Þ¤Ç¤Î»ÄÎÌ */ + /* + * ¥µ¥ó¥×¥ê¥ó¥°¼þÇÈ¿ô¥Æ¡¼¥Ö¥ë(¥Ø¥Ã¥À¤ÎINDEX¤¬Åº»ú) + * ñ°Ì¡§Hz + */ + int sampling_frequency_table[16] = + { + 96000, + 88200, + 64000, + 48000, + 44100, + 32000, + 24000, + 22050, + 16000, + 12000, + 11025, + 8000, + -1, + -1, + -1, + -1 + }; + + uint8_t *p = esbuf->buffer; + if ( esbuf->size < 8 ) { + return -1; + } + + id = get_adif_id(p+1); + layer = get_adif_layer(p+1); + protection_absent = get_adif_protection_absent(p+1); + profile = get_adif_profile(p+2); + sampling_frequency_index = get_adif_sampling_frequency_index(p+2); + private_bit = get_adif_private_bit(p+2); + channel_configuration = get_adif_channel_configuration(p+3); + original_copy = get_adif_original_copy(p+3); + home = get_adif_home(p+3); + copyright_identification_bit = get_adif_copyright_idication_bit(p+3); + copyright_identification_start = get_adif_copyright_idication_start(p+3); + aac_frame_length = get_adif_aac_frame_length(p+3); + adts_buffer_fullness = get_adts_buffer_fullness(p+5); + no_raw_data_blocks_in_frame = get_adts_no_raw_data_blocks_in_frame(p+5); + + /* + * ¤È¤ê¤¢¤¨¤º return ¤Ï ¥µ¥ó¥×¥ê¥ó¥°¼þÇÈ¿ô¤È¤·¤Æ¤ª¤¯ + * ËÜÅö¤Ï¼èÆÀ¤·¤¿¾ðÊó¤ò¹½Â¤ÂΤˤ·¤ÆÊֵѤ¹¤ëÊý¤¬¤¤¤¤¤Î¤À¤í¤¦¤±¤É¡¢ + * ÍøÍѤ¹¤ëͽÄê¤â¤Ê¤¤¤Î¤Ç¼èÆÀ¤¹¤ë¤À¤±¤Ë¤·¤Æ¤ª¤¯ + */ + return sampling_frequency_table[sampling_frequency_index]; +} + +static int get_adif_id(uint8_t *p) +{ + return ((*p & 0x08) >>3); +} + +static int get_adif_layer(uint8_t *p) +{ + return ((*p & 0x06) >>1); +} + +static int get_adif_protection_absent(uint8_t *p) +{ + return (*p & 0x01); +} + +static int get_adif_profile(uint8_t *p) +{ + return ((*p & 0xc0) >>6); +} + +static int get_adif_sampling_frequency_index(uint8_t *p) +{ + return ((*p & 0x3c) >>2); +} + +static int get_adif_private_bit(uint8_t *p) +{ + return ((*p & 0x02) >>1); +} + +static int get_adif_channel_configuration(uint8_t *p) +{ + return ((*p & 0x01) <<2 | (*(p+1) & 0xc0 >>6) ); +} + +static int get_adif_original_copy(uint8_t *p) +{ + return (*p & 0x20 >>5 ); +} + +static int get_adif_home(uint8_t *p) +{ + return (*p & 0x10 >>4 ); +} + +static int get_adif_copyright_idication_bit(uint8_t *p) +{ + return (*p & 0x08 >>3 ); +} + +static int get_adif_copyright_idication_start(uint8_t *p) +{ + return (*p & 0x04 >>2 ); +} + +static int get_adif_aac_frame_length(uint8_t *p) +{ + return ( ((*p & 0x02) <<11) || ((*(p+1) & 0xff) <<3) || ((*(p+2) & 0xe0) >>5) ); +} + +static int get_adts_buffer_fullness(uint8_t *p) +{ + return ( ((*p & 0x1f) <<6) || ((*(p+1) &0xfc) >>2)); +} + +static int get_adts_no_raw_data_blocks_in_frame(uint8_t *p) +{ + return (*p & 0x03); +} + +/* GOP START CODE ¤ò¸¡º÷¤¹¤ë */ +static int search_gop_start_code(splitesbuf_t *esbuf) +{ + uint8_t gop_start_code[4] = {0x00, 0x00, 0x01, 0xb8}; + int i; + + /* ¾®¤µ¤¹¤®¤ë */ + if ( esbuf->size < sizeof gop_start_code ){ + return -1; + } + for(i = 0; i < esbuf->size - sizeof gop_start_code; i++) { + if(!memcmp(esbuf->buffer +i ,gop_start_code, sizeof gop_start_code)){ + return i; + } + } + return -1; +}
--- a/recpt1/tssplitter_lite.h Mon Apr 19 00:17:57 2010 +0900 +++ b/recpt1/tssplitter_lite.h Mon Apr 19 00:30:09 2010 +0900 @@ -36,6 +36,129 @@ #define TSS_NULL (-2) #define LENGTH_PAT_HEADER (12) #define C_CHAR_COMMA ',' +#define LENGTH_TS_HEADER (4) +#define LENGTH_PES_HEADER (9) +#define LENGTH_PTS (5) + +/* ²þÄûÈǥǥ¸¥¿¥ëÊüÁ÷¶µ²Ê½ñ(¾å) P101 ɽ1 ARIB¤Ç¤ÎPSI/SI¤Î¼ïÎà¤è¤ê»²¾È */ +#define PAT (0x0000) +//#define PMT /* PAT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +#define CAT (0x0001) +#define NIT (0x0010) +#define SDT (0x0011) +#define BAT (0x0011) +#define EIT (0x0012) /* 0x0026, 0x0027 */ +#define RST (0x0013) +#define TDT (0x0014) /* Ãϥǥ¸¤Ç¤Ï»ÈÍѤµ¤ì¤Ê¤¤ */ +#define TOT (0x0014) +#define LIT (0x0020) /* ¤Þ¤¿¤ÏPMT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +#define ERT (0x0021) /* ¤Þ¤¿¤ÏPMT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +//#define ITT /* PMT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +#define PCAT (0x0022) +#define BIT (0x0024) +#define NBIT (0x0025) +//#define ECM /* PMT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +//#define EMM /* CAT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +#define LDT (0x0025) +#define DCT (0x0017) +//#define DTL /* DCT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ +#define DIT (0x001e) +#define SIT (0x001f) +#define SDTT (0x0023) +#define CDT (0x0029) +//#define DSM-CC_Section /* PMT¤Ë¤è¤ë´ÖÀÜ»ØÄê */ + +/* ¥»¥¯¥·¥ç¥ó¥Ø¥Ã¥ÀĹ */ +/* TS ¥Ñ¥±¥Ã¥È¤Ë³Æ¥»¥¯¥·¥ç¥ó¤òÀßÃÖ¤¹¤ëºÝ¡¢³ºÅöTS¥Ñ¥±¥Ã¥È¤Î»Ä¥µ¥¤¥º¤¬ + * ¤¤¤¯¤Ä°Ê¾å¤¢¤ì¤Ð½ñ¤¹þ¤á¤ë¤«¤ÎȽÄê¤Ë»ÈÍѤ¹¤ë¡£ + * ¥Ç¥³¡¼¥É¤Ë¤Ï¤¢¤Þ¤ê½ÅÍפǤÏ̵¤¤¤«¤â + */ +#define SECTION_LENGTH_PAT (8) +#define SECTION_LENGTH_PMT (8) +#define SECTION_LENGTH_CAT (8) +#define SECTION_LENGTH_NIT (8) +#define SECTION_LENGTH_BIT (8) +#define SECTION_LENGTH_SDT (11) +#define SECTION_LENGTH_EIT (14) /* H-EIT, M-EIT, L-EIT ¤ò¼¨¤¹ */ +#define SECTION_LENGTH_SDTT (15) +#define SECTION_LENGTH_CDT (13) +#define SECTION_LENGTH_TOT (10) + +enum { + PTS_FLAG = 0x80, + DTS_FLAG = 0x40, + ESCR_FLAG = 0x20, + ES_RATE_FLAG = 0x10, + DSM_TRICK_MODE_FLAG = 0x08, + COPY_INFO_FLAG = 0x04, + CRC_FLAG = 0x02, + EXTENSION_FLAG = 0x01 +}; + +enum { + PES_PRIVATE_DATA_FLAG = 0x80, + PACK_HEADER_FIELD_FLAG = 0x40, + PROGRAM_PACKET_SEQUENCE_COUNTER = 0x20, + PSTD_BUFFER_FLAG = 0x10, + PES_EXTENSION_FLAG2 = 0x01 +}; + +/* + * PCR¤«¤éSTC¤òÀ¸À®¤¹¤ë½èÍýÊý¼°(°Æ) + * 1. PCR¤òÆó¤Ä¼èÆÀ¤¹¤ë¤Þ¤Ç¥ë¡¼¥×(1.¢²4.¤Þ¤Ç¤Ï½é´ü½èÍý¤Ç¼Â»Ü¤¹¤ë¤³¤È) + * 2. ¥ë¡¼¥×³«»Ï»þ¹ï(PCR)¤È¡¢¥ë¡¼¥×È´¤±¤¿»þ¹ï(PCR)¤Îº¹Ê¬¤ò¼è¤ë + * 3. ¥ë¡¼¥×³«»Ï¡Á½ªÎ»¤Î´Ö¤Ë½èÍý¤·¤¿¥Ñ¥±¥Ã¥È¿ô¤ò¿ô¤¨¤ë + * 4. (2.¤ÎPCR¤Î¿Ê¤ó¤À»þ´Ö/3.¤Î¥Ñ¥±¥Ã¥È¿ô)¡¡¤Î·×»»¤Ë¤è¤Ã¤Æ¡¢1¥Ñ¥±¥Ã¥È¤Ë¤è¤Ã¤Æ¿Ê¤àPCR¤òÁÛÄꤹ¤ë + * 5. TS¼õ¿®»þ¤Ë¡¢1¤Ä¤Î¥Ñ¥±¥Ã¥È¤ò½èÍý¤¹¤ëÅÙ¤Ë4.¤ÎÁÛÄꤹ¤ë·Ð²á»þ¹ï¤òPCR¤Ë¤·¹þ¤ó¤ÇSTC¤È¤¹¤ë + * 6. PCR¤ò¿·µ¬¤Ë¼èÆÀ¤·¤¿¤é¡¢STC¤òÊäÀµ(¤½¤Î¤Þ¤ÞÂåÆþ)¤¹¤ë + */ +#define MAX_VIDEO (16) +#define MAX_AUDIO (32) +typedef struct _program_t +{ + int64_t stc; + int64_t cue_time; /* Ï¿²è³«»Ï»þ¹ï */ + int pmt_packet_id; /* ³ºÅöProgram(Service ID)¤ËÂбþ¤¹¤ëPMT */ + int pmt_version; /* ³ºÅöProgram(Service ID)¤ËÂбþ¤¹¤ëPMT¤ÎVersion */ + int pcr_packet_id; /* ³ºÅöProgram(Service ID)¤ÎPCR¤òÊÝ»ý¤¹¤ëPID */ + int64_t pcr1; /* PCR1 */ + int64_t pcr2; /* PCR2 */ + int packet_nb; /* PCR·×»»ÍÑ¥«¥¦¥ó¥¿ */ + int64_t pcr_incr; /* ³ºÅöProgram(Service ID)¤Ë±÷¤¤¤Æ¡¢1¤Ä¤ÎTS¥Ñ¥±¥Ã¥È¤ò½èÍý¤·¤¿»þ¤Ë·Ð²á¤¹¤ë(¤ÈÁÛÄꤹ¤ë»þ´Ö) */ + int video_start; /* VODEO0¤òÃßÀѳ«»Ï¤·¤Æ¤¤¤ë¡© */ + int video_pts; /* ºÇ¸å¤Ë½èÍý¤·¤¿VODEO0¤ÎES¤ÎPTS */ + int video_nb; /* PMT ¤Ë¸ºß¤¹¤ë¥Ó¥Ç¥ª¥¹¥È¥ê¡¼¥à¤Î¿ô */ + int audio_nb; /* PMT ¤Ë¸ºß¤¹¤ë²»À¼¥¹¥È¥ê¡¼¥à¤Î¿ô */ + int video[MAX_VIDEO]; /* PS½ÐÎϤ¹¤ë¾ì¹ç¤Ë»È¤¦¤«¤â */ + int audio[MAX_AUDIO]; /* PS½ÐÎϤ¹¤ë¾ì¹ç¤Ë»È¤¦¤«¤â */ + //splitpesbuf_t *pesbuf; + //splitesbuf_t *esbuf; +} program_t; +/* + * program_t ¤ò¥µ¡¼¥Ó¥¹IDʬ½àÈ÷¤·¤Æ¡¢»ÈÍѤ¹¤ë¥¤¥á¡¼¥¸¤Ç¤¤¤¿¤±¤É¡¢ + * ¥µ¡¼¥Ó¥¹ID¤ÎºÇÂçÃͤÏ0xFFFF¤Ç¤¢¤ë¤Î¤Ç¡¢ÀÅŪ¤Ë³ÎÊݤ¹¤ë¤È stack ¤¬´Êñ¤Ë°î¤ë¤Î¤Ç¡¢ + * ¼Â¹Ô»þ¤Ë malloc ¤È¤¹¤ë¤«¤Ê¤¡ + * ËÜÅö¤ÏɬÍפʤÀ¤±alloc¤¹¤ë¤Î¤¬¹¥¤Þ¤·¤¤¤Î¤À¤±¤É¡Ä + */ + +typedef struct _splitpesbuf_t +{ + program_t *Program; + int random_access_indicator; /* TS ¤Î random_access_indicator */ + int size; + u_char buffer[3*1024*1024]; +} splitpesbuf_t; + +typedef struct _splitesbuf_t +{ + program_t *Program; + int64_t pts; + int64_t dts; + int started; /* ³ºÅöES¤¬ÃßÀѳ«»Ï¤·¤Æ¤¤¤ë¤« */ + int random_access_indicator; /* TS ¤Î random_access_indicator */ + int size; + u_char buffer[3*1024*1024]; +} splitesbuf_t; /** * splitter¹½Â¤ÂÎ @@ -50,6 +173,15 @@ int pmt_counter; int avail_pmts[MAX_SERVICES]; int num_pmts; +// struct timespec tot_offset; +// struct timespec STC_timespec; + int64_t stc; + int64_t cue_time; + int status; + splitpesbuf_t *pesbuf[MAX_PID]; + splitesbuf_t *esbuf[MAX_PID]; + program_t *program; + int pid_sid_table[MAX_PID]; /* pid to sid ¤ÎÊÑ´¹¤ò¹Ô¤¦¤¿¤á¤Î¥Æ¡¼¥Ö¥ë */ } splitter; /* b25 decoder would hoard up large chank */