📄 demux_ts.c
字号:
idx = progid_idx_in_pmt(priv, progid); if(idx == -1) { int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t); tmp = (pmt_t *) realloc(priv->pmt, sz); 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++; } pmt = &(priv->pmt[idx]); section = &(pmt->section); skip = collect_section(section, is_start, buff, size); if(! skip) return 0; base = &(section->buffer[skip]); pmt->progid = progid; 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 = (struct pmt_es_t *) realloc(pmt->es, sz); 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; 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){ 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); } *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; 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; 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; if((packet[1] >> 7) & 0x01) //transport error ts_error = 1; buf_size -= 4; 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; } if(((pid > 1) && (pid < 16)) || (pid == 8191)) //invalid pid { stream_skip(stream, buf_size-1+junk); 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); afc = (packet[3] >> 4) & 3; if(afc > 1) { int c; c = stream_read_char(stream); buf_size--; rap_flag = (stream_read_char(stream) & 0x40) >> 6; buf_size--; c = min(c-1, buf_size); stream_skip(stream, c); buf_size -= c; if(buf_size == 0) continue; } if(! (afc % 2)) //no payload in this TS packet { stream_skip(stream, buf_size-1+junk); continue; } if(bad) { // logically this packet should be dropped, but if I do it // certain streams play corrupted. Maybe the decoders know // how to deal with it, but at least I consider the packet // as "not initial" mp_msg(MSGT_DEMUX, MSGL_V, "ts_parse: PID=%d, Transport error: %d, CC_OK: %s\n\n", tss->pid, ts_error, (cc_ok ? "yes" : "no")); if(priv->keep_broken == 0) { stream_skip(stream, buf_size-1+junk); continue; } is_start = 0; //queued to the packet data } //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) { fill_extradata(mp4_dec, tss); if(IS_VIDEO(mp4_dec->object_type) || IS_AUDIO(mp4_dec->object_type)) { tss->type = SL_PES_STREAM; tss->subtype = mp4_dec->object_type; } } //TABLE PARSING base = priv->ts.packet_size - buf_size; if(pid == 0) { stream_read(stream,&packet[base], buf_size); stream_skip(stream, junk); parse_pat(priv, is_start, &packet[base], buf_size); continue; } else if((tss->type == SL_SECTION) && pmt) { int k, ok=0, mp4_es_id = -1; ts_section_t *section; for(k = 0; k < pmt->mp4es_cnt; k++) { if(pmt->mp4es[k].decoder.object_type == MP4_OD && pmt->mp4es[k].decoder.stream_type == MP4_OD) mp4_es_id = pmt->mp4es[k].id; } mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4ESID: %d\n", mp4_es_id); for(k = 0; k < pmt->es_cnt; k++) { if(pmt->es[k].mp4_es_id == mp4_es_id) ok = 1; } stream_read(stream,&packet[base], buf_size); stream_skip(stream, junk); if(ok) { section = &(tss->section); parse_sl_section(pmt, section, progid, pid, is_start, &packet[base], buf_size); } continue; } else { progid = prog_id_in_pat(priv, pid); if(progid != -1) { if(pid != demuxer->video->id && pid != demuxer->audio->id && pid != demuxer->sub->id) { stream_read(stream,&packet[base], buf_size); stream_skip(stream, junk); parse_pmt(priv, progid, pid, is_start, &packet[base], buf_size); continue; } else mp_msg(MSGT_DEMUX, MSGL_ERR, "Argh! Data pid %d used in the PMT, Skipping PMT parsing!\n", pid); } } priv->last_pid = pid; is_video = IS_VIDEO(tss->type) || (tss->type==SL_PES_STREAM && IS_VIDEO(tss->subtype)); is_audio = IS_AUDIO(tss->type) || (tss->type==SL_PES_STREAM && IS_AUDIO(tss->subtype)) || (tss->type == PES_PRIVATE1); is_sub = ((tss->type == SPU_DVD) || (tss->type == SPU_DVB)); pid_type = pid_type_from_pmt(priv, pid); // PES CONTENT STARTS HERE if(! probe) { if((pid == demuxer->sub->id)) //or the lang is right { pid_type = SPU_DVD; } if(is_video && (demuxer->video->id == tss->pid)) { ds = demuxer->video; dp = &priv->fifo[1].pack; dp_offset = &priv->fifo[1].offset; buffer_size = &priv->fifo[1].buffer_size; } else if(is_audio && (demuxer->audio->id == tss->pid)) { ds = demuxer->audio; dp = &priv->fifo[0].pack; dp_offset = &priv->fifo[0].offset; buffer_size = &priv->fifo[0].buffer_size; } else if(is_sub || (pid_type == SPU_DVD) || (pid_type == SPU_DVB)) { //SUBS are infrequent, so the initial detection may fail // and we may need to add them at play-time if(demuxer->sub->id == -1) { uint16_t p; p = progid_for_pid(priv, tss->pid, priv->prog); if(p == priv->prog) { int asgn = 0; uint8_t *lang; if(!strcmp(dvdsub_lang, "")) asgn = 1; else { lang = pid_lang_from_pmt(priv, pid); if(lang != NULL) asgn = (strncmp(lang, dvdsub_lang, 3) == 0); else asgn = 0; } if(asgn) { demuxer->sub->id = tss->pid; mp_msg(MSGT_DEMUX, MSGL_INFO, "CHOSEN SUBs pid 0x%x (%d) FROM PROG %d\n", tss->pid, tss->pid, priv->prog); } } else { mp_msg(MSGT_DEMUX, MSGL_V, "DISCARDED SUBs pid 0x%x (%d) NOT CHOSEN OR NOT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -