📄 mpeg2_transport.c
字号:
buflen,
section_len,
mpeg2t_continuity_counter(buffer));
return 0;
}
// pmapptr points to program number
}
prog_num = ((pmapptr[0] << 8) | pmapptr[1]);
if (prog_num != pmap_pid->program_number) {
mpeg2t_message(LOG_ERR,
"Prog Map error - program number doesn't match - pid %x orig %x from pak %x",
pmap_pid->pid.pid, pmap_pid->program_number, prog_num);
return 0;
}
pmap_pid->version_number = (pmapptr[2] >> 1) & 0x1f;
pcr_pid = ((pmapptr[5] << 8) | pmapptr[6]) & 0x1fff;
if (pcr_pid != 0x1fff) {
mpeg2t_message(LOG_DEBUG, "Have PCR pid of %x", pcr_pid);
}
pmapptr += 7;
section_len -= 7; // remove all the fixed fields to get the prog info len
len = ((pmapptr[0] << 8) | pmapptr[1]) & 0xfff;
pmapptr += 2;
section_len -= 2;
if (len != 0) {
if (len > section_len) return 0;
if (len == pmap_pid->prog_info_len) {
// same length - do a compare
} else {
}
pmapptr += len;
section_len -= len;
}
section_len -= 4; // remove CRC
len = 0;
while (len < section_len) {
stream_type = pmapptr[0];
e_pid = ((pmapptr[1] << 8) | pmapptr[2]) & 0x1fff;
es_len = ((pmapptr[3] << 8) | pmapptr[4]) & 0xfff;
if (es_len + len > section_len) return 0;
if (mpeg2t_lookup_pid(ptr, e_pid) == NULL) {
mpeg2t_message(LOG_INFO, "Creating es pid %x", e_pid);
create_es(ptr, e_pid, stream_type, &pmapptr[5], es_len);
}
// create_es
len += 5 + es_len;
pmapptr += 5 + es_len;
}
return 1;
}
static void clean_es_data (mpeg2t_es_t *es_pid)
{
switch (es_pid->stream_type) {
case 1:
case 2:
// mpeg1 or mpeg2 video
es_pid->work_state = 0;
es_pid->header = 0;
es_pid->work_loaded = 0;
es_pid->have_seq_header = 0;
break;
case 3:
case 4:
// mpeg1/mpeg2 audio (mp3 codec
if (es_pid->work != NULL ) {
free(es_pid->work);
es_pid->work = NULL;
}
es_pid->work_loaded = 0;
es_pid->left = 0;
break;
case 0xf:
// aac
break;
}
}
void mpeg2t_malloc_es_work (mpeg2t_es_t *es_pid, uint32_t frame_len)
{
uint8_t *frameptr;
if (es_pid->work == NULL || es_pid->work->frame_len < frame_len) {
if (es_pid->work != NULL) {
free(es_pid->work);
es_pid->work = NULL;
}
frameptr = (uint8_t *)malloc(sizeof(mpeg2t_frame_t) + frame_len);
if (frameptr == NULL) return;
es_pid->work = (mpeg2t_frame_t *)frameptr;
es_pid->work->frame = frameptr + sizeof(mpeg2t_frame_t);
es_pid->work->frame_len = frame_len;
}
es_pid->work->next_frame = NULL;
es_pid->work->have_ps_ts = es_pid->have_ps_ts;
es_pid->work->ps_ts = es_pid->ps_ts;
es_pid->have_ps_ts = 0;
es_pid->work_loaded = 0;
}
void mpeg2t_finished_es_work (mpeg2t_es_t *es_pid,
uint32_t frame_len)
{
mpeg2t_frame_t *p;
es_pid->work->frame_len = frame_len;
if (es_pid->list == NULL) {
es_pid->list = es_pid->work;
} else {
p = es_pid->list;
while (p->next_frame != NULL) p = p->next_frame;
p->next_frame = es_pid->work;
}
es_pid->work = NULL;
es_pid->work_loaded = 0;
}
static int mpeg2t_process_es (mpeg2t_t *ptr,
mpeg2t_pid_t *ifptr,
const uint8_t *buffer)
{
uint32_t buflen;
uint32_t pes_len;
const uint8_t *esptr;
mpeg2t_es_t *es_pid = (mpeg2t_es_t *)ifptr;
int read_pes_options;
uint8_t stream_id;
uint32_t nextcc, pakcc;
int ret;
nextcc = ifptr->lastcc;
nextcc = (nextcc + 1) & 0xf;
pakcc = mpeg2t_continuity_counter(buffer);
if (nextcc != pakcc) {
mpeg2t_message(LOG_ERR, "cc error in PES %x should be %d is %d",
ifptr->pid, nextcc, pakcc);
clean_es_data(es_pid);
}
ifptr->lastcc = pakcc;
buflen = 188;
// process pas pointer
esptr = mpeg2t_transport_payload_start(buffer, &buflen);
if (esptr == NULL) return -1;
if (mpeg2t_payload_unit_start_indicator(buffer) != 0) {
// start of PES packet
if ((esptr[0] != 0) ||
(esptr[1] != 0) ||
(esptr[2] != 1)) {
mpeg2t_message(LOG_ERR,
"Illegal start to PES packet - pid %x - %02x %02x %02x",
ifptr->pid, esptr[0], esptr[1], esptr[2]);
return -1;
}
stream_id = es_pid->stream_id = esptr[3];
pes_len = (esptr[4] << 8) | esptr[5];
esptr += 6;
buflen -= 6;
read_pes_options = 0;
// do we have header extensions
switch ((stream_id & 0x70) >> 4) {
default:
if ((stream_id == 0xbd) ||
(stream_id >= 0xf3 && stream_id <= 0xf7) ||
(stream_id >= 0xf9 && stream_id <= 0xff)) {
read_pes_options = 1;
break;
}
// fall through
case 4:
case 5:
case 6:
if (esptr[2] <= buflen - 3) {
// multiple PES for header
read_pes_options = 1;
} else {
// don't have enough to read the header
}
break;
}
if (read_pes_options) {
if (esptr[2] + 3 > buflen) {
return 0;
}
//mpeg2t_read_pes_options(es_pid, esptr);
if (((esptr[1] & 0xc0) == 0x80) ||
((esptr[1] & 0xc0) == 0xc0)) {
// read presentation timestamp
uint64_t pts;
#if 1
mpeg2t_message(LOG_DEBUG, "Stream %x %02x %02x %02x",
stream_id, esptr[0], esptr[1], esptr[2]);
mpeg2t_message(LOG_DEBUG, "PTS %02x %02x %02x %02x %02x",
esptr[3], esptr[4], esptr[5], esptr[6], esptr[7]);
#endif
if (((esptr[1] >> 6) & 0x3) !=
((esptr[3] >> 4) & 0xf)) {
mpeg2t_message(LOG_ERR, "PID %x Timestamp flag value not same %x %x",
es_pid->pid.pid, esptr[1], esptr[2]);
return -1;
}
pts = ((esptr[3] >> 1) & 0x7);
pts <<= 8;
pts |= esptr[4];
pts <<= 7;
pts |= ((esptr[5] >> 1) & 0x7f);
pts <<= 8;
pts |= esptr[6];
pts <<= 7;
pts |= ((esptr[7] >> 1) & 0x7f);
es_pid->have_ps_ts = 1;
es_pid->ps_ts = pts;
}
buflen -= esptr[2] + 3;
esptr += esptr[2] + 3;
}
// process esptr, buflen
if (buflen == 0) {
es_pid->have_ps_ts = 0;
return 0;
}
} else {
// 0 in Payload start - process frame at start
read_pes_options = 0;
}
// have start of data is at esptr, buflen data
ret = 0;
switch (es_pid->stream_type) {
case 1:
case 2:
// mpeg1 or mpeg2 video
ret = process_mpeg2t_mpeg_video(es_pid, esptr, buflen);
break;
case 3:
case 4:
// mpeg1/mpeg2 audio (mp3 codec
ret = process_mpeg2t_mpeg_audio(es_pid, esptr, buflen);
break;
case 0xf:
// aac
break;
}
es_pid->have_ps_ts = 0;
return ret;
}
mpeg2t_pid_t *mpeg2t_process_buffer (mpeg2t_t *ptr,
const uint8_t *buffer,
uint32_t buflen,
uint32_t *buflen_used)
{
uint32_t offset;
uint32_t remaining;
uint32_t used;
uint16_t rpid;
mpeg2t_pid_t *pidptr;
int ret;
used = 0;
remaining = buflen;
while (used < buflen) {
offset = mpeg2t_find_sync_byte(buffer, remaining);
if (offset >= remaining) {
*buflen_used = buflen;
return NULL;
}
remaining -= offset;
buffer += offset;
used += offset;
if (remaining < 188) {
*buflen_used = used;
return NULL;
}
// we have a complete buffer
rpid = mpeg2t_pid(buffer);
#if 1
mpeg2t_message(LOG_DEBUG, "Buffer- PID %x start %d cc %d",
rpid, mpeg2t_payload_unit_start_indicator(buffer),
mpeg2t_continuity_counter(buffer));
#endif
if (rpid == 0x1fff) {
// just skip
} else {
// look up pid in table
pidptr = mpeg2t_lookup_pid(ptr, rpid);
if (pidptr != NULL) {
// okay - we've got a valid pid ptr
switch (pidptr->pak_type) {
case MPEG2T_PAS_PAK:
ret = mpeg2t_process_pas(ptr, buffer);
if (ret > 0) {
*buflen_used = used + 188;
return pidptr;
}
break;
case MPEG2T_PROG_MAP_PAK:
ret = mpeg2t_process_pmap(ptr, pidptr, buffer);
if (ret > 0) {
*buflen_used = used + 188;
return pidptr;
}
break;
case MPEG2T_ES_PAK:
if (mpeg2t_process_es(ptr, pidptr, buffer) > 0) {
*buflen_used = used + 188;
return pidptr;
}
break;
}
}
}
used += 188;
buffer += 188;
remaining -= 188;
}
*buflen_used = buflen;
return NULL;
}
mpeg2t_t *create_mpeg2_transport (void)
{
mpeg2t_t *ptr;
ptr = MALLOC_STRUCTURE(mpeg2t_t);
memset(ptr, 0, sizeof(ptr));
ptr->pas.pid.pak_type = MPEG2T_PAS_PAK;
ptr->pas.pid.next_pid = NULL;
ptr->pas.pid.pid = 0;
ptr->pas.pid.collect_pes = 1;
return (ptr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -