📄 mpeg2dataparser.cpp
字号:
s->audio_num++;
}
else
verbose.showf("more than %i audio channels, truncating\n", AUDIO_CHAN_MAX);
break;
case 0x06:
if (find_descriptor(0x56, buf, ES_info_len, NULL, NULL)) {
verbose.showf(" TELETEXT : PID 0x%04x\n", elementary_pid);
s->teletext_pid = elementary_pid;
break;
}
else if (find_descriptor(0x59, buf, ES_info_len, NULL, NULL)) {
/* Note: The subtitling descriptor can also signal
* teletext subtitling, but then the teletext descriptor
* will also be present; so we can be quite confident
* that we catch DVB subtitling streams only here, w/o
* parsing the descriptor. */
verbose.showf(" SUBTITLING: PID 0x%04x\n", elementary_pid);
s->subtitling_pid = elementary_pid;
break;
}
else if (find_descriptor(0x6a, buf, ES_info_len, NULL, NULL)) {
verbose.showf(" AC3 : PID 0x%04x\n", elementary_pid);
s->ac3_pid = elementary_pid;
parse_descriptorsPMT(buf, ES_info_len, s);
break;
}
/* fall through */
default:
verbose.showf(" OTHER : PID 0x%04x TYPE 0x%02x\n", elementary_pid, streamType);
};
buf += ES_info_len;
section_length -= ES_info_len;
};
tmp = msg_buf;
tmp += sprintf(tmp, "0x%04x (%.4s)", s->audio_pid[0], s->audio_lang[0]);
if (s->audio_num > AUDIO_CHAN_MAX) {
verbose.showf("more than %i audio channels: %i, truncating to %i\n",
AUDIO_CHAN_MAX, s->audio_num, AUDIO_CHAN_MAX);
s->audio_num = AUDIO_CHAN_MAX;
}
for (i=1; i<s->audio_num; i++)
tmp += sprintf(tmp, ", 0x%04x (%.4s)", s->audio_pid[i], s->audio_lang[i]);
verbose.showf ("0x%04x 0x%04x: %s -- %s, pmt_pid 0x%04x, vpid 0x%04x, apid %s\n",
s->transport_stream_id,
s->service_id,
s->provider_name, s->service_name,
s->pmt_pid, s->video_pid, msg_buf);
}
void Mpeg2DataParser::parse_nit (const unsigned char *buf, int section_length, int network_id)
{
int descriptors_loop_len = ((buf[0] & 0x0f) << 8) | buf[1];
if (section_length < descriptors_loop_len + 4)
{
verbose.showf("section too short: network_id == 0x%04x, section_length == %i, "
"descriptors_loop_len == %i\n",
network_id, section_length, descriptors_loop_len);
return;
}
parse_descriptorsNIT (buf + 2, descriptors_loop_len, current_tp);
section_length -= descriptors_loop_len + 4;
buf += descriptors_loop_len + 4;
while (section_length > 6) {
int transport_stream_id = (buf[0] << 8) | buf[1];
struct transponder *t;
t = find_transponder(transport_stream_id);
if (!t)
t = alloc_transponder(transport_stream_id);
t->network_id = network_id;
t->original_network_id = (buf[2] << 8) | buf[3];
descriptors_loop_len = ((buf[4] & 0x0f) << 8) | buf[5];
if (section_length < descriptors_loop_len + 4)
{
verbose.showf("section too short: transport_stream_id == 0x%04x, "
"section_length == %i, descriptors_loop_len == %i\n",
t->transport_stream_id, section_length,
descriptors_loop_len);
break;
}
verbose.showf(" transport_stream_id 0x%04x\n", t->transport_stream_id);
parse_descriptorsNIT (buf + 6, descriptors_loop_len, t);
/* if (tn.type == fe_info.type) {
// only add if develivery_descriptor matches FE type
t = find_transponder(tn.param.frequency);
if (!t)
t = alloc_transponder(tn.param.frequency);
copy_transponder(t, &tn);
}*/
section_length -= descriptors_loop_len + 6;
buf += descriptors_loop_len + 6;
};
}
void Mpeg2DataParser::parse_sdt (const unsigned char *buf, int section_length, int transport_stream_id)
{
buf += 3; /* skip original network id + reserved field */
struct transponder *tp;
tp = find_transponder(transport_stream_id); //i'm not expecting this to return anything, but just in case
if (!tp)
tp = alloc_transponder(transport_stream_id);
while (section_length > 4)
{
int service_id = (buf[0] << 8) | buf[1];
int remainingLength = ((buf[3] & 0x0f) << 8) | buf[4];
struct service *s;
if (section_length < remainingLength || !remainingLength)
{
verbose.showf(" section too short: service_id == 0x%02x, section_length == %i, "
"remainingLength == %i\n",
service_id, section_length,
remainingLength);
return;
}
s = find_service(tp, service_id);
if (!s)
/* maybe PAT has not yet been parsed... */
s = alloc_service(tp, service_id);
s->running = (enum running_mode)((buf[3] >> 5) & 0x7);
s->scrambled = (buf[3] >> 4) & 1;
s->transport_stream_id = transport_stream_id;
parse_descriptorsSDT (buf + 5, remainingLength - 5, s);
section_length -= remainingLength + 5;
buf += remainingLength + 5;
};
}
/**
* returns 0 when more sections are expected
* 1 when all sections are read on this pid
* -1 on invalid table id
*/
int Mpeg2DataParser::parse_section (struct section_buf *s)
{
const unsigned char *buf = s->buf;
int table_id;
int section_length;
int table_id_ext;
int section_version_number;
int section_number;
int last_section_number;
int i;
table_id = buf[0];
SECTION *pSection = (SECTION*)buf;
LONG_SECTION *pLong = (LONG_SECTION*)buf;
MPEG_HEADER_BITS *pHeader = (MPEG_HEADER_BITS*)&pSection->Header.W;
MPEG_HEADER_VERSION_BITS *pVersion = (MPEG_HEADER_VERSION_BITS*)&pLong->Version.B;
if (s->table_id != table_id)
return -1;
section_length = (((buf[2] & 0x0f) << 8) | buf[1]) + 3; //the mpeg2 field doesn't include the first 3 bytes of data
section_length -= 4; //let's ignore the CRC at he end
table_id_ext = (buf[4] << 8) | buf[3];
section_version_number = (buf[5] >> 1) & 0x1f;
section_number = buf[6];
last_section_number = buf[7];
if (s->segmented && s->table_id_ext != -1 && s->table_id_ext != table_id_ext) {
/* find or allocate actual section_buf matching table_id_ext */
while (s->next_seg) {
s = s->next_seg;
if (s->table_id_ext == table_id_ext)
break;
}
if (s->table_id_ext != table_id_ext) {
//assert(s->next_seg == NULL);
s->next_seg = (struct section_buf *)calloc(1, sizeof(struct section_buf));
s->next_seg->segmented = s->segmented;
s->next_seg->run_once = s->run_once;
s->next_seg->timeout = s->timeout;
s = s->next_seg;
s->table_id = table_id;
s->table_id_ext = table_id_ext;
s->section_version_number = section_version_number;
}
}
if (s->section_version_number != section_version_number ||
s->table_id_ext != table_id_ext) {
struct section_buf *next_seg = s->next_seg;
if (s->section_version_number != -1 && s->table_id_ext != -1)
verbose.showf("section version_number or table_id_ext changed "
"%d -> %d / %04x -> %04x\n",
s->section_version_number, section_version_number,
s->table_id_ext, table_id_ext);
s->table_id_ext = table_id_ext;
s->section_version_number = section_version_number;
s->sectionfilter_done = 0;
memset (s->section_done, 0, sizeof(s->section_done));
s->next_seg = next_seg;
}
buf += 8;
section_length -= 8;
if (!get_bit(s->section_done, section_number)) {
set_bit (s->section_done, section_number);
verbose.showf("pid 0x%02x tid 0x%02x table_id_ext 0x%04x, "
"%i/%i (version %i)\n",
s->pid, table_id, table_id_ext, section_number,
last_section_number, section_version_number);
switch (table_id)
{
case 0x00:
verbose.showf("PAT\n");
parse_pat (buf, section_length, table_id_ext);
break;
case 0x02:
verbose.showf("PMT 0x%04x for service 0x%04x\n", s->pid, table_id_ext);
parse_pmt (buf, section_length, table_id_ext);
break;
case 0x41:
verbose.showf("////////////////////////////////////////////// NIT other\n");
case 0x40:
verbose.showf("NIT (%s TS)\n", table_id == 0x40 ? "actual":"other");
parse_nit (buf, section_length, table_id_ext);
break;
case 0x42:
case 0x46:
verbose.showf("SDT (%s TS)\n", table_id == 0x42 ? "actual":"other");
parse_sdt (buf, section_length, table_id_ext);
break;
default:
;
};
for (i = 0; i <= last_section_number; i++)
if (get_bit (s->section_done, i) == 0)
break;
if (i > last_section_number)
s->sectionfilter_done = 1;
}
if (s->segmented) {
/* always wait for timeout; this is because we don't now how
* many segments there are
*/
return 0;
}
else if (s->sectionfilter_done)
return 1;
return 0;
}
void Mpeg2DataParser::PrintByteArray(const BYTE *pData, long cbSize)
{
char str[9];
memset((char*)&str, 32, 8);
str[8] = '\0';
int iter = 0;
for (iter = 0; iter < cbSize; iter++)
{
int pos = iter % 8;
if (pos == 0)
verbose.showf("\t");
verbose.showf("0x%.2x ", pData[iter]);
if ((pData[iter] >= 32) && (pData[iter] <= 126))
str[pos] = pData[iter];
if (pos == 7)
{
verbose.showf(" %S\n", (char*)&str);
memset((char*)&str, 32, 8);
}
}
int missing = 8 - (((iter-1)%8)+1);
if (missing != 0)
{
for (int i=0 ; i< missing ; i++ )
verbose.showf(" ");
verbose.showf(" %S\n", (char*)&str);
}
}
void Mpeg2DataParser::PrintWordArray(const BYTE *pData, long cbSize)
{
int iter = 0;
while (iter < cbSize)
{
if (iter % 16 == 0)
verbose.showf("\t");
if (iter%2 == 0)
verbose.showf("0x");
verbose.showf(_T("%.2x"), pData[iter]);
if (iter%2 == 1)
verbose.showf(" ");
if (iter % 16 == 15)
verbose.showf("\n");
iter++;
}
if (iter % 16 != 0)
verbose.showf("\n");
}
void Mpeg2DataParser::PaddingForNumber(long number, long totalWidth)
{
long len = 0;
if (number != 0)
len = log10((double)((number > 0) ? number : -1 * number));
if (number < 0)
len++;
len++;
while ( len < totalWidth )
{
output.showf(" ");
len++;
}
}
void Mpeg2DataParser::PrintDigitalWatchChannelsIni()
{
struct service *s;
output.showf("\nNetwork_%i(\"%s\", %i, %i, 1)\n", m_networkNumber, current_tp->network_name, current_tp->frequency, current_tp->bandwidth);
int i;
if (current_tp->n_other_f > 0)
output.showf("#Alternate %s\n", ((current_tp->n_other_f > 1) ? "frequencies" : "frequency"));
for ( i=0 ; i<current_tp->n_other_f ; i++ )
{
output.showf("#Network_%i(\"%s\", %i, %i, 1)\n", m_networkNumber, current_tp->network_name, current_tp->other_f[i], current_tp->bandwidth);
}
i=1;
vector<service *>::iterator it;
for ( it = current_tp->services.begin() ; it != current_tp->services.end() ; it++ )
{
s = *it;
for (int audio = 0 ; audio <= s->audio_num ; audio++ )
{
if (((audio < s->audio_num) && (s->audio_pid[audio])) || (s->ac3_pid))
{
output.showf(" Program_");
if (i < 10) output.showf(" ");
output.showf("%i(\"%s", i, s->service_name);
int len = strlen((char *)s->service_name);
if ((audio > 0) && (audio == s->audio_num))
{
output.showf(" AC3");
len += 4;
}
output.showf("\"");
while ( len < 20 ) { output.showf(" "); len++; }
output.showf(", ");
PaddingForNumber(s->service_id, 4);
output.showf("%i, ", s->service_id);
PaddingForNumber(s->video_pid, 4);
output.showf("%i, ", s->video_pid);
if (audio < s->audio_num)
{
PaddingForNumber(s->audio_pid[audio], 5);
output.showf("%i, ", s->audio_pid[audio]);
}
else
{
PaddingForNumber(s->ac3_pid, 4);
output.showf("A%i, ", s->ac3_pid);
}
PaddingForNumber(s->pmt_pid, 4);
output.showf("%i) #", s->pmt_pid);
if (audio == 0)
{
if (s->channel_num)
output.showf(" LCN=%i", s->channel_num);
if (s->teletext_pid)
output.showf(" Teletext=%i", s->teletext_pid);
}
output.showf("\n");
i++;
}
}
}
output.showf("\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -