📄 demux_ts.c
字号:
while((pos <= init_pos + param->probe) && (! demuxer->stream->eof)) { pos = stream_tell(demuxer->stream); if(ts_parse(demuxer, &es, tmp, 1)) { //Non PES-aligned A52 audio may escape detection if PMT is not present; //in this case we try to find at least 3 A52 syncwords if((es.type == PES_PRIVATE1) && (! audio_found)) { pptr = &pes_priv1[es.pid]; tmpbuf = (char*) realloc(pptr->buf, pptr->pos + es.size); if(tmpbuf != NULL) { pptr->buf = tmpbuf; memcpy(&(pptr->buf[ pptr->pos ]), es.start, es.size); pptr->pos += es.size; if(a52_check(pptr->buf, pptr->pos) > 2) { param->atype = AUDIO_A52; es.type = AUDIO_A52; } } } is_audio = IS_AUDIO(es.type) || ((es.type==SL_PES_STREAM) && IS_AUDIO(es.subtype)); is_video = IS_VIDEO(es.type) || ((es.type==SL_PES_STREAM) && IS_VIDEO(es.subtype)); is_sub = ((es.type == SPU_DVD) || (es.type == SPU_DVB)); if((! is_audio) && (! is_video) && (! is_sub)) continue; if(is_video) { if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VIDEO_ID=%d\n", es.pid); chosen_pid = (req_vpid == es.pid); if((! chosen_pid) && (req_vpid > 0)) continue; } else if(is_audio) { if (identify) { mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", es.pid); if (es.lang[0] > 0) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AID_%d_LANG=%s\n", es.pid, es.lang); } if(req_apid > 0) { chosen_pid = (req_apid == es.pid); if(! chosen_pid) continue; } else if(param->alang[0] > 0) { if(pid_match_lang(priv, es.pid, param->alang) == -1) continue; chosen_pid = 1; param->apid = req_apid = es.pid; } } else if(is_sub) { if (identify) { mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", es.pid); if (es.lang[0] > 0) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_SID_%d_LANG=%s\n", es.pid, es.lang); } chosen_pid = (req_spid == es.pid); if((! chosen_pid) && (req_spid > 0)) continue; } if(req_apid < 0 && (param->alang[0] == 0) && req_vpid < 0 && req_spid < 0) chosen_pid = 1; if((ret == 0) && chosen_pid) { ret = stream_tell(demuxer->stream); } p = progid_for_pid(priv, es.pid, param->prog); if(p != -1) has_tables++; if((param->prog == 0) && (p != -1)) { if(chosen_pid) param->prog = p; } if((param->prog > 0) && (param->prog != p)) { if(audio_found) { if(is_video && (req_vpid == es.pid)) { param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype; param->vpid = es.pid; video_found = 1; break; } } if(video_found) { if(is_audio && (req_apid == es.pid)) { param->atype = IS_AUDIO(es.type) ? es.type : es.subtype; param->apid = es.pid; audio_found = 1; break; } } continue; } mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d, PROG FOUND: %d\n", es.type, es.pid, param->prog); if(is_video) { if((req_vpid == -1) || (req_vpid == es.pid)) { param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype; param->vpid = es.pid; video_found = 1; } } if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found) { //novideo or we have at least 348 audio packets (64 KB) without video (TS with audio only) param->vtype = 0; break; } if(is_sub) { if((req_spid == -1) || (req_spid == es.pid)) { param->stype = es.type; param->spid = es.pid; sub_found = 1; } } if(is_audio) { if((req_apid == -1) || (req_apid == es.pid)) { param->atype = IS_AUDIO(es.type) ? es.type : es.subtype; param->apid = es.pid; audio_found = 1; } } if(audio_found && (param->apid == es.pid) && (! video_found)) num_packets++; if((req_apid == -2) && video_found) { param->atype = 0; break; } if((has_tables==0) && (video_found && audio_found) && (pos >= 1000000)) break; } } for(i=0; i<8192; i++) { if(pes_priv1[i].buf != NULL) { free(pes_priv1[i].buf); pes_priv1[i].buf = NULL; pes_priv1[i].pos = 0; } } if(video_found) { if(param->vtype == VIDEO_MPEG1) mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG1(pid=%d)", param->vpid); else if(param->vtype == VIDEO_MPEG2) mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2(pid=%d)", param->vpid); else if(param->vtype == VIDEO_MPEG4) mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG4(pid=%d)...", param->vpid); else if(param->vtype == VIDEO_H264) mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO H264(pid=%d)...", param->vpid); else if(param->vtype == VIDEO_AVC) mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO AVC(NAL-H264, pid=%d)...", param->vpid); } else { param->vtype = UNKNOWN; //WE DIDN'T MATCH ANY VIDEO STREAM mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO! "); } if(param->atype == AUDIO_MP2) mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MPA(pid=%d)", param->apid); else if(param->atype == AUDIO_A52) mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)", param->apid); else if(param->atype == AUDIO_LPCM_BE) mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO LPCM(pid=%d)", param->apid); else if(param->atype == AUDIO_AAC) mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC(pid=%d)", param->apid); else { audio_found = 0; param->atype = UNKNOWN; //WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO! "); } if(param->stype == SPU_DVD || param->stype == SPU_DVB) mp_msg(MSGT_DEMUXER, MSGL_INFO, " SUB %s(pid=%d) ", (param->stype==SPU_DVD ? "DVD" : "DVB"), param->spid); else { param->stype = UNKNOWN; mp_msg(MSGT_DEMUXER, MSGL_INFO, " NO SUBS (yet)! "); } if(video_found || audio_found) { if(demuxer->stream->eof && (ret == 0)) ret = init_pos; mp_msg(MSGT_DEMUXER, MSGL_INFO, " PROGRAM N. %d\n", param->prog); } else mp_msg(MSGT_DEMUXER, MSGL_INFO, "\n"); for(i=0; i<8192; i++) { if(priv->ts.pids[i] != NULL) { priv->ts.pids[i]->payload_size = 0; priv->ts.pids[i]->pts = priv->ts.pids[i]->last_pts = 0; priv->ts.pids[i]->last_cc = -1; priv->ts.pids[i]->is_synced = 0; } } return ret;}static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h){ int sps, sps_len; unsigned char *ptr; mp_mpeg_header_t picture; if(len < 6) return 0; sps = buf[5] & 0x1f; if(!sps) return 0; sps_len = (buf[6] << 8) | buf[7]; if(!sps_len || (sps_len > len - 8)) return 0; ptr = &(buf[8]); picture.display_picture_width = picture.display_picture_height = 0; h264_parse_sps(&picture, ptr, len - 8); if(!picture.display_picture_width || !picture.display_picture_height) return 0; *w = picture.display_picture_width; *h = picture.display_picture_height; return 1;}demuxer_t *demux_open_ts(demuxer_t * demuxer){ int i; uint8_t packet_size; sh_video_t *sh_video; sh_audio_t *sh_audio; off_t start_pos; tsdemux_init_t params; ts_priv_t * priv = (ts_priv_t*) demuxer->priv; mp_msg(MSGT_DEMUX, MSGL_INFO, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n", demuxer->audio->id, demuxer->video->id, demuxer->sub->id); demuxer->type= DEMUXER_TYPE_MPEG_TS; stream_reset(demuxer->stream); packet_size = ts_check_file(demuxer); if(!packet_size) return NULL; priv = malloc(sizeof(ts_priv_t)); if(priv == NULL) { mp_msg(MSGT_DEMUX, MSGL_FATAL, "DEMUX_OPEN_TS, couldn't allocate enough memory for ts->priv, exit\n"); return NULL; } for(i=0; i < 8192; i++) priv->ts.pids[i] = NULL; priv->pat.progs = NULL; priv->pat.progs_cnt = 0; priv->pat.section.buffer = NULL; priv->pat.section.buffer_len = 0; priv->pmt = NULL; priv->pmt_cnt = 0; priv->keep_broken = ts_keep_broken; priv->ts.packet_size = packet_size; demuxer->priv = priv; if(demuxer->stream->type != STREAMTYPE_FILE) demuxer->seekable = 1; else demuxer->seekable = 1; params.atype = params.vtype = params.stype = UNKNOWN; params.apid = demuxer->audio->id; params.vpid = demuxer->video->id; params.spid = demuxer->sub->id; params.prog = ts_prog; params.probe = ts_probe; if(dvdsub_lang != NULL) { strncpy(params.slang, dvdsub_lang, 3); params.slang[3] = 0; } else memset(params.slang, 0, 4); if(audio_lang != NULL) { strncpy(params.alang, audio_lang, 3); params.alang[3] = 0; } else memset(params.alang, 0, 4); start_pos = ts_detect_streams(demuxer, ¶ms); demuxer->audio->id = params.apid; demuxer->video->id = params.vpid; demuxer->sub->id = params.spid; priv->prog = params.prog; demux_aid_vid_mismatch = 1; // don't identify in new_sh_* since ids don't match if(params.vtype != UNKNOWN) { ES_stream_t *es = priv->ts.pids[params.vpid]; sh_video = new_sh_video(demuxer, 0); if(params.vtype == VIDEO_AVC && es->extradata && es->extradata_len) { int w = 0, h = 0; sh_video->bih = (BITMAPINFOHEADER *) calloc(1, sizeof(BITMAPINFOHEADER) + 4096); sh_video->bih->biSize= sizeof(BITMAPINFOHEADER) + es->extradata_len; sh_video->bih->biCompression = params.vtype; memcpy(sh_video->bih + 1, es->extradata, es->extradata_len); mp_msg(MSGT_DEMUXER,MSGL_DBG2, "EXTRADATA(%d BYTES): \n", es->extradata_len); for(i = 0;i < es->extradata_len; i++) mp_msg(MSGT_DEMUXER,MSGL_DBG2, "%02x ", (int) es->extradata[i]); mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\n"); if(parse_avc_sps(es->extradata, es->extradata_len, &w, &h)) { sh_video->bih->biWidth = w; sh_video->bih->biHeight = h; } } sh_video->ds = demuxer->video; sh_video->format = params.vtype; demuxer->video->sh = sh_video; } if(params.atype != UNKNOWN) { sh_audio = new_sh_audio(demuxer, 0); sh_audio->ds = demuxer->audio; sh_audio->format = params.atype; demuxer->audio->sh = sh_audio; } mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer, audio: %x(pid %d), video: %x(pid %d)...POS=%llu\n", params.atype, demuxer->audio->id, params.vtype, demuxer->video->id, (uint64_t) start_pos); start_pos = (start_pos <= priv->ts.packet_size ? 0 : start_pos - priv->ts.packet_size); demuxer->movi_start = start_pos; stream_reset(demuxer->stream); stream_seek(demuxer->stream, start_pos); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES? priv->last_pid = 8192; //invalid pid for(i = 0; i < 3; i++) { priv->fifo[i].pack = NULL; priv->fifo[i].offset = 0; } priv->fifo[0].ds = demuxer->audio; priv->fifo[1].ds = demuxer->video; priv->fifo[2].ds = demuxer->sub; priv->fifo[0].buffer_size = 1536; priv->fifo[1].buffer_size = 32767; priv->fifo[2].buffer_size = 32767; priv->pat.section.buffer_len = 0; for(i = 0; i < priv->pmt_cnt; i++) priv->pmt[i].section.buffer_len = 0; demuxer->filepos = stream_tell(demuxer->stream); return demuxer;}void demux_close_ts(demuxer_t * demuxer){ uint16_t i; ts_priv_t *priv = (ts_priv_t*) demuxer->priv; if(priv) { if(priv->pat.section.buffer) free(priv->pat.section.buffer); if(priv->pat.progs) free(priv->pat.progs); if(priv->pmt) { for(i = 0; i < priv->pmt_cnt; i++) { if(priv->pmt[i].section.buffer) free(priv->pmt[i].section.buffer); if(priv->pmt[i].es) free(priv->pmt[i].es); } free(priv->pmt); } free(priv); } demuxer->priv=NULL;}extern unsigned char mp_getbits(unsigned char*, unsigned int, unsigned char);#define getbits mp_getbitsstatic int mp4_parse_sl_packet(pmt_t *pmt, uint8_t *buf, uint16_t packet_len, int pid, ES_stream_t *pes_es){ int i, n, m, mp4_es_id = -1; uint64_t v = 0; uint32_t pl_size = 0; int deg_flag = 0; mp4_es_descr_t *es = NULL; mp4_sl_config_t *sl = NULL; uint8_t au_start = 0, au_end = 0, rap_flag = 0, ocr_flag = 0, padding = 0, padding_bits = 0, idle = 0; pes_es->is_synced = 0; mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, pid: %d, pmt: %pm, packet_len: %d\n", pid, pmt, packet_len); if(! pmt || !packet_len) return 0; for(i = 0; i < pmt->es_cnt; i++) { if(pmt->es[i].pid == pid) mp4_es_id = pmt->es[i].mp4_es_id; } if(mp4_es_id < 0) return -1; for(i = 0; i < pmt->mp4es_cnt; i++) { if(pmt->mp4es[i].id == mp4_es_id) es = &(pmt->mp4es[i]); } if(! es) return -1; pes_es->subtype = es->decoder.object_type; sl = &(es->sl); if(!sl) return -1; //now es is the complete es_descriptor of out mp4 ES stream mp_msg(MSGT_DEMUXER,MSGL_DBG2, "ID: %d, FLAGS: 0x%x, subtype: %x\n", es->id, sl->flags, pes_es->subtype); n = 0; if(sl->au_start) pes_es->sl.au_start = au_start = getbits(buf, n++, 1); else pes_es->sl.au_start = (pes_es->sl.last_au_end ? 1 : 0); if(sl->au_end) pes_es->sl.au_end = au_end = getbits(buf, n++, 1); if(!sl->au_start && !sl->au_end) { pes_es->sl.au_start = pes_es->sl.au_end = au_start = au_end = 1; } pes_es->sl.last_au_end = pes_es->sl.au_end; if(sl->ocr_len > 0) ocr_flag = getbits(buf, n++, 1); if(sl->idle) idle = getbits(buf, n++, 1); if(sl->padding) padding = getbits(buf, n++, 1); if(padding) { padding_bits = getbits(buf, n, 3); n += 3; } if(idle || (padding && !padding_bits)) { pes_es->payload_size = 0; return -1; } //(! idle && (!padding || padding_bits != 0)) is true n += sl->packet_seqnum_len; if(sl->degr_len) deg_flag = getbits(buf, n++, 1); if(deg_flag) n += sl->degr_len; if(ocr_flag) { n += sl->ocr_len; mp_msg(MSGT_DEMUXER,MSGL_DBG2, "OCR: %d bits\n", sl->ocr_len); } if(packet_len * 8 <= n) return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -