[Bug?] Invalid transport_descriptors_length field calculation in NIT generator
Michael Umansky <[email protected]> Wed, 10 Sep 2014 11:33:45 +0300
| Newsgroups | gmane.comp.video.videolan.libdvbpsi.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello, The calculation of the transport_descriptors_length field in NIT has one extra byte than it should. I am attaching the test file used to create an NIT containing one program. Using libdvbpsi-1.2.0. Here is the hex dump of the output file, I have bolded the invalid byte. % hd out.ts 00000000 47 40 10 10 00 40 b0 13 05 39 c3 00 00 f0 00 f0 |G@[email protected]......| 00000010 06 02 9a 05 39 f0 *01*5f b2 83 b6 ff ff ff ff ff |....9.._........| 00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * 000000bc It should be 0x00 as there are no descriptors attached. EN 300 468 V1.13.1 explicitly states: transport_descriptors_length: This is a 12-bit field specifying the total length in bytes of the TS descriptors /that follow/. (emphasis mine) Curiously enough, if you create a dummy NIT containing no programs, the highlighted byte is correctly set to 0x00. For your consideration. Thanks, Michael _______________________________________________ libdvbpsi-devel mailing list [email protected] https://mailman.videolan.org/listinfo/libdvbpsi-devel
test.c
(text/x-csrc, 2.6 KB)
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "path/to/libdvbpsi/config.h"
#include <dvbpsi/dvbpsi.h>
#include <dvbpsi/psi.h>
#include <dvbpsi/descriptor.h>
#include <dvbpsi/nit.h>
static void message(dvbpsi_t *handle, const dvbpsi_msg_level_t level, const char *msg) {
switch(level) {
case DVBPSI_MSG_ERROR:
fprintf(stderr, "%s", msg);
break;
case DVBPSI_MSG_WARN:
fprintf(stderr, "%s", msg);
break;
case DVBPSI_MSG_DEBUG:
fprintf(stdout, "%s", msg);
break;
default:
return;
}
}
static void write_psi(dvbpsi_psi_section_t *section, const uint16_t pid, uint8_t *packet, FILE *fp) {
packet[0] = 0x47;
while (section) {
size_t bytes_written = 0;
uint8_t *position_in_ts;
uint8_t *byte = section->p_data;
uint8_t *end = section->p_payload_end + (section->b_syntax_indicator ? 4 : 0);
packet[1] |= 0x40 | (pid >> 8);
packet[2] = pid & 0xFF;
packet[3] = (packet[3] & 0x0F) | 0x10;
packet[4] = 0x00;
position_in_ts = packet + 5;
while (position_in_ts < packet + 188 && byte < end)
*(position_in_ts++) = *(byte++);
while (position_in_ts < packet + 188)
*(position_in_ts++) = 0xFF;
bytes_written = fwrite(packet, 188, 1, fp);
if (bytes_written == 0)
return;
packet[3] = (packet[3] + 1) & 0x0F;
while (byte < end) {
packet[1] &= 0xBF;
packet[3] = (packet[3] & 0x0F) | 0x10;
position_in_ts = packet + 4;
while (position_in_ts < packet + 188 && byte < end)
*(position_in_ts++) = *(byte++);
while (position_in_ts < packet + 188)
*(position_in_ts++) = 0xFF;
bytes_written = fwrite(packet, 188, 1, fp);
if (bytes_written == 0)
return;
packet[3] = (packet[3] + 1) & 0x0F;
}
section = section->p_next;
}
}
int main(void) {
FILE *fp;
uint8_t packet[188] = { 0 };
dvbpsi_t *dvbpsi = dvbpsi_new(&message, DVBPSI_MSG_DEBUG);
dvbpsi_nit_t *nit = dvbpsi_nit_new(0x40, 666, 1337, 1, true);
dvbpsi_psi_section_t *sections = NULL;
dvbpsi_nit_ts_add(nit, 666, 1337);
fp = fopen("out.ts", "wb");
if (fp == NULL)
goto out;
sections = dvbpsi_nit_sections_generate(dvbpsi, nit, 0x40);
write_psi(sections, 0x10, packet, fp);
fclose(fp);
out:
dvbpsi_nit_delete(nit);
dvbpsi_DeletePSISections(sections);
dvbpsi_delete(dvbpsi);
return 0;
}