Skip to content

Commit 52b6291

Browse files
committed
for ossrs#250, decode the PAT of PSI ts packet.
1 parent 51aecb8 commit 52b6291

File tree

5 files changed

+394
-9
lines changed

5 files changed

+394
-9
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ Supported operating systems and hardware:
486486
).
487487
1. Support HLS(h.264+mp3) streaming, read
488488
[#301](https://github.com/winlinvip/simple-rtmp-server/issues/301).
489+
1. [dev] Support push MPEG-TS over UDP to SRS, read
490+
[#250](https://github.com/winlinvip/simple-rtmp-server/issues/250).
489491
1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech).
490492
1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92).
491493
1. [no-plan] Support multiple processes, for both origin and edge

trunk/src/app/srs_app_mpegts_udp.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,20 @@ using namespace std;
3535
#include <srs_kernel_ts.hpp>
3636
#include <srs_kernel_stream.hpp>
3737
#include <srs_kernel_ts.hpp>
38-
#include <srs_core_autofree.hpp>
3938

4039
#ifdef SRS_AUTO_STREAM_CASTER
4140

4241
SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
4342
{
4443
stream = new SrsStream();
44+
context = new SrsTsContext();
4545
output = _srs_config->get_stream_caster_output(c);
4646
}
4747

4848
SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
4949
{
5050
srs_freep(stream);
51+
srs_freep(context);
5152
}
5253

5354
int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
@@ -85,10 +86,7 @@ int SrsMpegtsOverUdp::on_ts_packet(SrsStream* stream)
8586
{
8687
int ret = ERROR_SUCCESS;
8788

88-
SrsTsPacket* packet = new SrsTsPacket();
89-
SrsAutoFree(SrsTsPacket, packet);
90-
91-
if ((ret = packet->decode(stream)) != ERROR_SUCCESS) {
89+
if ((ret = context->decode(stream)) != ERROR_SUCCESS) {
9290
srs_error("mpegts: decode ts packet failed. ret=%d", ret);
9391
return ret;
9492
}

trunk/src/app/srs_app_mpegts_udp.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class sockaddr_in;
3434
#include <string>
3535

3636
class SrsStream;
37+
class SrsTsContext;
3738
class SrsConfDirective;
3839

3940
#ifdef SRS_AUTO_STREAM_CASTER
@@ -45,6 +46,7 @@ class SrsMpegtsOverUdp
4546
{
4647
private:
4748
SrsStream* stream;
49+
SrsTsContext* context;
4850
std::string output;
4951
public:
5052
SrsMpegtsOverUdp(SrsConfDirective* c);

trunk/src/kernel/srs_kernel_ts.cpp

+186
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ using namespace std;
3939
#include <srs_kernel_buffer.hpp>
4040
#include <srs_kernel_utility.hpp>
4141
#include <srs_kernel_stream.hpp>
42+
#include <srs_core_autofree.hpp>
4243

4344
// in ms, for HLS aac sync time.
4445
#define SRS_CONF_DEFAULT_AAC_SYNC 100
@@ -401,6 +402,33 @@ SrsMpegtsFrame::SrsMpegtsFrame()
401402
key = false;
402403
}
403404

405+
SrsTsContext::SrsTsContext()
406+
{
407+
}
408+
409+
SrsTsContext::~SrsTsContext()
410+
{
411+
}
412+
413+
int SrsTsContext::decode(SrsStream* stream)
414+
{
415+
int ret = ERROR_SUCCESS;
416+
417+
// parse util EOF of stream.
418+
// for example, parse multiple times for the PES_packet_length(0) packet.
419+
while (!stream->empty()) {
420+
SrsTsPacket* packet = new SrsTsPacket();
421+
SrsAutoFree(SrsTsPacket, packet);
422+
423+
if ((ret = packet->decode(stream)) != ERROR_SUCCESS) {
424+
srs_error("mpegts: decode ts packet failed. ret=%d", ret);
425+
return ret;
426+
}
427+
}
428+
429+
return ret;
430+
}
431+
404432
SrsTsPacket::SrsTsPacket()
405433
{
406434
sync_byte = 0;
@@ -412,11 +440,13 @@ SrsTsPacket::SrsTsPacket()
412440
adaption_field_control = SrsTsAdaptationFieldTypeReserved;
413441
continuity_counter = 0;
414442
adaptation_field = NULL;
443+
payload = NULL;
415444
}
416445

417446
SrsTsPacket::~SrsTsPacket()
418447
{
419448
srs_freep(adaptation_field);
449+
srs_freep(payload);
420450
}
421451

422452
int SrsTsPacket::decode(SrsStream* stream)
@@ -471,6 +501,23 @@ int SrsTsPacket::decode(SrsStream* stream)
471501
// calc the user defined data size for payload.
472502
int nb_payload = SRS_TS_PACKET_SIZE - (stream->pos() - pos);
473503

504+
// optional: payload.
505+
if (adaption_field_control == SrsTsAdaptationFieldTypePayloadOnly || adaption_field_control == SrsTsAdaptationFieldTypeBoth) {
506+
if (pid == SrsTsPidPAT) {
507+
// 2.4.4.3 Program association Table
508+
srs_freep(payload);
509+
payload = new SrsTsPayloadPAT(this);
510+
} else {
511+
// left bytes as reserved.
512+
stream->skip(nb_payload);
513+
}
514+
515+
if (payload && (ret = payload->decode(stream)) != ERROR_SUCCESS) {
516+
srs_error("ts: demux payload failed. ret=%d", ret);
517+
return ret;
518+
}
519+
}
520+
474521
return ret;
475522
}
476523

@@ -713,6 +760,145 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
713760
return ret;
714761
}
715762

763+
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram()
764+
{
765+
number = 0;
766+
pid = 0;
767+
}
768+
769+
SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram()
770+
{
771+
}
772+
773+
SrsTsPayload::SrsTsPayload(SrsTsPacket* p)
774+
{
775+
packet = p;
776+
}
777+
778+
SrsTsPayload::~SrsTsPayload()
779+
{
780+
}
781+
782+
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
783+
{
784+
pointer_field = 0;
785+
}
786+
787+
SrsTsPayloadPSI::~SrsTsPayloadPSI()
788+
{
789+
}
790+
791+
int SrsTsPayloadPSI::decode(SrsStream* stream)
792+
{
793+
int ret = ERROR_SUCCESS;
794+
795+
/**
796+
* When the payload of the Transport Stream packet contains PSI data, the payload_unit_start_indicator has the following
797+
* significance: if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value
798+
* shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field. If the
799+
* Transport Stream packet does not carry the first byte of a PSI section, the payload_unit_start_indicator value shall be '0',
800+
* indicating that there is no pointer_field in the payload. Refer to 2.4.4.1 and 2.4.4.2. This also applies to private streams of
801+
* stream_type 5 (refer to Table 2-29).
802+
*/
803+
if (packet->payload_unit_start_indicator) {
804+
if (!stream->require(1)) {
805+
ret = ERROR_STREAM_CASTER_TS_AF;
806+
srs_error("ts: demux PSI failed. ret=%d", ret);
807+
return ret;
808+
}
809+
pointer_field = stream->read_1bytes();
810+
}
811+
812+
return ret;
813+
}
814+
815+
SrsTsPayloadPAT::SrsTsPayloadPAT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
816+
{
817+
nb_programs = 0;
818+
programs = NULL;
819+
}
820+
821+
SrsTsPayloadPAT::~SrsTsPayloadPAT()
822+
{
823+
srs_freep(programs);
824+
}
825+
826+
int SrsTsPayloadPAT::decode(SrsStream* stream)
827+
{
828+
int ret = ERROR_SUCCESS;
829+
830+
if ((ret = SrsTsPayloadPSI::decode(stream)) != ERROR_SUCCESS) {
831+
return ret;
832+
}
833+
834+
// atleast 8B without programs and crc32
835+
if (!stream->require(8)) {
836+
ret = ERROR_STREAM_CASTER_TS_AF;
837+
srs_error("ts: demux PAT failed. ret=%d", ret);
838+
return ret;
839+
}
840+
// 1B
841+
table_id = (SrsTsPsiId)stream->read_1bytes();
842+
843+
// 2B
844+
section_length = stream->read_2bytes();
845+
846+
section_syntax_indicator = (section_length >> 15) & 0x01;
847+
const0_value = (section_length >> 14) & 0x01;
848+
section_length &= 0x0FFF;
849+
850+
if (!stream->require(section_length)) {
851+
ret = ERROR_STREAM_CASTER_TS_AF;
852+
srs_error("ts: demux PAT section failed. ret=%d", ret);
853+
return ret;
854+
}
855+
int pos = stream->pos();
856+
857+
// 2B
858+
transport_stream_id = stream->read_2bytes();
859+
860+
// 1B
861+
current_next_indicator = stream->read_1bytes();
862+
863+
version_number = (current_next_indicator >> 1) & 0x1F;
864+
current_next_indicator &= 0x01;
865+
866+
// TODO: FIXME: check the indicator.
867+
868+
// 1B
869+
section_number = stream->read_1bytes();
870+
// 1B
871+
last_section_number = stream->read_1bytes();
872+
873+
// multiple 4B program data.
874+
int program_bytes = section_length - 4 - (stream->pos() - pos);
875+
nb_programs = program_bytes / 4;
876+
if (nb_programs > 0) {
877+
srs_freep(programs);
878+
programs = new SrsTsPayloadPATProgram[nb_programs];
879+
880+
for (int i = 0; i < nb_programs; i++) {
881+
SrsTsPayloadPATProgram* program = programs + i;
882+
883+
int tmpv = stream->read_4bytes();
884+
program->number = (int16_t)((tmpv >> 16) & 0xFFFF);
885+
program->pid = (int16_t)(tmpv & 0x1FFF);
886+
}
887+
}
888+
889+
// 4B
890+
if (!stream->require(4)) {
891+
ret = ERROR_STREAM_CASTER_TS_AF;
892+
srs_error("ts: demux PAT crc32 failed. ret=%d", ret);
893+
return ret;
894+
}
895+
CRC_32 = stream->read_4bytes();
896+
897+
// TODO: FIXME: verfy crc32.
898+
899+
return ret;
900+
}
901+
716902
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)
717903
{
718904
writer = w;

0 commit comments

Comments
 (0)