📄 demux_ts.c
字号:
es->lang[3] = 0; mp_msg(MSGT_DEMUX, MSGL_V, "Language Descriptor: %s\n", es->lang); } else if(ptr[j] == 0x5) //Registration Descriptor (looks like e fourCC :) ) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor\n"); if(descr_len < 4) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor length too short: %d, SKIPPING\n", descr_len); } else { char *d; memcpy(es->format_descriptor, &ptr[j+2], 4); es->format_descriptor[4] = 0; d = &ptr[j+2]; if(d[0] == 'A' && d[1] == 'C' && d[2] == '-' && d[3] == '3') { es->type = AUDIO_A52; } else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '1') { es->type = AUDIO_DTS; } else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '2') { es->type = AUDIO_DTS; } else if(d[0] == 'V' && d[1] == 'C' && d[2] == '-' && d[3] == '1') { es->type = VIDEO_VC1; } else es->type = UNKNOWN; mp_msg(MSGT_DEMUX, MSGL_DBG2, "FORMAT %s\n", es->format_descriptor); } } else if(ptr[j] == 0x1e) { es->mp4_es_id = (ptr[j+2] << 8) | ptr[j+3]; mp_msg(MSGT_DEMUX, MSGL_V, "SL Descriptor: ES_ID: %d(%x), pid: %d\n", es->mp4_es_id, es->mp4_es_id, es->pid); } else mp_msg(MSGT_DEMUX, MSGL_DBG2, "Unknown descriptor 0x%x, SKIPPING\n", ptr[j]); len -= 2 + descr_len; j += 2 + descr_len; } return 1;}static int parse_sl_section(pmt_t *pmt, ts_section_t *section, int is_start, unsigned char *buff, int size){ int tid, len, skip; uint8_t *ptr; skip = collect_section(section, is_start, buff, size); if(! skip) return 0; ptr = &(section->buffer[skip]); tid = ptr[0]; len = ((ptr[1] & 0x0f) << 8) | ptr[2]; mp_msg(MSGT_DEMUX, MSGL_V, "TABLEID: %d (av. %d), skip=%d, LEN: %d\n", tid, section->buffer_len, skip, len); if(len > 4093 || section->buffer_len < len || tid != 5) { mp_msg(MSGT_DEMUX, MSGL_V, "SECTION TOO LARGE or wrong section type, EXIT\n"); return 0; } if(! (ptr[5] & 1)) return 0; //8 is the current position, len - 9 is the amount of data available parse_mp4_descriptors(pmt, &ptr[8], len - 9, NULL); return 1;}static int parse_pmt(ts_priv_t * priv, uint16_t progid, uint16_t pid, int is_start, unsigned char *buff, int size){ unsigned char *base, *es_base; pmt_t *pmt; int32_t idx, es_count, section_bytes; uint8_t m=0; int skip; pmt_t *tmp; struct pmt_es_t *tmp_es; ts_section_t *section; ES_stream_t *tss; idx = progid_idx_in_pmt(priv, progid); if(idx == -1) { int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t); tmp = realloc_struct(priv->pmt, priv->pmt_cnt + 1, sizeof(pmt_t)); if(tmp == NULL) { mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz); return 0; } priv->pmt = tmp; idx = priv->pmt_cnt; memset(&(priv->pmt[idx]), 0, sizeof(pmt_t)); priv->pmt_cnt++; priv->pmt[idx].progid = progid; } pmt = &(priv->pmt[idx]); section = &(pmt->section); skip = collect_section(section, is_start, buff, size); if(! skip) return 0; base = &(section->buffer[skip]); mp_msg(MSGT_DEMUX, MSGL_V, "FILL_PMT(prog=%d), PMT_len: %d, IS_START: %d, TS_PID: %d, SIZE=%d, M=%d, ES_CNT=%d, IDX=%d, PMT_PTR=%p\n", progid, pmt->section.buffer_len, is_start, pid, size, m, pmt->es_cnt, idx, pmt); pmt->table_id = base[0]; if(pmt->table_id != 2) return -1; pmt->ssi = base[1] & 0x80; pmt->section_length = (((base[1] & 0xf) << 8 ) | base[2]); pmt->version_number = (base[5] >> 1) & 0x1f; pmt->curr_next = (base[5] & 1); pmt->section_number = base[6]; pmt->last_section_number = base[7]; pmt->PCR_PID = ((base[8] & 0x1f) << 8 ) | base[9]; pmt->prog_descr_length = ((base[10] & 0xf) << 8 ) | base[11]; if(pmt->prog_descr_length > pmt->section_length - 9) { mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, INVALID PROG_DESCR LENGTH (%d vs %d)\n", pmt->prog_descr_length, pmt->section_length - 9); return -1; } if(pmt->prog_descr_length) parse_program_descriptors(pmt, &base[12], pmt->prog_descr_length); es_base = &base[12 + pmt->prog_descr_length]; //the beginning of th ES loop section_bytes= pmt->section_length - 13 - pmt->prog_descr_length; es_count = 0; while(section_bytes >= 5) { int es_pid, es_type; es_type = es_base[0]; es_pid = ((es_base[1] & 0x1f) << 8) | es_base[2]; idx = es_pid_in_pmt(pmt, es_pid); if(idx == -1) { int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1); tmp_es = realloc_struct(pmt->es, pmt->es_cnt + 1, sizeof(struct pmt_es_t)); if(tmp_es == NULL) { mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz); continue; } pmt->es = tmp_es; idx = pmt->es_cnt; memset(&(pmt->es[idx]), 0, sizeof(struct pmt_es_t)); pmt->es_cnt++; } pmt->es[idx].descr_length = ((es_base[3] & 0xf) << 8) | es_base[4]; if(pmt->es[idx].descr_length > section_bytes - 5) { mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, ES_DESCR_LENGTH TOO LARGE %d > %d, EXIT\n", pmt->es[idx].descr_length, section_bytes - 5); return -1; } pmt->es[idx].pid = es_pid; if(es_type != 0x6) pmt->es[idx].type = UNKNOWN; else pmt->es[idx].type = es_type; parse_descriptors(&pmt->es[idx], &es_base[5]); switch(es_type) { case 1: pmt->es[idx].type = VIDEO_MPEG1; break; case 2: pmt->es[idx].type = VIDEO_MPEG2; break; case 3: case 4: pmt->es[idx].type = AUDIO_MP2; break; case 6: if(pmt->es[idx].type == 0x6) //this could have been ovrwritten by parse_descriptors pmt->es[idx].type = UNKNOWN; break; case 0x10: pmt->es[idx].type = VIDEO_MPEG4; break; case 0x0f: case 0x11: pmt->es[idx].type = AUDIO_AAC; break; case 0x1b: pmt->es[idx].type = VIDEO_H264; break; case 0x12: pmt->es[idx].type = SL_PES_STREAM; break; case 0x13: pmt->es[idx].type = SL_SECTION; break; case 0x81: pmt->es[idx].type = AUDIO_A52; break; case 0x8A: pmt->es[idx].type = AUDIO_DTS; break; case 0xEA: pmt->es[idx].type = VIDEO_VC1; break; default: mp_msg(MSGT_DEMUX, MSGL_DBG2, "UNKNOWN ES TYPE=0x%x\n", es_type); pmt->es[idx].type = UNKNOWN; } tss = priv->ts.pids[es_pid]; //an ES stream if(tss == NULL) { tss = new_pid(priv, es_pid); if(tss) tss->type = pmt->es[idx].type; } section_bytes -= 5 + pmt->es[idx].descr_length; mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT(%d INDEX %d), STREAM: %d, FOUND pid=0x%x (%d), type=0x%x, ES_DESCR_LENGTH: %d, bytes left: %d\n", progid, idx, es_count, pmt->es[idx].pid, pmt->es[idx].pid, pmt->es[idx].type, pmt->es[idx].descr_length, section_bytes); es_base += 5 + pmt->es[idx].descr_length; es_count++; } mp_msg(MSGT_DEMUX, MSGL_V, "----------------------------\n"); return 1;}static pmt_t* pmt_of_pid(ts_priv_t *priv, int pid, mp4_decoder_config_t **mp4_dec){ int32_t i, j, k; if(priv->pmt) { for(i = 0; i < priv->pmt_cnt; i++) { if(priv->pmt[i].es && priv->pmt[i].es_cnt) { for(j = 0; j < priv->pmt[i].es_cnt; j++) { if(priv->pmt[i].es[j].pid == pid) { //search mp4_es_id if(priv->pmt[i].es[j].mp4_es_id) { for(k = 0; k < priv->pmt[i].mp4es_cnt; k++) { if(priv->pmt[i].mp4es[k].id == priv->pmt[i].es[j].mp4_es_id) { *mp4_dec = &(priv->pmt[i].mp4es[k].decoder); break; } } } return &(priv->pmt[i]); } } } } } return NULL;}static inline int32_t pid_type_from_pmt(ts_priv_t *priv, int pid){ int32_t pmt_idx, pid_idx, i, j; pmt_idx = progid_idx_in_pmt(priv, priv->prog); if(pmt_idx != -1) { pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid); if(pid_idx != -1) return priv->pmt[pmt_idx].es[pid_idx].type; } //else //{ for(i = 0; i < priv->pmt_cnt; i++) { pmt_t *pmt = &(priv->pmt[i]); for(j = 0; j < pmt->es_cnt; j++) if(pmt->es[j].pid == pid) return pmt->es[j].type; } //} return UNKNOWN;}static inline uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid){ int32_t pmt_idx, pid_idx, i, j; pmt_idx = progid_idx_in_pmt(priv, priv->prog); if(pmt_idx != -1) { pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid); if(pid_idx != -1) return priv->pmt[pmt_idx].es[pid_idx].lang; } else { for(i = 0; i < priv->pmt_cnt; i++) { pmt_t *pmt = &(priv->pmt[i]); for(j = 0; j < pmt->es_cnt; j++) if(pmt->es[j].pid == pid) return pmt->es[j].lang; } } return NULL;}static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset, TS_stream_info *si){ int ret = 0; if((*dp != NULL) && (*dp_offset > 0)) { ret = *dp_offset; resize_demux_packet(*dp, ret); //shrinked to the right size ds_add_packet(ds, *dp); mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d bytes to %s fifo, PTS=%.3f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts); if(si) { float diff = (*dp)->pts - si->last_pts; float dur; if(abs(diff) > 1) //1 second, there's a discontinuity { si->duration += si->last_pts - si->first_pts; si->first_pts = si->last_pts = (*dp)->pts; } else { si->last_pts = (*dp)->pts; } si->size += ret; dur = si->duration + (si->last_pts - si->first_pts); if(dur > 0 && ds == demuxer->video) { ts_priv_t * priv = (ts_priv_t*) demuxer->priv; if(dur > 1) //otherwise it may be unreliable priv->vbitrate = (uint32_t) ((float) si->size / dur); } } } *dp = NULL; *dp_offset = 0; return ret;}static int fill_extradata(mp4_decoder_config_t * mp4_dec, ES_stream_t *tss){ uint8_t *tmp; mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4_dec: %p, pid: %d\n", mp4_dec, tss->pid); if(mp4_dec->buf_size > tss->extradata_alloc) { tmp = (uint8_t *) realloc(tss->extradata, mp4_dec->buf_size); if(!tmp) return 0; tss->extradata = tmp; tss->extradata_alloc = mp4_dec->buf_size; } memcpy(tss->extradata, mp4_dec->buf, mp4_dec->buf_size); tss->extradata_len = mp4_dec->buf_size; mp_msg(MSGT_DEMUX, MSGL_V, "EXTRADATA: %p, alloc=%d, len=%d\n", tss->extradata, tss->extradata_alloc, tss->extradata_len); return tss->extradata_len;}// 0 = EOF or no stream found// else = [-] number of bytes written to the packetstatic int ts_parse(demuxer_t *demuxer , ES_stream_t *es, unsigned char *packet, int probe){ ES_stream_t *tss; uint8_t done = 0; int buf_size, is_start, pid, base; int len, cc, cc_ok, afc, retv = 0, is_video, is_audio, is_sub; ts_priv_t * priv = (ts_priv_t*) demuxer->priv; stream_t *stream = demuxer->stream; char *p; demux_stream_t *ds = NULL; demux_packet_t **dp = NULL; int *dp_offset = 0, *buffer_size = 0; int32_t progid, pid_type, bad, ts_error; int junk = 0, rap_flag = 0; pmt_t *pmt; mp4_decoder_config_t *mp4_dec; TS_stream_info *si; while(! done) { bad = ts_error = 0; ds = (demux_stream_t*) NULL; dp = (demux_packet_t **) NULL; dp_offset = buffer_size = NULL; rap_flag = 0; mp4_dec = NULL; es->is_synced = 0; si = NULL; junk = priv->ts.packet_size - TS_PACKET_SIZE; buf_size = priv->ts.packet_size - junk; if(stream_eof(stream)) { if(! probe) { ts_dump_streams(priv); demuxer->filepos = stream_tell(demuxer->stream); } return 0; } if(! ts_sync(stream)) { mp_msg(MSGT_DEMUX, MSGL_INFO, "TS_PARSE: COULDN'T SYNC\n"); return 0; } len = stream_read(stream, &packet[1], 3); if (len != 3) return 0; buf_size -= 4; if((packet[1] >> 7) & 0x01) //transport error ts_error = 1; is_start = packet[1] & 0x40; pid = ((packet[1] & 0x1f) << 8) | packet[2]; tss = priv->ts.pids[pid]; //an ES stream if(tss == NULL) { tss = new_pid(priv, pid); if(tss == NULL) continue; } cc = (packet[3] & 0xf); cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc)); tss->last_cc = cc; bad = ts_error; // || (! cc_ok); if(bad) { if(priv->keep_broken == 0) { stream_skip(stream, buf_size-1+junk); continue; } is_start = 0; //queued to the packet data } if(is_start) tss->is_synced = 1; if((!is_start && !tss->is_synced) || ((pid > 1) && (pid < 16)) || (pid == 8191)) //invalid pid { stream_skip(stream, buf_size-1+junk); continue; } afc = (packet[3] >> 4) & 3; if(! (afc % 2)) //no payload in this TS packet { stream_skip(stream, buf_size-1+junk); continue; } if(afc > 1) { int c; c = stream_read_char(stream); buf_size--; if(c < 0 || c > 183) //broken from the stream layer or invalid { stream_skip(stream, buf_size-1+junk); continue; } //c==0 is allowed! if(c > 0) { rap_flag = (stream_read_char(stream) & 0x40) >> 6; buf_size--; c--; stream_skip(stream, c); buf_size -= c; if(buf_size == 0) continue; } } //find the program that the pid belongs to; if (it's the right one or -1) && pid_type==SL_SECTION //call parse_sl_section() pmt = pmt_of_pid(priv, pid, &mp4_dec); if(mp4_dec)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -