Skip to content

Commit 88e4dbf

Browse files
committed
Fixed an issue with not all PES data bytes being accounted for during demux.
Added a tsd_demux_end function to flush registered PID data remaining at end of demux. Added PES Packet size to tsinfo.c example.
1 parent 4239f6a commit 88e4dbf

File tree

3 files changed

+89
-23
lines changed

3 files changed

+89
-23
lines changed

examples/tsinfo.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ int main(int argc, char **charv) {
6363
}
6464
} while(count > 0);
6565

66+
// finally end the demux process which will flush any remaining PES data.
67+
tsd_demux_end(&ctx);
68+
6669
// destroy context
6770
tsd_context_destroy(&ctx);
6871

@@ -78,6 +81,8 @@ void event_cb(TSDemuxContext *ctx, uint16_t pid, TSDEventId event_id, void *data
7881
}else if(event_id == TSD_EVENT_PES) {
7982
TSDPESPacket *pes = (TSDPESPacket*) data;
8083
// This is where we would write the PES data into our buffer.
84+
printf("\n====================\n");
85+
printf("PID %d PES Packet, Size: %d\n", pid, pes->data_bytes_length);
8186
}else if(event_id == TSD_EVENT_ADAP_FIELD_PRV_DATA) {
8287
// we're only watching for SCTE Adaptions Field Private Data,
8388
// so we know that we must parse it as a list of descritors.

src/tsdemux.c

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,31 @@ TSDCode demux_descriptors(TSDemuxContext *ctx, TSDPacket *hdr)
13081308
return TSD_OK;
13091309
}
13101310

1311+
TSDCode demux_pes_flush(TSDemuxContext *ctx, int reg_idx)
1312+
{
1313+
if(ctx == NULL) return TSD_INVALID_CONTEXT;
1314+
if(reg_idx < 0) return TSD_INVALID_ARGUMENT;
1315+
1316+
TSDDataContext *dataCtx = ctx->registered_pids_data[reg_idx];
1317+
1318+
// if the buffer already has same data in it, we will parse it.
1319+
size_t data_len = dataCtx->write - dataCtx->buffer;
1320+
if(data_len > 0) {
1321+
TSDPESPacket pes;
1322+
TSDCode res = tsd_parse_pes(ctx, dataCtx->buffer, data_len, &pes);
1323+
if(res != TSD_OK) {
1324+
return res;
1325+
} else {
1326+
// call the user callback with the data.
1327+
uint16_t pid = ctx->registered_pids[reg_idx].pid;
1328+
ctx->event_cb(ctx, pid, TSD_EVENT_PES, (void *)&pes);
1329+
}
1330+
// clear the DataContext.
1331+
tsd_data_context_reset(ctx, dataCtx);
1332+
}
1333+
return TSD_OK;
1334+
}
1335+
13111336
TSDCode demux_pes(TSDemuxContext *ctx, TSDPacket *hdr, int reg_idx)
13121337
{
13131338
if(ctx == NULL) return TSD_INVALID_CONTEXT;
@@ -1320,11 +1345,25 @@ TSDCode demux_pes(TSDemuxContext *ctx, TSDPacket *hdr, int reg_idx)
13201345

13211346
const uint8_t *ptr = hdr->data_bytes;
13221347
TSDDataContext *dataCtx = ctx->registered_pids_data[reg_idx];
1348+
TSDCode initial_parse_res = TSD_OK;
13231349

13241350
size_t ptr_len = hdr->data_bytes_length;
1325-
// PES data should have the payload unit start indicator.
1326-
if(!(hdr->flags & TSD_PF_PAYLOAD_UNIT_START_IND)) {
1327-
return TSD_OK;
1351+
// is this the start of a new PES packet?
1352+
if((hdr->flags & TSD_PF_PAYLOAD_UNIT_START_IND)) {
1353+
// if the buffer already has same data in it, we will parse it.
1354+
size_t data_len = dataCtx->write - dataCtx->buffer;
1355+
if(data_len > 0) {
1356+
TSDPESPacket pes;
1357+
initial_parse_res = tsd_parse_pes(ctx, dataCtx->buffer, data_len, &pes);
1358+
if(initial_parse_res == TSD_OK) {
1359+
// call the user callback with the data.
1360+
ctx->event_cb(ctx, hdr->pid, TSD_EVENT_PES, (void *)&pes);
1361+
} else {
1362+
initial_parse_res = TSD_PARSE_ERROR;
1363+
}
1364+
// clear the DataContext for the new packet data.
1365+
tsd_data_context_reset(ctx, dataCtx);
1366+
}
13281367
}
13291368

13301369
// write the data into the DataContext.
@@ -1337,14 +1376,13 @@ TSDCode demux_pes(TSDemuxContext *ctx, TSDPacket *hdr, int reg_idx)
13371376
size_t data_len = dataCtx->write - dataCtx->buffer;
13381377
if(data_len > 5) {
13391378
// get the PES length
1340-
uint16_t pes_len = parse_u16(&dataCtx->buffer[5]) + 5;
1341-
// if the amount of data in the DataContext matches the PES length,
1379+
uint16_t pes_len = parse_u16(&dataCtx->buffer[4]);
1380+
// if the amount of data in the DataContext matches the PES length
13421381
// we have enough data to parse the PES packet.
1343-
if(data_len >= pes_len) {
1382+
if(pes_len > 0 && data_len >= pes_len) {
13441383
TSDPESPacket pes;
13451384
res = tsd_parse_pes(ctx, dataCtx->buffer, data_len, &pes);
13461385
if(res != TSD_OK) {
1347-
// bad PES data.
13481386
return TSD_PARSE_ERROR;
13491387
} else {
13501388
// call the user callback with the data.
@@ -1353,7 +1391,7 @@ TSDCode demux_pes(TSDemuxContext *ctx, TSDPacket *hdr, int reg_idx)
13531391
tsd_data_context_reset(ctx, dataCtx);
13541392
}
13551393
}
1356-
return TSD_OK;
1394+
return initial_parse_res;
13571395
}
13581396

13591397
TSDCode demux_adaptation_field_prv_data(TSDemuxContext *ctx, TSDPacket *hdr, int reg_idx)
@@ -1467,21 +1505,19 @@ size_t tsd_demux(TSDemuxContext *ctx,
14671505

14681506
// if this isn't a PMT PID, check to usee if the user has registerd it
14691507
if(parsed == 0) {
1470-
if(hdr.flags & TSD_PF_PAYLOAD_UNIT_START_IND) {
1471-
size_t i;
1472-
for(i=0; i < ctx->registered_pids_length; ++i) {
1473-
if(ctx->registered_pids[i].pid != hdr.pid) {
1474-
continue;
1475-
}
1476-
// if the user registered PES data demux the PES.
1477-
if(ctx->registered_pids[i].data_types & TSD_REG_PES) {
1478-
// demux the PES data
1479-
demux_pes(ctx, &hdr, i);
1480-
}
1481-
// if the user registered the Adaptation field data, demux that.
1482-
if(ctx->registered_pids[i].data_types & TSD_REG_ADAPTATION_FIELD) {
1483-
demux_adaptation_field_prv_data(ctx, &hdr, i);
1484-
}
1508+
size_t i;
1509+
for(i=0; i < ctx->registered_pids_length; ++i) {
1510+
if(ctx->registered_pids[i].pid != hdr.pid) {
1511+
continue;
1512+
}
1513+
// if the user registered PES data demux the PES.
1514+
if(ctx->registered_pids[i].data_types & TSD_REG_PES) {
1515+
// demux the PES data
1516+
demux_pes(ctx, &hdr, i);
1517+
}
1518+
// if the user registered the Adaptation field data, demux that.
1519+
if(ctx->registered_pids[i].data_types & TSD_REG_ADAPTATION_FIELD) {
1520+
demux_adaptation_field_prv_data(ctx, &hdr, i);
14851521
}
14861522
}
14871523
}
@@ -1503,6 +1539,17 @@ size_t tsd_demux(TSDemuxContext *ctx,
15031539
return size - remaining;
15041540
}
15051541

1542+
TSDCode tsd_demux_end(TSDemuxContext *ctx)
1543+
{
1544+
if(ctx == NULL) return TSD_INVALID_CONTEXT;
1545+
1546+
int i=0;
1547+
for(; i<ctx->registered_pids_length; ++i) {
1548+
demux_pes_flush(ctx, i);
1549+
}
1550+
return TSD_OK;
1551+
}
1552+
15061553
TSDCode tsd_register_pid(TSDemuxContext *ctx, uint16_t pid, int reg_data_type)
15071554
{
15081555
if(ctx == NULL) return TSD_INVALID_CONTEXT;

src/tsdemux.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,9 +1005,23 @@ TSDCode tsd_set_event_callback(TSDemuxContext *ctx, tsd_on_event callback);
10051005

10061006
/**
10071007
* Demux a Transport Stream.
1008+
* @param ctx The contenxt being used to demux,
1009+
* @param data The data to demux.
1010+
* @param size The size of data.
1011+
* @param code Used to store the return code of this process.
1012+
* @return The total number of bytes parsed. The process result is stored in
1013+
* code which on success will be TSD_OK;
10081014
*/
10091015
size_t tsd_demux(TSDemuxContext *ctx, void *data, size_t size, TSDCode *code);
10101016

1017+
/**
1018+
* Ends the Demuxxing process.
1019+
* Flushing any pending PES packets in the buffers.
1020+
* @param ctx The context being used to demux.
1021+
* @return TSD_OK on success.
1022+
*/
1023+
TSDCode tsd_demux_end(TSDemuxContext *ctx);
1024+
10111025
/**
10121026
* Parse Packet Header.
10131027
* Parses a TS Packet from the supplied data.

0 commit comments

Comments
 (0)