📄 mpegts.c
字号:
}static void gf_m2ts_process_pat(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ses, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){ GF_M2TS_Program *prog; GF_M2TS_SECTION_ES *pmt; u32 i, nb_progs, evt_type; /*skip if already received*/ if (status==GF_M2TS_TABLE_REPEAT) { if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_PAT_REPEAT, NULL); return; } nb_progs = data_size / 4; for (i=0; i<nb_progs; i++) { u16 number, pid; number = (data[0]<<8) | data[1]; pid = (data[2]&0x1f)<<8 | data[3]; data += 4; if (number==0) { if (!ts->nit) { ts->nit = gf_m2ts_section_filter_new(gf_m2ts_process_nit); } } else { GF_SAFEALLOC(prog, GF_M2TS_Program); prog->streams = gf_list_new(); prog->pmt_pid = pid; prog->number = number; gf_list_add(ts->programs, prog); GF_SAFEALLOC(pmt, GF_M2TS_SECTION_ES); pmt->flags = GF_M2TS_ES_IS_SECTION; gf_list_add(prog->streams, pmt); pmt->pid = prog->pmt_pid; pmt->program = prog; ts->ess[pmt->pid] = (GF_M2TS_ES *)pmt; pmt->sec = gf_m2ts_section_filter_new(gf_m2ts_process_pmt); } } evt_type = (status==GF_M2TS_TABLE_UPDATE) ? GF_M2TS_EVT_PAT_UPDATE : GF_M2TS_EVT_PAT_FOUND; if (ts->on_event) ts->on_event(ts, evt_type, NULL);}static GFINLINE u64 gf_m2ts_get_pts(unsigned char *data){ u64 pts; u32 val; pts = (u64)((data[0] >> 1) & 0x07) << 30; val = (data[1] << 8) | data[2]; pts |= (u64)(val >> 1) << 15; val = (data[3] << 8) | data[4]; pts |= (u64)(val >> 1); return pts;}static void gf_m2ts_pes_header(unsigned char *data, u32 data_size, GF_M2TS_PESHeader *pesh){ Bool has_pts, has_dts; memset(pesh, 0, sizeof(GF_M2TS_PESHeader)); pesh->id = data[0]; pesh->pck_len = (data[1]<<8) | data[2];/* 2bits scrambling_control = gf_bs_read_int(bs,2); priority = gf_bs_read_int(bs,1);*/ pesh->data_alignment = (data[3] & 0x4) ? 1 : 0;/* copyright = gf_bs_read_int(bs,1); original = gf_bs_read_int(bs,1);*/ has_pts = (data[4]&0x80); has_dts = (data[4]&0x40);/* ESCR_flag = gf_bs_read_int(bs,1); ES_rate_flag = gf_bs_read_int(bs,1); DSM_flag = gf_bs_read_int(bs,1); additional_copy_flag = gf_bs_read_int(bs,1); prev_crc_flag = gf_bs_read_int(bs,1); extension_flag = gf_bs_read_int(bs,1);*/ pesh->hdr_data_len = data[5]; data += 6; if (has_pts) { pesh->PTS = gf_m2ts_get_pts(data); data+=5; } if (has_dts) { pesh->DTS = gf_m2ts_get_pts(data); data+=5; }}static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Header *hdr, unsigned char *data, u32 data_size, GF_M2TS_AdaptationField *paf){ Bool flush_pes = 0; if (!pes->reframe) return; if (hdr->payload_start) { flush_pes = 1; } else if (pes->pes_len && (pes->data_len + data_size == pes->pes_len + 6)) { /* 6 = startcode+stream_id+length*/ /*reassemble pes*/ if (pes->data) pes->data = (char*)realloc(pes->data, pes->data_len+data_size); else pes->data = (char*)malloc(data_size); memcpy(pes->data+pes->data_len, data, data_size); pes->data_len += data_size; /*force discard*/ data_size = 0; } /*PES first fragment: flush previous packet*/ if (flush_pes && pes->data) { GF_M2TS_PESHeader pesh; /*we need at least a full, valid start code !!*/ if ((pes->data_len >= 4) && !pes->data[0] && !pes->data[1] && (pes->data[2]==0x1)) { u32 len; u32 stream_id = pes->data[3] | 0x100; if ((stream_id >= 0x1c0 && stream_id <= 0x1df) || (stream_id >= 0x1e0 && stream_id <= 0x1ef) || (stream_id == 0x1bd)) { /*OK read header*/ gf_m2ts_pes_header(pes->data+3, pes->data_len-3, &pesh); /*3-byte start-code + 6 bytes header + hdr extensions*/ len = 9 + pesh.hdr_data_len; pes->reframe(ts, pes, pesh.DTS, pesh.PTS, pes->data+len, pes->data_len-len); } /*SL-packetized stream*/ else if ((u8) pes->data[3]==0xfa) { GF_M2TS_SL_PCK sl_pck; /*read header*/ gf_m2ts_pes_header(pes->data+3, pes->data_len-3, &pesh); /*3-byte start-code + 6 bytes header + hdr extensions*/ len = 9 + pesh.hdr_data_len; GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] SL Packet in PES for %d\n", pes->pid)); sl_pck.data = pes->data + len; sl_pck.data_len = pes->data_len - len; sl_pck.stream = (GF_M2TS_ES *)pes; if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_SL_PCK, &sl_pck); } } if (pes->data) { free(pes->data); pes->data = NULL; pes->data_len = 0; pes->pes_len = 0; } pes->rap = 0; if (!data_size) return; } /*reassemble*/ if (pes->data) pes->data = (char*)realloc(pes->data, pes->data_len+data_size); else pes->data = (char*)malloc(data_size); memcpy(pes->data+pes->data_len, data, data_size); pes->data_len += data_size; if (paf && paf->random_access_indicator) pes->rap = 1; if (!pes->pes_len && (pes->data_len>=6)) pes->pes_len = (pes->data[4]<<8) | pes->data[5];}static void gf_m2ts_get_adaptation_field(GF_M2TS_Demuxer *ts, GF_M2TS_AdaptationField *paf, unsigned char *data, u32 size){ paf->discontinuity_indicator = (data[0] & 0x80) ? 1 : 0; paf->random_access_indicator = (data[0] & 0x40) ? 1 : 0; paf->priority_indicator = (data[0] & 0x20) ? 1 : 0; paf->PCR_flag = (data[0] & 0x10) ? 1 : 0; paf->OPCR_flag = (data[0] & 0x8) ? 1 : 0; paf->splicing_point_flag = (data[0] & 0x4) ? 1 : 0; paf->transport_private_data_flag = (data[0] & 0x2) ? 1 : 0; paf->adaptation_field_extension_flag = (data[0] & 0x1) ? 1 : 0; if (paf->PCR_flag == 1){ u64 PCR = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4]; paf->PCR_base = (PCR << 1) | (data[5] >> 7); paf->PCR_ext = ((data[5] & 1) << 8) | data[6]; }#if 0 if (paf->OPCR_flag == 1){ u64 PCR = (data[7] << 24) | (data[8] << 16) | (data[9] << 8) | data[10]; paf->PCR_base = (PCR << 1) | (data[11] >> 7); paf->PCR_ext = ((data[11] & 1) << 8) | data[12]; }#endif }static void gf_m2ts_process_packet(GF_M2TS_Demuxer *ts, unsigned char *data){ GF_M2TS_ES *es; GF_M2TS_Header hdr; GF_M2TS_AdaptationField af, *paf; u32 payload_size, af_size; u32 pos = 0; /* read TS packet header*/ hdr.sync = data[0]; hdr.error = (data[1] & 0x80) ? 1 : 0; hdr.payload_start = (data[1] & 0x40) ? 1 : 0; hdr.priority = (data[1] & 0x20) ? 1 : 0; hdr.pid = ( (data[1]&0x1f) << 8) | data[2]; hdr.scrambling_ctrl = (data[3] >> 6) & 0x3; hdr.adaptation_field = (data[3] >> 4) & 0x3; hdr.continuity_counter = data[3] & 0xf;#if DEBUG_TS_PACKET GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] Packet PID %d\n", hdr.pid));#endif paf = NULL; payload_size = 184; pos = 4; switch (hdr.adaptation_field) { /*adaptation+data*/ case 3: af_size = data[4]; if (af_size>183) { //error return; } paf = ⁡ memset(paf, 0, sizeof(GF_M2TS_AdaptationField)); gf_m2ts_get_adaptation_field(ts, paf, data+5, af_size); pos += 1+af_size; payload_size = 183 - af_size; break; /*adaptation only - still process in cas of PCR*/ case 2: af_size = data[4]; if (af_size>183) { //error return; } paf = ⁡ memset(paf, 0, sizeof(GF_M2TS_AdaptationField)); gf_m2ts_get_adaptation_field(ts, paf, data+5, af_size); payload_size = 0; break; /*reserved*/ case 0: return; default: break; } data += pos; /*PAT*/ if (hdr.pid == 0) { gf_m2ts_gather_section(ts, ts->pat, NULL, &hdr, data, payload_size); return; } else { es = ts->ess[hdr.pid]; /*check for DVB reserved PIDs*/ if (!es) { /*SDT*/ if (hdr.pid == 0x0011) { gf_m2ts_gather_section(ts, ts->sdt, NULL, &hdr, data, payload_size); return; } /*NIT for DVB*/ else if (hdr.pid == 0x0010) { /*ignore them, unused at application level*/ //if (!hdr.error) gf_m2ts_gather_section(ts, ts->nit, NULL, &hdr, data, payload_size); return; } return; } if (es->flags & GF_M2TS_ES_IS_SECTION) { /* The stream uses sections to carry its payload */ GF_M2TS_SECTION_ES *ses = (GF_M2TS_SECTION_ES *)es; if (ses->sec) gf_m2ts_gather_section(ts, ses->sec, ses, &hdr, data, payload_size); } else { /* regular stream using PES packets */ /* let the pes reassembler decide if packets with error shall be discarded*/ gf_m2ts_process_pes(ts, (GF_M2TS_PES *)es, &hdr, data, payload_size, paf); if (paf && paf->PCR_flag) { GF_M2TS_PES_PCK pck; memset(&pck, 0, sizeof(GF_M2TS_PES_PCK)); pck.PTS = paf->PCR_base * 300 + paf->PCR_ext; // ??? pck.stream = (GF_M2TS_PES *)es; if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_PES_PCR, &pck); } } } return;}GF_Err gf_m2ts_process_data(GF_M2TS_Demuxer *ts, char *data, u32 data_size){ u32 pos; Bool is_align = 1; if (ts->buffer) { if (ts->alloc_size < ts->buffer_size+data_size) { ts->alloc_size = ts->buffer_size+data_size; ts->buffer = (char*)realloc(ts->buffer, sizeof(char)*ts->alloc_size); } memcpy(ts->buffer + ts->buffer_size, data, sizeof(char)*data_size); ts->buffer_size += data_size; is_align = 0; } else { ts->buffer = data; ts->buffer_size = data_size; } /*sync input data*/ pos = gf_m2ts_sync(ts, is_align); if (pos==ts->buffer_size) { if (is_align) { ts->buffer = (char*)malloc(sizeof(char)*data_size); memcpy(ts->buffer, data, sizeof(char)*data_size); ts->alloc_size = ts->buffer_size = data_size; } return GF_OK; } for (;;) { /*wait for a complete packet*/ if (ts->buffer_size - pos < 188) { ts->buffer_size -= pos; if (!ts->buffer_size) { if (!is_align) free(ts->buffer); ts->buffer = NULL; return GF_OK; } if (is_align) { data = ts->buffer+pos; ts->buffer = (char*)malloc(sizeof(char)*ts->buffer_size); memcpy(ts->buffer, data, sizeof(char)*ts->buffer_size); ts->alloc_size = ts->buffer_size; } else { memmove(ts->buffer, ts->buffer + pos, sizeof(char)*ts->buffer_size); } return GF_OK; } /*process*/ gf_m2ts_process_packet(ts, ts->buffer+pos); pos += 188; } return GF_OK;}void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *ts){ u32 i; for (i=0; i<GF_M2TS_MAX_STREAMS; i++) { GF_M2TS_PES *pes = (GF_M2TS_PES *) ts->ess[i]; if (!pes || (pes->pid==pes->program->pmt_pid)) continue; pes->frame_state = 0; if (pes->data) free(pes->data); pes->data = NULL; pes->data_len = 0; pes->PTS = pes->DTS = 0; }}GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode){ if (pes->pid==pes->program->pmt_pid) return GF_BAD_PARAM; if (mode==GF_M2TS_PES_FRAMING_RAW) { pes->reframe = gf_m2ts_reframe_default; return GF_OK; } else if (mode==GF_M2TS_PES_FRAMING_SKIP) { pes->reframe = NULL; return GF_OK; } else { // mode==GF_M2TS_PES_FRAMING_DEFAULT switch (pes->stream_type) { case GF_M2TS_VIDEO_MPEG1: case GF_M2TS_VIDEO_MPEG2: pes->reframe = gf_m2ts_reframe_mpeg_video; break; case GF_M2TS_AUDIO_MPEG1: case GF_M2TS_AUDIO_MPEG2: pes->reframe = gf_m2ts_reframe_mpeg_audio; break; case GF_M2TS_VIDEO_H264: pes->reframe = gf_m2ts_reframe_avc_h264; break; default: pes->reframe = gf_m2ts_reframe_default; break; } return GF_OK; }}GF_M2TS_Demuxer *gf_m2ts_demux_new(){ GF_M2TS_Demuxer *ts; GF_SAFEALLOC(ts, GF_M2TS_Demuxer); ts->programs = gf_list_new(); ts->SDTs = gf_list_new(); ts->pat = gf_m2ts_section_filter_new(gf_m2ts_process_pat); ts->sdt = gf_m2ts_section_filter_new(gf_m2ts_process_sdt); return ts;}void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts){ u32 i; if (ts->pat) gf_m2ts_section_filter_del(ts->pat); if (ts->sdt) gf_m2ts_section_filter_del(ts->sdt); if (ts->nit) gf_m2ts_section_filter_del(ts->nit); for (i=0; i<8192; i++) { if (ts->ess[i]) gf_m2ts_es_del(ts->ess[i]); } if (ts->buffer) free(ts->buffer); while (gf_list_count(ts->programs)) { GF_M2TS_Program *p = (GF_M2TS_Program *)gf_list_last(ts->programs); gf_list_rem_last(ts->programs); gf_list_del(p->streams); if (p->pmt_iod) gf_odf_desc_del((GF_Descriptor *)p->pmt_iod); free(p); } gf_list_del(ts->programs); gf_m2ts_reset_sdt(ts); gf_list_del(ts->SDTs); free(ts);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -