📄 demux_ts.c
字号:
mp_msg(MSGT_DEMUX, MSGL_DBG2, "PARSE_MP4_DESC_LEN(%d), bytes: ", *len); j = min(*len, 4); while(i < j) { mp_msg(MSGT_DEMUX, MSGL_DBG2, " %x ", buf[i]); size |= (buf[i] & 0x7f); if(!(buf[i] & 0x80)) break; size <<= 7; i++; } mp_msg(MSGT_DEMUX, MSGL_DBG2, ", SIZE=%d\n", size); *len = i+1; return size;}static uint16_t parse_mp4_slconfig_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int i = 0; mp4_es_descr_t *es; mp4_sl_config_t *sl; mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_SLCONFIG_DESCRIPTOR(%d)\n", len); es = (mp4_es_descr_t *) elem; if(!es) { mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n"); return len; } sl = &(es->sl); sl->ts_len = sl->ocr_len = sl->au_len = sl->instant_bitrate_len = sl->degr_len = sl->au_seqnum_len = sl->packet_seqnum_len = 0; sl->ocr = sl->dts = sl->cts = 0; if(buf[0] == 0) { i++; sl->flags = buf[i]; i++; sl->ts_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3]; i += 4; sl->ocr_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3]; i += 4; sl->ts_len = buf[i]; i++; sl->ocr_len = buf[i]; i++; sl->au_len = buf[i]; i++; sl->instant_bitrate_len = buf[i]; i++; sl->degr_len = (buf[i] >> 4) & 0x0f; sl->au_seqnum_len = ((buf[i] & 0x0f) << 1) | ((buf[i+1] >> 7) & 0x01); i++; sl->packet_seqnum_len = ((buf[i] >> 2) & 0x1f); i++; } else if(buf[0] == 1) { sl->flags = 0; sl->ts_resolution = 1000; sl->ts_len = 32; i++; } else if(buf[0] == 2) { sl->flags = 4; i++; } else { sl->flags = 0; i++; } sl->au_start = (sl->flags >> 7) & 0x1; sl->au_end = (sl->flags >> 6) & 0x1; sl->random_accesspoint = (sl->flags >> 5) & 0x1; sl->random_accesspoint_only = (sl->flags >> 4) & 0x1; sl->padding = (sl->flags >> 3) & 0x1; sl->use_ts = (sl->flags >> 2) & 0x1; sl->idle = (sl->flags >> 1) & 0x1; sl->duration = sl->flags & 0x1; if(sl->duration) { sl->timescale = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3]; i += 4; sl->au_duration = (buf[i] << 8) | buf[i+1]; i += 2; sl->cts_duration = (buf[i] << 8) | buf[i+1]; i += 2; } else //no support for fixed durations atm sl->timescale = sl->au_duration = sl->cts_duration = 0; mp_msg(MSGT_DEMUX, MSGL_V, "MP4SLCONFIG(len=0x%x), predef: %d, flags: %x, use_ts: %d, tslen: %d, timescale: %d, dts: %llu, cts: %llu\n", len, buf[0], sl->flags, sl->use_ts, sl->ts_len, sl->timescale, (uint64_t) sl->dts, (uint64_t) sl->cts); return len;}static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem);static uint16_t parse_mp4_decoder_config_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int i = 0, j; mp4_es_descr_t *es; mp4_decoder_config_t *dec; mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_CONFIG_DESCRIPTOR(%d)\n", len); es = (mp4_es_descr_t *) elem; if(!es) { mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n"); return len; } dec = (mp4_decoder_config_t*) &(es->decoder); dec->object_type = buf[i]; dec->stream_type = (buf[i+1]>>2) & 0x3f; if(dec->object_type == 1 && dec->stream_type == 1) { dec->object_type = MP4_OD; dec->stream_type = MP4_OD; } else if(dec->stream_type == 4) { if(dec->object_type == 0x6a) dec->object_type = VIDEO_MPEG1; if(dec->object_type >= 0x60 && dec->object_type <= 0x65) dec->object_type = VIDEO_MPEG2; else if(dec->object_type == 0x20) dec->object_type = VIDEO_MPEG4; else if(dec->object_type == 0x21) dec->object_type = VIDEO_AVC; /*else if(dec->object_type == 0x22) fprintf(stderr, "TYPE 0x22\n");*/ else dec->object_type = UNKNOWN; } else if(dec->stream_type == 5) { if(dec->object_type == 0x40) dec->object_type = AUDIO_AAC; else if(dec->object_type == 0x6b) dec->object_type = AUDIO_MP2; else if(dec->object_type >= 0x66 && dec->object_type <= 0x69) dec->object_type = AUDIO_MP2; else dec->object_type = UNKNOWN; } else dec->object_type = dec->stream_type = UNKNOWN; if(dec->object_type != UNKNOWN) { //update the type of the current stream for(j = 0; j < pmt->es_cnt; j++) { if(pmt->es[j].mp4_es_id == es->id) { pmt->es[j].type = SL_PES_STREAM; } } } if(len > 13) parse_mp4_descriptors(pmt, &buf[13], len-13, dec); mp_msg(MSGT_DEMUX, MSGL_V, "MP4DECODER(0x%x), object_type: 0x%x, stream_type: 0x%x\n", len, dec->object_type, dec->stream_type); return len;}static uint16_t parse_mp4_decoder_specific_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int i; mp4_decoder_config_t *dec; mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_SPECIFIC_DESCRIPTOR(%d)\n", len); dec = (mp4_decoder_config_t *) elem; if(!dec) { mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n"); return len; } mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4 SPECIFIC INFO BYTES: \n"); for(i=0; i<len; i++) mp_msg(MSGT_DEMUX, MSGL_DBG2, "%02x ", buf[i]); mp_msg(MSGT_DEMUX, MSGL_DBG2, "\n"); memcpy(dec->buf, buf, len); dec->buf_size = len; return len;}static uint16_t parse_mp4_es_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int i = 0, j = 0, k, found; uint8_t flag; mp4_es_descr_t es, *target_es = NULL, *tmp; mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES: len=%d\n", len); memset(&es, 0, sizeof(mp4_es_descr_t)); while(i < len) { es.id = (buf[i] << 8) | buf[i+1]; mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_ID: %d\n", es.id); i += 2; flag = buf[i]; i++; if(flag & 0x80) i += 2; if(flag & 0x40) i += buf[i]+1; if(flag & 0x20) //OCR, maybe we need it i += 2; j = parse_mp4_descriptors(pmt, &buf[i], len-i, &es); mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES, types after parse_mp4_descriptors: 0x%x, 0x%x\n", es.decoder.object_type, es.decoder.stream_type); if(es.decoder.object_type != UNKNOWN && es.decoder.stream_type != UNKNOWN) { found = 0; //search this ES_ID if we already have it for(k=0; k < pmt->mp4es_cnt; k++) { if(pmt->mp4es[k].id == es.id) { target_es = &(pmt->mp4es[k]); found = 1; } } if(! found) { tmp = (mp4_es_descr_t *) realloc(pmt->mp4es, sizeof(mp4_es_descr_t)*(pmt->mp4es_cnt+1)); if(tmp == NULL) { fprintf(stderr, "CAN'T REALLOC MP4_ES_DESCR\n"); continue; } pmt->mp4es = tmp; target_es = &(pmt->mp4es[pmt->mp4es_cnt]); pmt->mp4es_cnt++; } memcpy(target_es, &es, sizeof(mp4_es_descr_t)); mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_CNT: %d, ID=%d\n", pmt->mp4es_cnt, target_es->id); } i += j; } return len;}static void parse_mp4_object_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int i, j = 0, id; id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6); mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_OBJECT_DESCRIPTOR: len=%d, OD_ID=%d\n", len, id); if(buf[1] & 0x20) { i += buf[2] + 1; //url mp_msg(MSGT_DEMUX, MSGL_V, "URL\n"); } else { i = 2; while(i < len) { j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem); mp_msg(MSGT_DEMUX, MSGL_V, "OBJD, NOW i = %d, j=%d, LEN=%d\n", i, j, len); i += j; } }}static void parse_mp4_iod(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int i, j = 0; mp4_od_t *iod = &(pmt->iod); iod->id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6); mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_IOD: len=%d, IOD_ID=%d\n", len, iod->id); i = 2; if(buf[1] & 0x20) { i += buf[2] + 1; //url mp_msg(MSGT_DEMUX, MSGL_V, "URL\n"); } else { i = 7; while(i < len) { j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem); mp_msg(MSGT_DEMUX, MSGL_V, "IOD, NOW i = %d, j=%d, LEN=%d\n", i, j, len); i += j; } }}static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem){ int tag, descr_len, i = 0, j = 0; mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DESCRIPTORS, len=%d\n", len); if(! len) return len; while(i < len) { tag = buf[i]; j = len - i -1; descr_len = get_mp4_desc_len(&(buf[i+1]), &j); mp_msg(MSGT_DEMUX, MSGL_V, "TAG=%d (0x%x), DESCR_len=%d, len=%d, j=%d\n", tag, tag, descr_len, len, j); if(descr_len > len - j+1) { mp_msg(MSGT_DEMUX, MSGL_V, "descriptor is too long, exit\n"); return len; } i += j+1; switch(tag) { case 0x1: parse_mp4_object_descriptor(pmt, &(buf[i]), descr_len, elem); break; case 0x2: parse_mp4_iod(pmt, &(buf[i]), descr_len, elem); break; case 0x3: parse_mp4_es_descriptor(pmt, &(buf[i]), descr_len, elem); break; case 0x4: parse_mp4_decoder_config_descriptor(pmt, &buf[i], descr_len, elem); break; case 0x05: parse_mp4_decoder_specific_descriptor(pmt, &buf[i], descr_len, elem); break; case 0x6: parse_mp4_slconfig_descriptor(pmt, &buf[i], descr_len, elem); break; default: mp_msg(MSGT_DEMUX, MSGL_V, "Unsupported mp4 descriptor 0x%x\n", tag); } i += descr_len; } return len;}static ES_stream_t *new_pid(ts_priv_t *priv, int pid){ ES_stream_t *tss; tss = malloc(sizeof(ES_stream_t)); if(! tss) return NULL; memset(tss, 0, sizeof(ES_stream_t)); tss->pid = pid; tss->last_cc = -1; tss->type = UNKNOWN; tss->subtype = UNKNOWN; tss->is_synced = 0; tss->extradata = NULL; tss->extradata_alloc = tss->extradata_len = 0; priv->ts.pids[pid] = tss; return tss;}static int parse_program_descriptors(pmt_t *pmt, uint8_t *buf, uint16_t len){ uint16_t i = 0, k, olen = len; while(len > 0) { mp_msg(MSGT_DEMUX, MSGL_V, "PROG DESCR, TAG=%x, LEN=%d(%x)\n", buf[i], buf[i+1], buf[i+1]); if(buf[i+1] > len-2) { mp_msg(MSGT_DEMUX, MSGL_V, "ERROR, descriptor len is too long, skipping\n"); return olen; } if(buf[i] == 0x1d) { if(buf[i+3] == 2) //buggy versions of vlc muxer make this non-standard mess (missing iod_scope) k = 3; else k = 4; //this is standard compliant parse_mp4_descriptors(pmt, &buf[i+k], (int) buf[i+1]-(k-2), NULL); } len -= 2 + buf[i+1]; } return olen;}static int parse_descriptors(struct pmt_es_t *es, uint8_t *ptr){ int j, descr_len, len; j = 0; len = es->descr_length; while(len > 2) { descr_len = ptr[j+1]; mp_msg(MSGT_DEMUX, MSGL_V, "...descr id: 0x%x, len=%d\n", ptr[j], descr_len); if(descr_len > len) { mp_msg(MSGT_DEMUX, MSGL_ERR, "INVALID DESCR LEN for tag %02x: %d vs %d max, EXIT LOOP\n", ptr[j], descr_len, len); return -1; } if(ptr[j] == 0x6a) //A52 Descriptor { if(es->type == 0x6) { es->type = AUDIO_A52; mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB A52 Descriptor\n"); } } else if(ptr[j] == 0x59) //Subtitling Descriptor { uint8_t subtype; mp_msg(MSGT_DEMUX, MSGL_DBG2, "Subtitling Descriptor\n"); if(descr_len < 8) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Descriptor length too short for DVB Subtitle Descriptor: %d, SKIPPING\n", descr_len); } else { memcpy(es->lang, &ptr[j+2], 3); es->lang[3] = 0; subtype = ptr[j+5]; if( (subtype >= 0x10 && subtype <= 0x13) || (subtype >= 0x20 && subtype <= 0x23) ) { es->type = SPU_DVB; //page parameters: compo page 2 bytes, ancillary page 2 bytes } else es->type = UNKNOWN; } } else if(ptr[j] == 0x50) //Component Descriptor { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Component Descriptor\n"); memcpy(es->lang, &ptr[j+5], 3); es->lang[3] = 0; } else if(ptr[j] == 0xa) //Language Descriptor { memcpy(es->lang, &ptr[j+2], 3); 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 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, uint16_t progid, uint16_t pid, 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 skip, m=0; pmt_t *tmp; struct pmt_es_t *tmp_es; ts_section_t *section; ES_stream_t *tss;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -