diff --git a/README.md b/README.md
index a2e0ec544..6aef9bece 100755
--- a/README.md
+++ b/README.md
@@ -67,7 +67,7 @@ cd simple-rtmp-server/trunk
[Usage: How to deploy low lantency application?](https://github.com/winlinvip/simple-rtmp-server/wiki/SampleRealtime)
[Usage: How to deploy srs on ARM?](https://github.com/winlinvip/simple-rtmp-server/wiki/SampleARM)
[Usage: How to show the demo of SRS?](https://github.com/winlinvip/simple-rtmp-server/wiki/SampleDemo)
-[Usage: Who is using SRS?](https://github.com/winlinvip/simple-rtmp-server/wiki/Sample)
+[Usage: Solution using SRS?](https://github.com/winlinvip/simple-rtmp-server/wiki/Sample)
### System Requirements
Supported operating systems and hardware:
diff --git a/trunk/research/hls/ts_info.cc b/trunk/research/hls/ts_info.cc
index c29a23e42..9c775abc7 100644
--- a/trunk/research/hls/ts_info.cc
+++ b/trunk/research/hls/ts_info.cc
@@ -80,14 +80,14 @@ Annex A CRC Decoder Model
enum TSPidTable
{
- // Program Association Table(see Table 2-25).
- TSPidTablePAT = 0x00,
- // Conditional Access Table (see Table 2-27).
- TSPidTableCAT = 0x01,
- // Transport Stream Description Table
- TSPidTableTSDT = 0x02,
- // null packets (see Table 2-3)
- TSPidTableNULL = 0x01FFF,
+ // Program Association Table(see Table 2-25).
+ TSPidTablePAT = 0x00,
+ // Conditional Access Table (see Table 2-27).
+ TSPidTableCAT = 0x01,
+ // Transport Stream Description Table
+ TSPidTableTSDT = 0x02,
+ // null packets (see Table 2-3)
+ TSPidTableNULL = 0x01FFF,
};
/*adaptation_field_control*/
@@ -96,34 +96,34 @@ enum TSPidTable
*/
enum TSAdaptionType
{
- // Reserved for future use by ISO/IEC
- TSAdaptionTypeReserved = 0x00,
- // No adaptation_field, payload only
- TSAdaptionTypePayloadOnly = 0x01,
- // Adaptation_field only, no payload
- TSAdaptionTypeAdaptionOnly = 0x02,
- // Adaptation_field followed by payload
- TSAdaptionTypeBoth = 0x03,
+ // Reserved for future use by ISO/IEC
+ TSAdaptionTypeReserved = 0x00,
+ // No adaptation_field, payload only
+ TSAdaptionTypePayloadOnly = 0x01,
+ // Adaptation_field only, no payload
+ TSAdaptionTypeAdaptionOnly = 0x02,
+ // Adaptation_field followed by payload
+ TSAdaptionTypeBoth = 0x03,
};
#endif
// Table 2-29 – Stream type assignments. page 66.
enum TSStreamType
{
- // ITU-T | ISO/IEC Reserved
- TSStreamTypeReserved = 0x00,
- /*defined by ffmpeg*/
- TSStreamTypeVideoMpeg1 = 0x01,
- TSStreamTypeVideoMpeg2 = 0x02,
- TSStreamTypeAudioMpeg1 = 0x03,
- TSStreamTypeAudioMpeg2 = 0x04,
- TSStreamTypePrivateSection = 0x05,
- TSStreamTypePrivateData = 0x06,
- TSStreamTypeAudioAAC = 0x0f,
- TSStreamTypeVideoMpeg4 = 0x10,
- TSStreamTypeVideoH264 = 0x1b,
- TSStreamTypeAudioAC3 = 0x81,
- TSStreamTypeAudioDTS = 0x8a,
+ // ITU-T | ISO/IEC Reserved
+ TSStreamTypeReserved = 0x00,
+ /*defined by ffmpeg*/
+ TSStreamTypeVideoMpeg1 = 0x01,
+ TSStreamTypeVideoMpeg2 = 0x02,
+ TSStreamTypeAudioMpeg1 = 0x03,
+ TSStreamTypeAudioMpeg2 = 0x04,
+ TSStreamTypePrivateSection = 0x05,
+ TSStreamTypePrivateData = 0x06,
+ TSStreamTypeAudioAAC = 0x0f,
+ TSStreamTypeVideoMpeg4 = 0x10,
+ TSStreamTypeVideoH264 = 0x1b,
+ TSStreamTypeAudioAC3 = 0x81,
+ TSStreamTypeAudioDTS = 0x8a,
};
/**
@@ -155,7 +155,7 @@ class TSMessage;
class TSPacket
{
public:
- TSHeader* header;
+ TSHeader* header;
TSAdaptionField* adaption_field;
TSPayload* payload;
@@ -272,7 +272,7 @@ public:
int size;
int pointer_field_size;
- TSPidType type;
+ TSPidType type;
/**
* 2.4.4.2 Semantics definition of fields in pointer syntax
@@ -417,38 +417,38 @@ public:
*/
enum TSPESStreamId
{
- PES_program_stream_map = 0xbc, // 0b10111100
- PES_private_stream_1 = 0xbd, // 0b10111101
- PES_padding_stream = 0xbe, // 0b10111110
- PES_private_stream_2 = 0xbf, // 0b10111111
-
- // 110x xxxx
- // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC
- // 14496-3 audio stream number x xxxx
- // (stream_id>>5)&0x07 == PES_audio_prefix
- PES_audio_prefix = 0x06, // 0b110
-
- // 1110 xxxx
- // ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC
- // 14496-2 video stream number xxxx
- // (stream_id>>4)&0x0f == PES_audio_prefix
- PES_video_prefix = 0x0e, // 0b1110
-
- PES_ECM_stream = 0xf0, // 0b11110000
- PES_EMM_stream = 0xf1, // 0b11110001
- PES_DSMCC_stream = 0xf2, // 0b11110010
- PES_13522_stream = 0xf3, // 0b11110011
- PES_H_222_1_type_A = 0xf4, // 0b11110100
- PES_H_222_1_type_B = 0xf5, // 0b11110101
- PES_H_222_1_type_C = 0xf6, // 0b11110110
- PES_H_222_1_type_D = 0xf7, // 0b11110111
- PES_H_222_1_type_E = 0xf8, // 0b11111000
- PES_ancillary_stream = 0xf9, // 0b11111001
- PES_SL_packetized_stream = 0xfa, // 0b11111010
- PES_FlexMux_stream = 0xfb, // 0b11111011
- // reserved data stream
- // 1111 1100 … 1111 1110
- PES_program_stream_directory= 0xff, // 0b11111111
+ PES_program_stream_map = 0xbc, // 0b10111100
+ PES_private_stream_1 = 0xbd, // 0b10111101
+ PES_padding_stream = 0xbe, // 0b10111110
+ PES_private_stream_2 = 0xbf, // 0b10111111
+
+ // 110x xxxx
+ // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC
+ // 14496-3 audio stream number x xxxx
+ // (stream_id>>5)&0x07 == PES_audio_prefix
+ PES_audio_prefix = 0x06, // 0b110
+
+ // 1110 xxxx
+ // ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC
+ // 14496-2 video stream number xxxx
+ // (stream_id>>4)&0x0f == PES_audio_prefix
+ PES_video_prefix = 0x0e, // 0b1110
+
+ PES_ECM_stream = 0xf0, // 0b11110000
+ PES_EMM_stream = 0xf1, // 0b11110001
+ PES_DSMCC_stream = 0xf2, // 0b11110010
+ PES_13522_stream = 0xf3, // 0b11110011
+ PES_H_222_1_type_A = 0xf4, // 0b11110100
+ PES_H_222_1_type_B = 0xf5, // 0b11110101
+ PES_H_222_1_type_C = 0xf6, // 0b11110110
+ PES_H_222_1_type_D = 0xf7, // 0b11110111
+ PES_H_222_1_type_E = 0xf8, // 0b11111000
+ PES_ancillary_stream = 0xf9, // 0b11111001
+ PES_SL_packetized_stream = 0xfa, // 0b11111010
+ PES_FlexMux_stream = 0xfb, // 0b11111011
+ // reserved data stream
+ // 1111 1100 … 1111 1110
+ PES_program_stream_directory= 0xff, // 0b11111111
};
@@ -465,64 +465,64 @@ public:
// 2B
u_int16_t PES_packet_length; //16bits
- // 1B
- // 2bits const '10'
- int8_t PES_scrambling_control; //2bits
- int8_t PES_priority; //1bit
- int8_t data_alignment_indicator; //1bit
- int8_t copyright; //1bit
- int8_t original_or_copy; //1bit
-
- // 1B
- int8_t PTS_DTS_flags; //2bits
- int8_t ESCR_flag; //1bit
- int8_t ES_rate_flag; //1bit
- int8_t DSM_trick_mode_flag; //1bit
- int8_t additional_copy_info_flag; //1bit
- int8_t PES_CRC_flag; //1bit
- int8_t PES_extension_flag; //1bit
-
- // 1B
- u_int8_t PES_header_data_length; //8bits
-
- int64_t pts; // 33bits
- int64_t dts; // 33bits
-
- int16_t ESCR_extension; //9bits
- int64_t ESCR_base; //33bits
- int32_t ES_rate; //22bits
-
- int8_t trick_mode_control; //3bits
- int8_t trick_mode_value; //5bits
-
- int8_t additional_copy_info; //7bits
- int16_t previous_PES_packet_CRC; //16bits
-
- int8_t PES_private_data_flag; //1bit
- int8_t pack_header_field_flag; //1bit
- int8_t program_packet_sequence_counter_flag; //1bit
- int8_t P_STD_buffer_flag; //1bit
- // reserved 3bits
- int8_t PES_extension_flag_2; //1bit
-
- // 16B
- char* PES_private_data; //128bits
-
- int8_t pack_field_length; //8bits
- char* pack_field; //[pack_field_length] bytes
-
- int8_t program_packet_sequence_counter; //7bits
- int8_t MPEG1_MPEG2_identifier; //1bit
- int8_t original_stuff_length; //6bits
-
- int8_t P_STD_buffer_scale; //1bit
- int16_t P_STD_buffer_size; //13bits
-
- int8_t PES_extension_field_length; //7bits
- char* PES_extension_field; //[PES_extension_field_length] bytes
-
- int stuffing_size;
- char* stuffing_byte;
+ // 1B
+ // 2bits const '10'
+ int8_t PES_scrambling_control; //2bits
+ int8_t PES_priority; //1bit
+ int8_t data_alignment_indicator; //1bit
+ int8_t copyright; //1bit
+ int8_t original_or_copy; //1bit
+
+ // 1B
+ int8_t PTS_DTS_flags; //2bits
+ int8_t ESCR_flag; //1bit
+ int8_t ES_rate_flag; //1bit
+ int8_t DSM_trick_mode_flag; //1bit
+ int8_t additional_copy_info_flag; //1bit
+ int8_t PES_CRC_flag; //1bit
+ int8_t PES_extension_flag; //1bit
+
+ // 1B
+ u_int8_t PES_header_data_length; //8bits
+
+ int64_t pts; // 33bits
+ int64_t dts; // 33bits
+
+ int16_t ESCR_extension; //9bits
+ int64_t ESCR_base; //33bits
+ int32_t ES_rate; //22bits
+
+ int8_t trick_mode_control; //3bits
+ int8_t trick_mode_value; //5bits
+
+ int8_t additional_copy_info; //7bits
+ int16_t previous_PES_packet_CRC; //16bits
+
+ int8_t PES_private_data_flag; //1bit
+ int8_t pack_header_field_flag; //1bit
+ int8_t program_packet_sequence_counter_flag; //1bit
+ int8_t P_STD_buffer_flag; //1bit
+ // reserved 3bits
+ int8_t PES_extension_flag_2; //1bit
+
+ // 16B
+ char* PES_private_data; //128bits
+
+ int8_t pack_field_length; //8bits
+ char* pack_field; //[pack_field_length] bytes
+
+ int8_t program_packet_sequence_counter; //7bits
+ int8_t MPEG1_MPEG2_identifier; //1bit
+ int8_t original_stuff_length; //6bits
+
+ int8_t P_STD_buffer_scale; //1bit
+ int16_t P_STD_buffer_size; //13bits
+
+ int8_t PES_extension_field_length; //7bits
+ char* PES_extension_field; //[PES_extension_field_length] bytes
+
+ int stuffing_size;
+ char* stuffing_byte;
TSPayloadPES();
virtual ~TSPayloadPES();
@@ -547,13 +547,13 @@ public:
*/
struct TSPid
{
- TSPidType type;
- // page 66.
- TSStreamType stream_type;
- // page 36
- TSPidTable pid;
- // page 36
- u_int8_t continuity_counter;
+ TSPidType type;
+ // page 66.
+ TSStreamType stream_type;
+ // page 36
+ TSPidTable pid;
+ // page 36
+ u_int8_t continuity_counter;
};
/**
@@ -562,29 +562,29 @@ struct TSPid
class TSMessage
{
public:
- // 2.4.3.2 Transport Stream packet layer. page 36
- // the pid of PES packet.
- TSPidTable pid;
-
- // the type of pid.
- TSPidType type;
- // the type of stream, codec type.
- TSStreamType stream_type;
- // page 36
- u_int8_t continuity_counter;
-
- // 2.4.3.7 Semantic definition of fields in PES packet. page 49
- // PES packet header size plus data size.
+ // 2.4.3.2 Transport Stream packet layer. page 36
+ // the pid of PES packet.
+ TSPidTable pid;
+
+ // the type of pid.
+ TSPidType type;
+ // the type of stream, codec type.
+ TSStreamType stream_type;
+ // page 36
+ u_int8_t continuity_counter;
+
+ // 2.4.3.7 Semantic definition of fields in PES packet. page 49
+ // PES packet header size plus data size.
u_int16_t PES_packet_length; //16bits
- // the stream id.
- u_int8_t stream_id;
-
- // 2.4.3.7 Semantic definition of fields in PES packet. page 49.
- int32_t packet_start_code_prefix;
-
- int64_t pts; // 33bits
- int64_t dts; // 33bits
+ // the stream id.
+ u_int8_t stream_id;
+
+ // 2.4.3.7 Semantic definition of fields in PES packet. page 49.
+ int32_t packet_start_code_prefix;
+
+ int64_t pts; // 33bits
+ int64_t dts; // 33bits
int64_t pcr;
// header size.
@@ -594,20 +594,20 @@ public:
int parsed_packet_size;
// total packet size.
- int packet_data_size;
- char* packet_data;
-
- // for avc.
- u_int8_t nal_ref_idc;
- u_int8_t nal_unit_type;
-
- TSMessage();
- virtual ~TSMessage();
-
- void append(u_int8_t*& p, int size);
- void detach(TSContext* ctx, TSMessage*& pmsg);
-
- bool is_video();
+ int packet_data_size;
+ char* packet_data;
+
+ // for avc.
+ u_int8_t nal_ref_idc;
+ u_int8_t nal_unit_type;
+
+ TSMessage();
+ virtual ~TSMessage();
+
+ void append(u_int8_t*& p, int size);
+ void detach(TSContext* ctx, TSMessage*& pmsg);
+
+ bool is_video();
};
// ts context
@@ -618,9 +618,9 @@ public:
* consumed pids.
*/
int pid_size;
- TSPid* pids;
- int64_t ts_packet_count;
- std::map msgs;
+ TSPid* pids;
+ int64_t ts_packet_count;
+ std::map msgs;
TSContext();
virtual ~TSContext();
@@ -675,17 +675,17 @@ TSPid* TSContext::get(TSPidTable pid)
void TSContext::push(TSPidTable pid, TSStreamType stream_type, TSPidType type, u_int8_t continuity_counter)
{
- TSPid* p = get(pid);
-
+ TSPid* p = get(pid);
+
if (!p) {
p = new TSPid[pid_size + 1];
- memcpy(p, pids, sizeof(TSPid) * pid_size);
-
- p[pid_size] = (TSPid){type, stream_type, pid, continuity_counter};
- pid_size++;
-
- srs_freepa(pids);
- pids = p;
+ memcpy(p, pids, sizeof(TSPid) * pid_size);
+
+ p[pid_size] = (TSPid){type, stream_type, pid, continuity_counter};
+ pid_size++;
+
+ srs_freepa(pids);
+ pids = p;
}
p->continuity_counter = continuity_counter;
@@ -693,73 +693,73 @@ void TSContext::push(TSPidTable pid, TSStreamType stream_type, TSPidType type, u
TSMessage* TSContext::get_msg(TSPidTable pid)
{
- if (msgs[pid] == NULL) {
- TSMessage* msg = new TSMessage();
- msg->pid = pid;
- msgs[pid] = msg;
- }
-
- return msgs[pid];
+ if (msgs[pid] == NULL) {
+ TSMessage* msg = new TSMessage();
+ msg->pid = pid;
+ msgs[pid] = msg;
+ }
+
+ return msgs[pid];
}
void TSContext::detach(TSMessage* msg)
{
- msgs[msg->pid] = NULL;
+ msgs[msg->pid] = NULL;
}
TSMessage::TSMessage()
{
- pid = TSPidTablePAT;
- type = TSPidTypeReserved;
- stream_type = TSStreamTypeReserved;
- stream_id = 0;
- packet_start_code_prefix = 0;
- pts = dts = pcr = 0;
- PES_packet_length = 0;
- packet_header_size = 0;
- parsed_packet_size = 0;
- packet_data_size = 0;
- packet_data = NULL;
-
- nal_ref_idc = 0;
- nal_unit_type = 0;
+ pid = TSPidTablePAT;
+ type = TSPidTypeReserved;
+ stream_type = TSStreamTypeReserved;
+ stream_id = 0;
+ packet_start_code_prefix = 0;
+ pts = dts = pcr = 0;
+ PES_packet_length = 0;
+ packet_header_size = 0;
+ parsed_packet_size = 0;
+ packet_data_size = 0;
+ packet_data = NULL;
+
+ nal_ref_idc = 0;
+ nal_unit_type = 0;
}
TSMessage::~TSMessage()
{
- srs_freepa(packet_data);
+ srs_freepa(packet_data);
}
void TSMessage::append(u_int8_t*& p, int size)
{
- if (size <= 0) {
- return;
- }
-
- // for PES_packet_length is 0, the size is varient.
- if (packet_data_size - parsed_packet_size < size) {
- int realloc_size = size - (packet_data_size - parsed_packet_size);
- packet_data = (char*)realloc(packet_data, packet_data_size + realloc_size);
-
- packet_data_size += realloc_size;
- }
-
- memcpy(packet_data + parsed_packet_size, p, size);
- p += size;
- parsed_packet_size += size;
+ if (size <= 0) {
+ return;
+ }
+
+ // for PES_packet_length is 0, the size is varient.
+ if (packet_data_size - parsed_packet_size < size) {
+ int realloc_size = size - (packet_data_size - parsed_packet_size);
+ packet_data = (char*)realloc(packet_data, packet_data_size + realloc_size);
+
+ packet_data_size += realloc_size;
+ }
+
+ memcpy(packet_data + parsed_packet_size, p, size);
+ p += size;
+ parsed_packet_size += size;
}
void TSMessage::detach(TSContext* ctx, TSMessage*& pmsg)
{
- if (parsed_packet_size >= packet_data_size) {
- ctx->detach(this);
- pmsg = this;
- }
+ if (parsed_packet_size >= packet_data_size) {
+ ctx->detach(this);
+ pmsg = this;
+ }
}
bool TSMessage::is_video()
{
- return type == TSPidTypeVideo;
+ return type == TSPidTypeVideo;
}
TSAdaptionField::TSAdaptionField()
@@ -1064,12 +1064,12 @@ TSPMTESInfo::TSPMTESInfo()
stream_type = 0;
elementary_PID = 0;
ES_info_length = 0;
- ES_info = NULL;
+ ES_info = NULL;
}
TSPMTESInfo::~TSPMTESInfo()
{
- srs_freepa(ES_info);
+ srs_freepa(ES_info);
}
TSPayloadPMT::TSPayloadPMT()
@@ -1091,18 +1091,18 @@ TSPayloadPMT::TSPayloadPMT()
TSPayloadPMT::~TSPayloadPMT()
{
- srs_freepa(program_info_desc);
-
- for (std::vector::iterator it = ES_info.begin(); it != ES_info.end(); ++it) {
- TSPMTESInfo* info = *it;
- srs_freep(info);
- }
- ES_info.clear();
+ srs_freepa(program_info_desc);
+
+ for (std::vector::iterator it = ES_info.begin(); it != ES_info.end(); ++it) {
+ TSPMTESInfo* info = *it;
+ srs_freep(info);
+ }
+ ES_info.clear();
}
TSPMTESInfo* TSPayloadPMT::at(int index)
{
- return ES_info.at(index);
+ return ES_info.at(index);
}
int TSPayloadPMT::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* last, u_int8_t*& p, TSMessage*& pmsg)
@@ -1144,55 +1144,55 @@ int TSPayloadPMT::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t
program_info_length &= 0xFFF;
if (program_info_length > 0) {
- program_info_desc = new char[program_info_length];
- memcpy(program_info_desc, p, program_info_length);
- p += program_info_length;
+ program_info_desc = new char[program_info_length];
+ memcpy(program_info_desc, p, program_info_length);
+ p += program_info_length;
}
// [section_length] - 4(CRC) - 9B - [program_info_length]
int ES_bytes = section_length - 4 - 9 - program_info_length;
while (ES_bytes > 0) {
- TSPMTESInfo* info = new TSPMTESInfo();
-
- info->stream_type = *p++;
- ES_bytes--;
-
- pp = (char*)&info->elementary_PID;
- pp[1] = *p++;
- pp[0] = *p++;
- ES_bytes -= 2;
-
- info->elementary_PID &= 0x1FFF;
-
- pp = (char*)&info->ES_info_length;
- pp[1] = *p++;
- pp[0] = *p++;
- ES_bytes -= 2;
-
- info->ES_info_length &= 0x0FFF;
-
- if (info->ES_info_length > 0) {
- info->ES_info = new char[info->ES_info_length];
- memcpy(info->ES_info, p, info->ES_info_length);
-
- p += info->ES_info_length;
- ES_bytes -= info->ES_info_length;
- }
-
- ES_info.push_back(info);
-
- if (info->stream_type == TSStreamTypeVideoH264) {
- // TODO: support more video type.
- ctx->push((TSPidTable)info->elementary_PID, (TSStreamType)info->stream_type, TSPidTypeVideo, pkt->header->continuity_counter);
- trace("ts+pmt add pid: %d, type: H264 video", info->elementary_PID);
- } else if (info->stream_type == TSStreamTypeAudioAAC) {
- // TODO: support more audio type.
- // see aac: 6.2 Audio Data Transport Stream, ADTS
- ctx->push((TSPidTable)info->elementary_PID, (TSStreamType)info->stream_type, TSPidTypeAudio, pkt->header->continuity_counter);
- trace("ts+pmt add pid: %d, type: AAC audio", info->elementary_PID);
- } else {
- trace("ts+pmt ignore the stream type: %d", info->stream_type);
- }
+ TSPMTESInfo* info = new TSPMTESInfo();
+
+ info->stream_type = *p++;
+ ES_bytes--;
+
+ pp = (char*)&info->elementary_PID;
+ pp[1] = *p++;
+ pp[0] = *p++;
+ ES_bytes -= 2;
+
+ info->elementary_PID &= 0x1FFF;
+
+ pp = (char*)&info->ES_info_length;
+ pp[1] = *p++;
+ pp[0] = *p++;
+ ES_bytes -= 2;
+
+ info->ES_info_length &= 0x0FFF;
+
+ if (info->ES_info_length > 0) {
+ info->ES_info = new char[info->ES_info_length];
+ memcpy(info->ES_info, p, info->ES_info_length);
+
+ p += info->ES_info_length;
+ ES_bytes -= info->ES_info_length;
+ }
+
+ ES_info.push_back(info);
+
+ if (info->stream_type == TSStreamTypeVideoH264) {
+ // TODO: support more video type.
+ ctx->push((TSPidTable)info->elementary_PID, (TSStreamType)info->stream_type, TSPidTypeVideo, pkt->header->continuity_counter);
+ trace("ts+pmt add pid: %d, type: H264 video", info->elementary_PID);
+ } else if (info->stream_type == TSStreamTypeAudioAAC) {
+ // TODO: support more audio type.
+ // see aac: 6.2 Audio Data Transport Stream, ADTS
+ ctx->push((TSPidTable)info->elementary_PID, (TSStreamType)info->stream_type, TSPidTypeAudio, pkt->header->continuity_counter);
+ trace("ts+pmt add pid: %d, type: AAC audio", info->elementary_PID);
+ } else {
+ trace("ts+pmt ignore the stream type: %d", info->stream_type);
+ }
}
pp = (char*)&CRC_32;
@@ -1252,44 +1252,44 @@ TSPayloadPES::TSPayloadPES()
TSPayloadPES::~TSPayloadPES()
{
- srs_freepa(PES_private_data);
- srs_freepa(pack_field);
- srs_freepa(PES_extension_field);
- srs_freepa(stuffing_byte);
+ srs_freepa(PES_private_data);
+ srs_freepa(pack_field);
+ srs_freepa(PES_extension_field);
+ srs_freepa(stuffing_byte);
}
int64_t TSPayloadPES::decode_33bits_int(u_int8_t*& p, int64_t& temp)
{
- char* pp = (char*)&temp;
- pp[4] = *p++;
- pp[3] = *p++;
- pp[2] = *p++;
- pp[1] = *p++;
- pp[0] = *p++;
-
- return decode_33bits_int(temp);
+ char* pp = (char*)&temp;
+ pp[4] = *p++;
+ pp[3] = *p++;
+ pp[2] = *p++;
+ pp[1] = *p++;
+ pp[0] = *p++;
+
+ return decode_33bits_int(temp);
}
int64_t TSPayloadPES::decode_33bits_int(int64_t& temp)
{
int64_t ret = 0;
-
- // marker_bit 1bit
- temp = temp >> 1;
- // PTS [14..0] 15bits
- ret |= temp & 0x7fff;
- // marker_bit 1bit
- temp = temp >> 1;
- // PTS [29..15] 15bits, 15zero, 29-15+1one
- ret |= temp & 0x3fff8000LL;
- // marker_bit 1bit
- temp = temp >> 1;
- // PTS [32..30] 3bits
- ret |= temp & 0x1c0000000LL;
-
- temp = temp >> 33;
-
- return ret;
+
+ // marker_bit 1bit
+ temp = temp >> 1;
+ // PTS [14..0] 15bits
+ ret |= temp & 0x7fff;
+ // marker_bit 1bit
+ temp = temp >> 1;
+ // PTS [29..15] 15bits, 15zero, 29-15+1one
+ ret |= temp & 0x3fff8000LL;
+ // marker_bit 1bit
+ temp = temp >> 1;
+ // PTS [32..30] 3bits
+ ret |= temp & 0x1c0000000LL;
+
+ temp = temp >> 33;
+
+ return ret;
}
int TSPayloadPES::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* last, u_int8_t*& p, TSMessage*& pmsg)
@@ -1302,249 +1302,249 @@ int TSPayloadPES::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t
pp[0] = *p++;
packet_start_code_prefix &= 0xFFFFFF;
- if (packet_start_code_prefix != 0x01) {
- trace("ts+pes decode unit start packet error, msg is empty.");
- return -1;
- }
+ if (packet_start_code_prefix != 0x01) {
+ trace("ts+pes decode unit start packet error, msg is empty.");
+ return -1;
+ }
- stream_id = *p++;
-
- pp = (char*)&PES_packet_length;
- pp[1] = *p++;
- pp[0] = *p++;
- u_int8_t* pos_packet = p;
-
- if (stream_id != PES_program_stream_map
- && stream_id != PES_padding_stream
- && stream_id != PES_private_stream_2
- && stream_id != PES_ECM_stream
- && stream_id != PES_EMM_stream
- && stream_id != PES_program_stream_directory
- && stream_id != PES_DSMCC_stream
- && stream_id != PES_H_222_1_type_E
- ) {
- original_or_copy = *p++;
-
- //int8_t const2bits = (original_or_copy >> 6) & 0x03;
- PES_scrambling_control = (original_or_copy >> 4) & 0x03;
- PES_priority = (original_or_copy >> 3) & 0x01;
- data_alignment_indicator = (original_or_copy >> 2) & 0x01;
- copyright = (original_or_copy >> 1) & 0x01;
- original_or_copy &= 0x01;
-
- PES_extension_flag = *p++;
-
- PTS_DTS_flags = (PES_extension_flag >> 6) & 0x03;
- ESCR_flag = (PES_extension_flag >> 5) & 0x01;
- ES_rate_flag = (PES_extension_flag >> 4) & 0x01;
- DSM_trick_mode_flag = (PES_extension_flag >> 3) & 0x01;
- additional_copy_info_flag = (PES_extension_flag >> 2) & 0x01;
- PES_CRC_flag = (PES_extension_flag >> 1) & 0x01;
- PES_extension_flag &= 0x01;
-
- PES_header_data_length = *p++;
- u_int8_t* pos_header = p;
+ stream_id = *p++;
+
+ pp = (char*)&PES_packet_length;
+ pp[1] = *p++;
+ pp[0] = *p++;
+ u_int8_t* pos_packet = p;
+
+ if (stream_id != PES_program_stream_map
+ && stream_id != PES_padding_stream
+ && stream_id != PES_private_stream_2
+ && stream_id != PES_ECM_stream
+ && stream_id != PES_EMM_stream
+ && stream_id != PES_program_stream_directory
+ && stream_id != PES_DSMCC_stream
+ && stream_id != PES_H_222_1_type_E
+ ) {
+ original_or_copy = *p++;
+
+ //int8_t const2bits = (original_or_copy >> 6) & 0x03;
+ PES_scrambling_control = (original_or_copy >> 4) & 0x03;
+ PES_priority = (original_or_copy >> 3) & 0x01;
+ data_alignment_indicator = (original_or_copy >> 2) & 0x01;
+ copyright = (original_or_copy >> 1) & 0x01;
+ original_or_copy &= 0x01;
+
+ PES_extension_flag = *p++;
+
+ PTS_DTS_flags = (PES_extension_flag >> 6) & 0x03;
+ ESCR_flag = (PES_extension_flag >> 5) & 0x01;
+ ES_rate_flag = (PES_extension_flag >> 4) & 0x01;
+ DSM_trick_mode_flag = (PES_extension_flag >> 3) & 0x01;
+ additional_copy_info_flag = (PES_extension_flag >> 2) & 0x01;
+ PES_CRC_flag = (PES_extension_flag >> 1) & 0x01;
+ PES_extension_flag &= 0x01;
+
+ PES_header_data_length = *p++;
+ u_int8_t* pos_header = p;
- int64_t temp = 0;
- if (PTS_DTS_flags == 0x2) {
- pts = decode_33bits_int(p, temp);
- // '0010' 4bits
- //int8_t const4bits = temp & 0x0F;
- }
+ int64_t temp = 0;
+ if (PTS_DTS_flags == 0x2) {
+ pts = decode_33bits_int(p, temp);
+ // '0010' 4bits
+ //int8_t const4bits = temp & 0x0F;
+ }
- if (PTS_DTS_flags == 0x3) {
- pts = decode_33bits_int(p, temp);
- // '0011' 4bits
- //int8_t const4bits = temp & 0x0F;
-
- dts = decode_33bits_int(p, temp);
- // '0001' 4bits
- //int8_t const4bits = temp & 0x0F;
- }
-
- if (ESCR_flag) {
- pp = (char*)&temp;
- pp[5] = *p++;
- pp[4] = *p++;
- pp[3] = *p++;
- pp[2] = *p++;
- pp[1] = *p++;
- pp[0] = *p++;
-
- // marker_bit 1bit
- temp = temp >> 1;
- // ESCR_extension 9bits
- ESCR_extension = temp & 0x1f;
- temp = temp >> 9;
-
- ESCR_base = decode_33bits_int(temp);
-
- // reserved 2bits
- //int8_t reserved2bits = temp & 0x03;
- }
-
- if (ES_rate_flag) {
- pp = (char*)&ES_rate;
- pp[2] = *p++;
- pp[1] = *p++;
- pp[0] = *p++;
-
- ES_rate = ES_rate >> 1;
- ES_rate &= 0x3FFFFF;
- }
+ if (PTS_DTS_flags == 0x3) {
+ pts = decode_33bits_int(p, temp);
+ // '0011' 4bits
+ //int8_t const4bits = temp & 0x0F;
+
+ dts = decode_33bits_int(p, temp);
+ // '0001' 4bits
+ //int8_t const4bits = temp & 0x0F;
+ }
+
+ if (ESCR_flag) {
+ pp = (char*)&temp;
+ pp[5] = *p++;
+ pp[4] = *p++;
+ pp[3] = *p++;
+ pp[2] = *p++;
+ pp[1] = *p++;
+ pp[0] = *p++;
+
+ // marker_bit 1bit
+ temp = temp >> 1;
+ // ESCR_extension 9bits
+ ESCR_extension = temp & 0x1f;
+ temp = temp >> 9;
+
+ ESCR_base = decode_33bits_int(temp);
+
+ // reserved 2bits
+ //int8_t reserved2bits = temp & 0x03;
+ }
+
+ if (ES_rate_flag) {
+ pp = (char*)&ES_rate;
+ pp[2] = *p++;
+ pp[1] = *p++;
+ pp[0] = *p++;
+
+ ES_rate = ES_rate >> 1;
+ ES_rate &= 0x3FFFFF;
+ }
- if (DSM_trick_mode_flag) {
- trick_mode_control = *p++;
+ if (DSM_trick_mode_flag) {
+ trick_mode_control = *p++;
- trick_mode_value = trick_mode_control & 0x1f;
- trick_mode_control = (trick_mode_control >> 5) & 0x03;
- }
-
- if (additional_copy_info_flag) {
- additional_copy_info = *p++;
- additional_copy_info &= 0x7f;
- }
-
- if (PES_CRC_flag) {
- pp = (char*)&previous_PES_packet_CRC;
- pp[1] = *p++;
- pp[0] = *p++;
- }
+ trick_mode_value = trick_mode_control & 0x1f;
+ trick_mode_control = (trick_mode_control >> 5) & 0x03;
+ }
+
+ if (additional_copy_info_flag) {
+ additional_copy_info = *p++;
+ additional_copy_info &= 0x7f;
+ }
+
+ if (PES_CRC_flag) {
+ pp = (char*)&previous_PES_packet_CRC;
+ pp[1] = *p++;
+ pp[0] = *p++;
+ }
- if (PES_extension_flag) {
- PES_extension_flag_2 = *p++;
-
- PES_private_data_flag = (PES_extension_flag_2 >> 7) & 0x01;
- pack_header_field_flag = (PES_extension_flag_2 >> 6) & 0x01;
- program_packet_sequence_counter_flag = (PES_extension_flag_2 >> 5) & 0x01;
- P_STD_buffer_flag = (PES_extension_flag_2 >> 4) & 0x01;
- PES_extension_flag_2 &= PES_extension_flag_2 & 0x01;
-
- if (PES_private_data_flag) {
- PES_private_data = new char[16];
- memcpy(PES_private_data, p, 16);
- p += 16;
- }
-
- if (pack_header_field_flag) {
- pack_field_length = *p++;
- if (pack_field_length > 0) {
- pack_field = new char[pack_field_length];
- memcpy(pack_field, p, pack_field_length);
- p += pack_field_length;
- }
- }
-
- if (program_packet_sequence_counter_flag) {
- program_packet_sequence_counter = *p++;
- program_packet_sequence_counter &= 0x7f;
-
- original_stuff_length = *p++;
- MPEG1_MPEG2_identifier = (original_stuff_length >> 6) & 0x01;
- original_stuff_length &= 0x3f;
- }
-
- if (P_STD_buffer_flag) {
- pp = (char*)&P_STD_buffer_size;
- pp[1] = *p++;
- pp[0] = *p++;
-
- // '01'
- //int8_t const2bits = (P_STD_buffer_scale >>14) & 0x03;
+ if (PES_extension_flag) {
+ PES_extension_flag_2 = *p++;
+
+ PES_private_data_flag = (PES_extension_flag_2 >> 7) & 0x01;
+ pack_header_field_flag = (PES_extension_flag_2 >> 6) & 0x01;
+ program_packet_sequence_counter_flag = (PES_extension_flag_2 >> 5) & 0x01;
+ P_STD_buffer_flag = (PES_extension_flag_2 >> 4) & 0x01;
+ PES_extension_flag_2 &= PES_extension_flag_2 & 0x01;
+
+ if (PES_private_data_flag) {
+ PES_private_data = new char[16];
+ memcpy(PES_private_data, p, 16);
+ p += 16;
+ }
+
+ if (pack_header_field_flag) {
+ pack_field_length = *p++;
+ if (pack_field_length > 0) {
+ pack_field = new char[pack_field_length];
+ memcpy(pack_field, p, pack_field_length);
+ p += pack_field_length;
+ }
+ }
+
+ if (program_packet_sequence_counter_flag) {
+ program_packet_sequence_counter = *p++;
+ program_packet_sequence_counter &= 0x7f;
+
+ original_stuff_length = *p++;
+ MPEG1_MPEG2_identifier = (original_stuff_length >> 6) & 0x01;
+ original_stuff_length &= 0x3f;
+ }
+
+ if (P_STD_buffer_flag) {
+ pp = (char*)&P_STD_buffer_size;
+ pp[1] = *p++;
+ pp[0] = *p++;
+
+ // '01'
+ //int8_t const2bits = (P_STD_buffer_scale >>14) & 0x03;
- P_STD_buffer_scale = (P_STD_buffer_scale >>13) & 0x01;
- P_STD_buffer_size &= 0x1FFF;
- }
-
- if (PES_extension_flag_2) {
- PES_extension_field_length = *p++;
- PES_extension_field_length &= 0x07;
-
- if (PES_extension_field_length > 0) {
- PES_extension_field = new char[PES_extension_field_length];
- memcpy(PES_extension_field, p, PES_extension_field_length);
- p += PES_extension_field_length;
- }
- }
- }
-
- // stuffing_byte
- int stuffing_size = PES_header_data_length - (p - pos_header);
- if (stuffing_size > 0) {
- stuffing_byte = new char[stuffing_size];
- memcpy(stuffing_byte, p, stuffing_size);
- p += stuffing_size;
- }
-
- // get the pid.
- TSPid* pid = ctx->get(pkt->header->pid);
- if (!pid) {
- trace("ts+pes pid: %d type is invalid.", pkt->header->pid);
- }
-
- // get the message to build from the chunks(PES packets).
- TSMessage* msg = ctx->get_msg(pid->pid);
+ P_STD_buffer_scale = (P_STD_buffer_scale >>13) & 0x01;
+ P_STD_buffer_size &= 0x1FFF;
+ }
+
+ if (PES_extension_flag_2) {
+ PES_extension_field_length = *p++;
+ PES_extension_field_length &= 0x07;
+
+ if (PES_extension_field_length > 0) {
+ PES_extension_field = new char[PES_extension_field_length];
+ memcpy(PES_extension_field, p, PES_extension_field_length);
+ p += PES_extension_field_length;
+ }
+ }
+ }
+
+ // stuffing_byte
+ int stuffing_size = PES_header_data_length - (p - pos_header);
+ if (stuffing_size > 0) {
+ stuffing_byte = new char[stuffing_size];
+ memcpy(stuffing_byte, p, stuffing_size);
+ p += stuffing_size;
+ }
+
+ // get the pid.
+ TSPid* pid = ctx->get(pkt->header->pid);
+ if (!pid) {
+ trace("ts+pes pid: %d type is invalid.", pkt->header->pid);
+ }
+
+ // get the message to build from the chunks(PES packets).
+ TSMessage* msg = ctx->get_msg(pid->pid);
- msg->type = pid->type;
- msg->stream_type = pid->stream_type;
- msg->continuity_counter = pid->continuity_counter;
- msg->stream_id = stream_id;
- msg->packet_start_code_prefix = packet_start_code_prefix;
- msg->dts = dts;
- msg->pts = pts;
-
- // PES_packet_data_byte, page58.
- // the packet size contains the header size.
- // The number of PES_packet_data_bytes, N, is specified by the
- // PES_packet_length field. N shall be equal to the value
- // indicated in the PES_packet_length minus the number of bytes
- // between the last byte of the PES_packet_length field and the
- // first PES_packet_data_byte.
- msg->PES_packet_length = PES_packet_length;
- msg->packet_header_size = p - pos_packet;
- msg->packet_data_size = PES_packet_length - msg->packet_header_size;
-
- /**
- * when actual packet length > 0xffff(65535),
- * which exceed the max u_int16_t packet length,
- * use 0 packet length, the next unit start indicates the end of packet.
- */
- if (PES_packet_length == 0) {
- msg->packet_data_size = last - p - msg->packet_header_size;
- }
-
- if (msg->packet_data_size > 0) {
- msg->packet_data = new char[msg->packet_data_size];
- }
-
- // PES_packet_data_byte
- int size = srs_min(msg->packet_data_size, last - p);
- if (size > 0) {
- msg->append(p, size);
- }
-
- if (PES_packet_length > 0) {
- msg->detach(ctx, pmsg);
- }
-
- trace("ts+pes stream_id: %d size: %d pts: %"PRId64" dts: %"PRId64" total: %d header: %d packet_size: %d parsed_size: %d",
- stream_id, PES_packet_length, pts, dts, msg->PES_packet_length, msg->packet_header_size, msg->packet_data_size, msg->parsed_packet_size);
- } else if (stream_id == PES_program_stream_map
- || stream_id == PES_private_stream_2
- || stream_id == PES_ECM_stream
- || stream_id == PES_EMM_stream
- || stream_id == PES_program_stream_directory
- || stream_id == PES_DSMCC_stream
- || stream_id == PES_H_222_1_type_E
- ) {
- // for (i = 0; i < PES_packet_length; i++) {
- // PES_packet_data_byte
- // }
- } else if (stream_id != PES_padding_stream) {
- // for (i = 0; i < PES_packet_length; i++) {
- // padding_byte
- // }
- }
+ msg->type = pid->type;
+ msg->stream_type = pid->stream_type;
+ msg->continuity_counter = pid->continuity_counter;
+ msg->stream_id = stream_id;
+ msg->packet_start_code_prefix = packet_start_code_prefix;
+ msg->dts = dts;
+ msg->pts = pts;
+
+ // PES_packet_data_byte, page58.
+ // the packet size contains the header size.
+ // The number of PES_packet_data_bytes, N, is specified by the
+ // PES_packet_length field. N shall be equal to the value
+ // indicated in the PES_packet_length minus the number of bytes
+ // between the last byte of the PES_packet_length field and the
+ // first PES_packet_data_byte.
+ msg->PES_packet_length = PES_packet_length;
+ msg->packet_header_size = p - pos_packet;
+ msg->packet_data_size = PES_packet_length - msg->packet_header_size;
+
+ /**
+ * when actual packet length > 0xffff(65535),
+ * which exceed the max u_int16_t packet length,
+ * use 0 packet length, the next unit start indicates the end of packet.
+ */
+ if (PES_packet_length == 0) {
+ msg->packet_data_size = last - p - msg->packet_header_size;
+ }
+
+ if (msg->packet_data_size > 0) {
+ msg->packet_data = new char[msg->packet_data_size];
+ }
+
+ // PES_packet_data_byte
+ int size = srs_min(msg->packet_data_size, last - p);
+ if (size > 0) {
+ msg->append(p, size);
+ }
+
+ if (PES_packet_length > 0) {
+ msg->detach(ctx, pmsg);
+ }
+
+ trace("ts+pes stream_id: %d size: %d pts: %"PRId64" dts: %"PRId64" total: %d header: %d packet_size: %d parsed_size: %d",
+ stream_id, PES_packet_length, pts, dts, msg->PES_packet_length, msg->packet_header_size, msg->packet_data_size, msg->parsed_packet_size);
+ } else if (stream_id == PES_program_stream_map
+ || stream_id == PES_private_stream_2
+ || stream_id == PES_ECM_stream
+ || stream_id == PES_EMM_stream
+ || stream_id == PES_program_stream_directory
+ || stream_id == PES_DSMCC_stream
+ || stream_id == PES_H_222_1_type_E
+ ) {
+ // for (i = 0; i < PES_packet_length; i++) {
+ // PES_packet_data_byte
+ // }
+ } else if (stream_id != PES_padding_stream) {
+ // for (i = 0; i < PES_packet_length; i++) {
+ // padding_byte
+ // }
+ }
return ret;
}
@@ -1603,16 +1603,16 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l
return pmt->demux(ctx, pkt, start, last, p, pmsg);
}
if (pid && (pid->type == TSPidTypeVideo || pid->type == TSPidTypeAudio)) {
- TSMessage* msg = ctx->get_msg(pkt->header->pid);
+ TSMessage* msg = ctx->get_msg(pkt->header->pid);
- if (pkt->adaption_field->pcr > 0) {
- msg->pcr = pkt->adaption_field->pcr;
- }
-
+ if (pkt->adaption_field->pcr > 0) {
+ msg->pcr = pkt->adaption_field->pcr;
+ }
+
// flush previous PES_packet_length(0) packets.
if (msg->packet_start_code_prefix == 0x01
&& pkt->header->payload_unit_start_indicator == 1
- && msg->PES_packet_length == 0
+ && msg->PES_packet_length == 0
) {
msg->detach(ctx, pmsg);
// reparse current message
@@ -1620,21 +1620,21 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l
return ret;
}
- // parse continous packet.
- if (!pkt->header->payload_unit_start_indicator) {
- if (msg->packet_start_code_prefix != 0x01) {
- trace("ts+pes decode continous packet error, msg is empty.");
- return -1;
- }
- msg->append(p, last - p);
-
- // for PES_packet_length is 0, donot attach it.
- if (msg->PES_packet_length > 0) {
- msg->detach(ctx, pmsg);
- }
- return ret;
- }
-
+ // parse continous packet.
+ if (!pkt->header->payload_unit_start_indicator) {
+ if (msg->packet_start_code_prefix != 0x01) {
+ trace("ts+pes decode continous packet error, msg is empty.");
+ return -1;
+ }
+ msg->append(p, last - p);
+
+ // for PES_packet_length is 0, donot attach it.
+ if (msg->PES_packet_length > 0) {
+ msg->detach(ctx, pmsg);
+ }
+ return ret;
+ }
+
type = pid->type;
pes = new TSPayloadPES();
return pes->demux(ctx, pkt, start, last, p, pmsg);
@@ -1684,7 +1684,7 @@ int TSPacket::demux(TSContext* ctx, u_int8_t* start, u_int8_t* last, u_int8_t*&
payload->size = TS_PACKET_SIZE - header->get_size() - adaption_field->get_size();
if (header->adaption_field_control == TSAdaptionTypePayloadOnly || header->adaption_field_control == TSAdaptionTypeBoth) {
- // parse new packet.
+ // parse new packet.
if ((ret = payload->demux(ctx, this, start, last, p, pmsg)) != 0) {
trace("ts+header payload decode error. ret=%d", ret);
return ret;
@@ -1771,84 +1771,84 @@ int TSHeader::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* la
class TSH264Codec
{
public:
- u_int8_t* raw_data;
- int size;
-
- TSH264Codec()
- {
- size = 0;
- raw_data = NULL;
- }
-
- u_int8_t at(int index)
- {
- if (index >= size) {
- return 0;
- }
- return raw_data[index];
- }
-
- int parse(TSMessage* msg, char* last, char*& p)
- {
- int ret = 0;
-
- srs_assert(p);
-
- while (next_start_code_prefix(p) != 0x000001) {
- char ch = *p++;
- if (ch != 0x00) {
- trace("ts+h264 parse msg failed, "
- "expect 0x00 before start-code. actual is: %#x", (u_int8_t)ch);
- return -1;
- }
- }
-
- if (p >= last) {
- trace("ts+h264 parse msg finished, no start-code.");
- return ret;
- }
-
- // start_code_prefix_one_3bytes /* equal to 0x000001 */
- p += 3;
-
- if (p < last) {
- raw_data = (u_int8_t*)p;
- }
- while (p < last - 3) {
- if (match_start_code_prefix(p)) {
- break;
- }
- p++;
- }
-
- if (raw_data) {
- size = (u_int8_t*)p - raw_data;
- if (p == last - 3) {
- size = (u_int8_t*)last - raw_data;
- p = last;
- }
- }
-
- trace("ts+h264 parse msg finished");
- return ret;
- }
-
- bool match_start_code_prefix(char*p)
- {
- return p[0] == 0x00 && p[1] == 0x00 && (p[2] == 0x00 || p[2] == 0x01);
- }
-
- int32_t next_start_code_prefix(char* p)
- {
- int32_t value = 0;
- char* pp = (char*)&value;
-
- pp[2] = p[0];
- pp[1] = p[1];
- pp[0] = p[2];
+ u_int8_t* raw_data;
+ int size;
+
+ TSH264Codec()
+ {
+ size = 0;
+ raw_data = NULL;
+ }
+
+ u_int8_t at(int index)
+ {
+ if (index >= size) {
+ return 0;
+ }
+ return raw_data[index];
+ }
+
+ int parse(TSMessage* msg, char* last, char*& p)
+ {
+ int ret = 0;
+
+ srs_assert(p);
+
+ while (next_start_code_prefix(p) != 0x000001) {
+ char ch = *p++;
+ if (ch != 0x00) {
+ trace("ts+h264 parse msg failed, "
+ "expect 0x00 before start-code. actual is: %#x", (u_int8_t)ch);
+ return -1;
+ }
+ }
+
+ if (p >= last) {
+ trace("ts+h264 parse msg finished, no start-code.");
+ return ret;
+ }
+
+ // start_code_prefix_one_3bytes /* equal to 0x000001 */
+ p += 3;
+
+ if (p < last) {
+ raw_data = (u_int8_t*)p;
+ }
+ while (p < last - 3) {
+ if (match_start_code_prefix(p)) {
+ break;
+ }
+ p++;
+ }
+
+ if (raw_data) {
+ size = (u_int8_t*)p - raw_data;
+ if (p == last - 3) {
+ size = (u_int8_t*)last - raw_data;
+ p = last;
+ }
+ }
+
+ trace("ts+h264 parse msg finished");
+ return ret;
+ }
+
+ bool match_start_code_prefix(char*p)
+ {
+ return p[0] == 0x00 && p[1] == 0x00 && (p[2] == 0x00 || p[2] == 0x01);
+ }
+
+ int32_t next_start_code_prefix(char* p)
+ {
+ int32_t value = 0;
+ char* pp = (char*)&value;
+
+ pp[2] = p[0];
+ pp[1] = p[1];
+ pp[0] = p[2];
- return value;
- }
+ return value;
+ }
};
/**
@@ -1857,22 +1857,22 @@ public:
*/
enum TSAacSampleFrequency
{
- TSAacSampleFrequency96000 = 0x00,
- TSAacSampleFrequency88200 = 0x01,
- TSAacSampleFrequency64000 = 0x02,
- TSAacSampleFrequency48000 = 0x03,
- TSAacSampleFrequency44100 = 0x04,
- TSAacSampleFrequency32000 = 0x05,
- TSAacSampleFrequency24000 = 0x06,
- TSAacSampleFrequency22050 = 0x07,
- TSAacSampleFrequency16000 = 0x08,
- TSAacSampleFrequency12000 = 0x09,
- TSAacSampleFrequency11025 = 0x0a,
- TSAacSampleFrequency8000 = 0x0b,
- TSAacSampleFrequencyReserved0 = 0x0c,
- TSAacSampleFrequencyReserved1 = 0x0d,
- TSAacSampleFrequencyReserved2 = 0x0e,
- TSAacSampleFrequencyReserved3 = 0x0f,
+ TSAacSampleFrequency96000 = 0x00,
+ TSAacSampleFrequency88200 = 0x01,
+ TSAacSampleFrequency64000 = 0x02,
+ TSAacSampleFrequency48000 = 0x03,
+ TSAacSampleFrequency44100 = 0x04,
+ TSAacSampleFrequency32000 = 0x05,
+ TSAacSampleFrequency24000 = 0x06,
+ TSAacSampleFrequency22050 = 0x07,
+ TSAacSampleFrequency16000 = 0x08,
+ TSAacSampleFrequency12000 = 0x09,
+ TSAacSampleFrequency11025 = 0x0a,
+ TSAacSampleFrequency8000 = 0x0b,
+ TSAacSampleFrequencyReserved0 = 0x0c,
+ TSAacSampleFrequencyReserved1 = 0x0d,
+ TSAacSampleFrequencyReserved2 = 0x0e,
+ TSAacSampleFrequencyReserved3 = 0x0f,
};
/**
@@ -1881,313 +1881,313 @@ enum TSAacSampleFrequency
class TSAacAdts
{
public:
- // adts_fixed_header
- // 2B, 16bits
- int16_t syncword; //12bits
- int8_t ID; //1bit
- int8_t layer; //2bits
- int8_t protection_absent; //1bit
- // 12bits
- int8_t profile; //2bit
- TSAacSampleFrequency sampling_frequency_index; //4bits
- int8_t private_bit; //1bit
- int8_t channel_configuration; //3bits
- int8_t original_or_copy; //1bit
- int8_t home; //1bit
-
- // adts_variable_header
- // 28bits
- int8_t copyright_identification_bit; //1bit
- int8_t copyright_identification_start; //1bit
- int16_t frame_length; //13bits
- int16_t adts_buffer_fullness; //11bits
- int8_t number_of_raw_data_blocks_in_frame; //2bits
-
- u_int8_t* raw_data;
- int size;
-
- TSAacAdts()
- {
- syncword = 0;
- ID = 0;
- layer = 0;
- protection_absent = 0;
- profile = 0;
- sampling_frequency_index = TSAacSampleFrequencyReserved0;
- private_bit = 0;
- channel_configuration = 0;
- original_or_copy = 0;
- home = 0;
- copyright_identification_bit = 0;
- copyright_identification_start = 0;
- frame_length = 0;
- adts_buffer_fullness = 0;
- number_of_raw_data_blocks_in_frame = 0;
-
- size = 0;
- raw_data = NULL;
- }
-
- u_int8_t at(int index)
- {
- if (index >= size) {
- return 0;
- }
- return raw_data[index];
- }
-
- int parse(TSMessage* msg, char*& p)
- {
- int ret = 0;
-
- srs_assert(p);
-
- char* start = p;
-
- // adts_fixed_header
- char* pp = (char*)&syncword;
- pp[1] = *p++;
- pp[0] = *p++;
-
- protection_absent = syncword & 0x01;
- layer = (syncword >> 1) & 0x03;
- ID = (syncword >> 3) & 0x01;
- syncword = (syncword >> 4) & 0x0FFF;
- if (syncword != 0xfff) {
- trace("ts+aac invalid sync word. expect 0xfff, actual %#x", syncword);
- return -1;
- }
+ // adts_fixed_header
+ // 2B, 16bits
+ int16_t syncword; //12bits
+ int8_t ID; //1bit
+ int8_t layer; //2bits
+ int8_t protection_absent; //1bit
+ // 12bits
+ int8_t profile; //2bit
+ TSAacSampleFrequency sampling_frequency_index; //4bits
+ int8_t private_bit; //1bit
+ int8_t channel_configuration; //3bits
+ int8_t original_or_copy; //1bit
+ int8_t home; //1bit
+
+ // adts_variable_header
+ // 28bits
+ int8_t copyright_identification_bit; //1bit
+ int8_t copyright_identification_start; //1bit
+ int16_t frame_length; //13bits
+ int16_t adts_buffer_fullness; //11bits
+ int8_t number_of_raw_data_blocks_in_frame; //2bits
+
+ u_int8_t* raw_data;
+ int size;
+
+ TSAacAdts()
+ {
+ syncword = 0;
+ ID = 0;
+ layer = 0;
+ protection_absent = 0;
+ profile = 0;
+ sampling_frequency_index = TSAacSampleFrequencyReserved0;
+ private_bit = 0;
+ channel_configuration = 0;
+ original_or_copy = 0;
+ home = 0;
+ copyright_identification_bit = 0;
+ copyright_identification_start = 0;
+ frame_length = 0;
+ adts_buffer_fullness = 0;
+ number_of_raw_data_blocks_in_frame = 0;
+
+ size = 0;
+ raw_data = NULL;
+ }
+
+ u_int8_t at(int index)
+ {
+ if (index >= size) {
+ return 0;
+ }
+ return raw_data[index];
+ }
+
+ int parse(TSMessage* msg, char*& p)
+ {
+ int ret = 0;
+
+ srs_assert(p);
+
+ char* start = p;
+
+ // adts_fixed_header
+ char* pp = (char*)&syncword;
+ pp[1] = *p++;
+ pp[0] = *p++;
+
+ protection_absent = syncword & 0x01;
+ layer = (syncword >> 1) & 0x03;
+ ID = (syncword >> 3) & 0x01;
+ syncword = (syncword >> 4) & 0x0FFF;
+ if (syncword != 0xfff) {
+ trace("ts+aac invalid sync word. expect 0xfff, actual %#x", syncword);
+ return -1;
+ }
- // adts_variable_header
- int64_t temp = 0;
- pp = (char*)&temp;
- pp[4] = *p++;
- pp[3] = *p++;
- pp[2] = *p++;
- pp[1] = *p++;
- pp[0] = *p++;
-
- number_of_raw_data_blocks_in_frame = temp & 0x03;
- temp = temp >> 2;
+ // adts_variable_header
+ int64_t temp = 0;
+ pp = (char*)&temp;
+ pp[4] = *p++;
+ pp[3] = *p++;
+ pp[2] = *p++;
+ pp[1] = *p++;
+ pp[0] = *p++;
+
+ number_of_raw_data_blocks_in_frame = temp & 0x03;
+ temp = temp >> 2;
- adts_buffer_fullness = temp & 0x7FF;
- temp = temp >> 11;
+ adts_buffer_fullness = temp & 0x7FF;
+ temp = temp >> 11;
- frame_length = temp & 0x1FFF;
- temp = temp >> 13;
-
- copyright_identification_start = temp & 0x01;
- temp = temp >> 1;
-
- copyright_identification_bit = temp & 0x01;
- temp = temp >> 1;
-
- // adts_fixed_header
- home = temp & 0x01;
- temp = temp >> 1;
-
- original_or_copy = temp & 0x01;
- temp = temp >> 1;
-
- channel_configuration = temp & 0x07;
- temp = temp >> 3;
-
- private_bit = temp & 0x01;
- temp = temp >> 1;
-
- sampling_frequency_index = (TSAacSampleFrequency)(temp & 0x0F);
- temp = temp >> 4;
-
- profile = temp & 0x03;
- temp = temp >> 2;
+ frame_length = temp & 0x1FFF;
+ temp = temp >> 13;
+
+ copyright_identification_start = temp & 0x01;
+ temp = temp >> 1;
+
+ copyright_identification_bit = temp & 0x01;
+ temp = temp >> 1;
+
+ // adts_fixed_header
+ home = temp & 0x01;
+ temp = temp >> 1;
+
+ original_or_copy = temp & 0x01;
+ temp = temp >> 1;
+
+ channel_configuration = temp & 0x07;
+ temp = temp >> 3;
+
+ private_bit = temp & 0x01;
+ temp = temp >> 1;
+
+ sampling_frequency_index = (TSAacSampleFrequency)(temp & 0x0F);
+ temp = temp >> 4;
+
+ profile = temp & 0x03;
+ temp = temp >> 2;
- if (!number_of_raw_data_blocks_in_frame) {
- // adts_error_check
- if (!protection_absent) {
- // crc_check
- trace("ts+aac TODO: crc_check.");
- }
- // raw_data_block
- raw_data = (u_int8_t*)p;
- size = frame_length - (p - start);
- p += size;
- } else {
- trace("ts+aac TODO: parse multiple blocks.");
- }
-
- return ret;
- }
+ if (!number_of_raw_data_blocks_in_frame) {
+ // adts_error_check
+ if (!protection_absent) {
+ // crc_check
+ trace("ts+aac TODO: crc_check.");
+ }
+ // raw_data_block
+ raw_data = (u_int8_t*)p;
+ size = frame_length - (p - start);
+ p += size;
+ } else {
+ trace("ts+aac TODO: parse multiple blocks.");
+ }
+
+ return ret;
+ }
};
class AacMuxer
{
public:
- int fd;
- const char* file;
+ int fd;
+ const char* file;
- AacMuxer()
- {
- file = NULL;
- fd = 0;
- }
-
- virtual ~AacMuxer()
- {
- if (fd > 0) {
- close(fd);
- }
- }
+ AacMuxer()
+ {
+ file = NULL;
+ fd = 0;
+ }
+
+ virtual ~AacMuxer()
+ {
+ if (fd > 0) {
+ close(fd);
+ }
+ }
- int open(const char* _file)
- {
- file = _file;
- if ((fd = ::open(file, O_CREAT|O_WRONLY|O_TRUNC,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH)) < 0
- ) {
- return -1;
- }
-
- return 0;
- }
+ int open(const char* _file)
+ {
+ file = _file;
+ if ((fd = ::open(file, O_CREAT|O_WRONLY|O_TRUNC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH)) < 0
+ ) {
+ return -1;
+ }
+
+ return 0;
+ }
- int write_audio(char* data, int size)
- {
- if (size > 0 && write(fd, data, size) != size) {
- return -1;
- }
-
- return 0;
- }
+ int write_audio(char* data, int size)
+ {
+ if (size > 0 && write(fd, data, size) != size) {
+ return -1;
+ }
+
+ return 0;
+ }
- int write_video(char* data, int size)
- {
- return 0;
- }
+ int write_video(char* data, int size)
+ {
+ return 0;
+ }
};
int consume(TSMessage* msg, AacMuxer* aac_muxer)
{
- int ret = 0;
-
- char* p = msg->packet_data;
- if (!p) {
- trace("ts+aac+h264 ignore empty message.");
- return ret;
- }
-
- char* last = msg->packet_data + msg->packet_data_size;
-
- if (!msg->is_video()) {
- // write AAC raw audio.
- if (aac_muxer && (ret = aac_muxer->write_audio((char*)msg->packet_data, msg->packet_data_size)) != 0) {
- return ret;
- }
-
- // parse AAC audio.
- int64_t dts = -1;
- while (p < last) {
- TSAacAdts aac;
- if ((ret = aac.parse(msg, p)) != 0) {
- return ret;
- }
- trace("ts+aac audio raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x",
- aac.size, aac.at(0), aac.at(1), aac.at(2), aac.at(3));
-
- if (dts == -1) {
- dts = (msg->dts == 0)? msg->pts : msg->dts;
- } else {
- // see ffmpeg: avpriv_aac_parse_header
- // rdb = get_bits(gbc, 2); /* number_of_raw_data_blocks_in_frame */
- // hdr->samples = (rdb + 1) * 1024;
- int samples = (aac.number_of_raw_data_blocks_in_frame + 1) * 1024;
- static int sample_rates[] = {
- 96000, 88200, 64000, 48000, 44100, 32000,
- 24000, 22050, 16000, 12000, 11025, 8000,
- 1, 1, 1, 1
- };
- int sample_rate = sample_rates[aac.sampling_frequency_index];
-
- dts += samples * 90000 / sample_rate;
- }
-
- trace("ts+aac+h264+data %s pts:%"PRId64" dts:%"PRId64" size: %d",
- (msg->type == TSPidTypeVideo)? "video":"audio", dts, dts, aac.frame_length);
-
- // TODO: process audio.
- }
- } else {
- trace("ts+aac+h264+data %s pts:%"PRId64" dts:%"PRId64" size: %d",
- (msg->type == TSPidTypeVideo)? "video":"audio", msg->pts,
- (msg->dts == 0)? msg->pts : msg->dts, msg->packet_data_size);
-
- // parse H264 video.
- bool first = true;
- while (p < last) {
- TSH264Codec h264;
- if ((ret = h264.parse(msg, last, p)) != 0) {
- return ret;
- }
- trace("ts+h264 video raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x",
- h264.size, h264.at(0), h264.at(1), h264.at(2), h264.at(3));
-
- // first?
- if (!first) {
- continue;
- }
- first = false;
-
- // TODO: process video.
-
- // directly check the sequence header for test_22m.flv
- if (h264.at(0) == 0x67 && h264.at(1) == 0x00 && h264.at(2) == 0x1f && h264.at(3) == 0xac) {
- trace("ts+h264 directly find the sequence header for test_22m.flv");
- }
- // 7.3.1 NAL unit syntax, hls-mpeg-ts-iso13818-1.pdf, page 44
- char* pp = (char*)h264.raw_data;
- int8_t nal_unit_type = *pp++;
- int8_t nal_ref_idc = (nal_unit_type >> 5) & 0x03;
- nal_unit_type &= 0x1f;
-
- msg->nal_ref_idc = nal_ref_idc;
- msg->nal_unit_type = nal_unit_type;
-
- if (nal_ref_idc != 0) {
- trace("ts+h264 got an SPS or PPS.");
- }
- if (nal_unit_type == 7) {
- trace("ts+h264 got an SPS.");
- } else if (nal_unit_type == 5) {
- trace("ts+h264 got an Coded slice of an IDR picture.");
- } else if (nal_unit_type == 8) {
- trace("ts+h264 got an PPS.");
- } else if (nal_unit_type == 9) {
- trace("ts+h264 got an Picture delimiter.");
- int8_t pic_type = *pp++;
- pic_type = (pic_type >> 6) & 0x07;
- if (pic_type == 0) {
- trace("ts+h264 got an I picture.");
- } else if (pic_type == 1) {
- trace("ts+h264 got an I,P picture.");
- } else if (pic_type == 2) {
- trace("ts+h264 got an I,P,B picture.");
- } else if (pic_type == 3) {
- trace("ts+h264 got an SI picture.");
- } else if (pic_type == 4) {
- trace("ts+h264 got an SI,SP picture.");
- } else if (pic_type == 5) {
- trace("ts+h264 got an I,SI picture.");
- } else if (pic_type == 6) {
- trace("ts+h264 got an I,SI,P,SP picture.");
- } else if (pic_type == 7) {
- trace("ts+h264 got an I,SI,P,SP,B picture.");
- }
- } else {
- trace("ts+h264 got an unknown unit type: %d.", nal_unit_type);
- }
- }
+ int ret = 0;
+
+ char* p = msg->packet_data;
+ if (!p) {
+ trace("ts+aac+h264 ignore empty message.");
+ return ret;
}
- return ret;
+ char* last = msg->packet_data + msg->packet_data_size;
+
+ if (!msg->is_video()) {
+ // write AAC raw audio.
+ if (aac_muxer && (ret = aac_muxer->write_audio((char*)msg->packet_data, msg->packet_data_size)) != 0) {
+ return ret;
+ }
+
+ // parse AAC audio.
+ int64_t dts = -1;
+ while (p < last) {
+ TSAacAdts aac;
+ if ((ret = aac.parse(msg, p)) != 0) {
+ return ret;
+ }
+ trace("ts+aac audio raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x",
+ aac.size, aac.at(0), aac.at(1), aac.at(2), aac.at(3));
+
+ if (dts == -1) {
+ dts = (msg->dts == 0)? msg->pts : msg->dts;
+ } else {
+ // see ffmpeg: avpriv_aac_parse_header
+ // rdb = get_bits(gbc, 2); /* number_of_raw_data_blocks_in_frame */
+ // hdr->samples = (rdb + 1) * 1024;
+ int samples = (aac.number_of_raw_data_blocks_in_frame + 1) * 1024;
+ static int sample_rates[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000,
+ 1, 1, 1, 1
+ };
+ int sample_rate = sample_rates[aac.sampling_frequency_index];
+
+ dts += samples * 90000 / sample_rate;
+ }
+
+ trace("ts+aac+h264+data %s pts:%"PRId64" dts:%"PRId64" size: %d",
+ (msg->type == TSPidTypeVideo)? "video":"audio", dts, dts, aac.frame_length);
+
+ // TODO: process audio.
+ }
+ } else {
+ trace("ts+aac+h264+data %s pts:%"PRId64" dts:%"PRId64" size: %d",
+ (msg->type == TSPidTypeVideo)? "video":"audio", msg->pts,
+ (msg->dts == 0)? msg->pts : msg->dts, msg->packet_data_size);
+
+ // parse H264 video.
+ bool first = true;
+ while (p < last) {
+ TSH264Codec h264;
+ if ((ret = h264.parse(msg, last, p)) != 0) {
+ return ret;
+ }
+ trace("ts+h264 video raw data parsed, size: %d, 0x%02x 0x%02x 0x%02x 0x%02x",
+ h264.size, h264.at(0), h264.at(1), h264.at(2), h264.at(3));
+
+ // first?
+ if (!first) {
+ continue;
+ }
+ first = false;
+
+ // TODO: process video.
+
+ // directly check the sequence header for test_22m.flv
+ if (h264.at(0) == 0x67 && h264.at(1) == 0x00 && h264.at(2) == 0x1f && h264.at(3) == 0xac) {
+ trace("ts+h264 directly find the sequence header for test_22m.flv");
+ }
+ // 7.3.1 NAL unit syntax, hls-mpeg-ts-iso13818-1.pdf, page 44
+ char* pp = (char*)h264.raw_data;
+ int8_t nal_unit_type = *pp++;
+ int8_t nal_ref_idc = (nal_unit_type >> 5) & 0x03;
+ nal_unit_type &= 0x1f;
+
+ msg->nal_ref_idc = nal_ref_idc;
+ msg->nal_unit_type = nal_unit_type;
+
+ if (nal_ref_idc != 0) {
+ trace("ts+h264 got an SPS or PPS.");
+ }
+ if (nal_unit_type == 7) {
+ trace("ts+h264 got an SPS.");
+ } else if (nal_unit_type == 5) {
+ trace("ts+h264 got an Coded slice of an IDR picture.");
+ } else if (nal_unit_type == 8) {
+ trace("ts+h264 got an PPS.");
+ } else if (nal_unit_type == 9) {
+ trace("ts+h264 got an Picture delimiter.");
+ int8_t pic_type = *pp++;
+ pic_type = (pic_type >> 6) & 0x07;
+ if (pic_type == 0) {
+ trace("ts+h264 got an I picture.");
+ } else if (pic_type == 1) {
+ trace("ts+h264 got an I,P picture.");
+ } else if (pic_type == 2) {
+ trace("ts+h264 got an I,P,B picture.");
+ } else if (pic_type == 3) {
+ trace("ts+h264 got an SI picture.");
+ } else if (pic_type == 4) {
+ trace("ts+h264 got an SI,SP picture.");
+ } else if (pic_type == 5) {
+ trace("ts+h264 got an I,SI picture.");
+ } else if (pic_type == 6) {
+ trace("ts+h264 got an I,SI,P,SP picture.");
+ } else if (pic_type == 7) {
+ trace("ts+h264 got an I,SI,P,SP,B picture.");
+ }
+ } else {
+ trace("ts+h264 got an unknown unit type: %d.", nal_unit_type);
+ }
+ }
+ }
+
+ return ret;
}
int main(int argc, char** argv)
@@ -2234,36 +2234,36 @@ int main(int argc, char** argv)
// maybe need to parse multiple times for the PES_packet_length(0) packets.
while (p == start) {
- TSPacket pkt;
- TSMessage* msg = NULL;
- if ((ret = pkt.demux(&ctx, start, last, p, msg)) != 0) {
- trace("demuxer+read decode ts packet error. ret=%d", ret);
- return ret;
- }
-
- offset += nread;
- if (!msg) {
- continue;
- }
-
- if ((ret = consume(msg, &aac_muxer)) != 0) {
- trace("demuxer+consume parse and consume message failed. ret=%d", ret);
- return -1;
- }
-
- int64_t pts = msg->pts;
- int64_t dts = (msg->dts == 0)? msg->pts : msg->dts;
- int64_t pcr = msg->pcr;
- static int64_t last_pcr_dts = 0;
- trace("demuxer+report id=%d, type=%s, size=%d, dts=%d, pts=%d, cts=%d, pcr=%d, dts-pcr=%d, ref=%d, unit=%d, dts(diff-pcr)=%d",
- ctx.ts_packet_count, (msg->type == TSPidTypeVideo)? "video":"audio",
- msg->parsed_packet_size, dts, pts, pts - dts, pcr, pcr? dts - pcr : 0,
- msg->nal_ref_idc, msg->nal_unit_type, pcr? dts - last_pcr_dts: 0);
- if (pcr > 0) {
- last_pcr_dts = dts;
- }
-
- srs_freep(msg);
+ TSPacket pkt;
+ TSMessage* msg = NULL;
+ if ((ret = pkt.demux(&ctx, start, last, p, msg)) != 0) {
+ trace("demuxer+read decode ts packet error. ret=%d", ret);
+ return ret;
+ }
+
+ offset += nread;
+ if (!msg) {
+ continue;
+ }
+
+ if ((ret = consume(msg, &aac_muxer)) != 0) {
+ trace("demuxer+consume parse and consume message failed. ret=%d", ret);
+ return -1;
+ }
+
+ int64_t pts = msg->pts;
+ int64_t dts = (msg->dts == 0)? msg->pts : msg->dts;
+ int64_t pcr = msg->pcr;
+ static int64_t last_pcr_dts = 0;
+ trace("demuxer+report id=%d, type=%s, size=%d, dts=%d, pts=%d, cts=%d, pcr=%d, dts-pcr=%d, ref=%d, unit=%d, dts(diff-pcr)=%d",
+ ctx.ts_packet_count, (msg->type == TSPidTypeVideo)? "video":"audio",
+ msg->parsed_packet_size, dts, pts, pts - dts, pcr, pcr? dts - pcr : 0,
+ msg->nal_ref_idc, msg->nal_unit_type, pcr? dts - last_pcr_dts: 0);
+ if (pcr > 0) {
+ last_pcr_dts = dts;
+ }
+
+ srs_freep(msg);
}
}
diff --git a/trunk/research/librtmp/srs_play.c b/trunk/research/librtmp/srs_play.c
index 00953fcea..adb337d01 100644
--- a/trunk/research/librtmp/srs_play.c
+++ b/trunk/research/librtmp/srs_play.c
@@ -31,46 +31,46 @@ gcc srs_play.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_play
int main(int argc, char** argv)
{
- srs_rtmp_t rtmp;
-
- // packet data
- int type, size;
- u_int32_t timestamp = 0;
- char* data;
-
+ srs_rtmp_t rtmp;
+
+ // packet data
+ int type, size;
+ u_int32_t timestamp = 0;
+ char* data;
+
printf("suck rtmp stream like rtmpdump\n");
printf("srs(simple-rtmp-server) client librtmp library.\n");
printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live/livestream");
- if (srs_simple_handshake(rtmp) != 0) {
- printf("simple handshake failed.\n");
- goto rtmp_destroy;
- }
- printf("simple handshake success\n");
+ if (srs_simple_handshake(rtmp) != 0) {
+ printf("simple handshake failed.\n");
+ goto rtmp_destroy;
+ }
+ printf("simple handshake success\n");
- if (srs_connect_app(rtmp) != 0) {
- printf("connect vhost/app failed.\n");
- goto rtmp_destroy;
- }
- printf("connect vhost/app success\n");
+ if (srs_connect_app(rtmp) != 0) {
+ printf("connect vhost/app failed.\n");
+ goto rtmp_destroy;
+ }
+ printf("connect vhost/app success\n");
+
+ if (srs_play_stream(rtmp) != 0) {
+ printf("play stream failed.\n");
+ goto rtmp_destroy;
+ }
+ printf("play stream success\n");
+
+ for (;;) {
+ if (srs_read_packet(rtmp, &type, ×tamp, &data, &size) != 0) {
+ goto rtmp_destroy;
+ }
+ printf("got packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size);
+
+ free(data);
+ }
- if (srs_play_stream(rtmp) != 0) {
- printf("play stream failed.\n");
- goto rtmp_destroy;
- }
- printf("play stream success\n");
-
- for (;;) {
- if (srs_read_packet(rtmp, &type, ×tamp, &data, &size) != 0) {
- goto rtmp_destroy;
- }
- printf("got packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size);
-
- free(data);
- }
-
rtmp_destroy:
srs_rtmp_destroy(rtmp);
diff --git a/trunk/research/librtmp/srs_publish.c b/trunk/research/librtmp/srs_publish.c
index b475c7a43..865cc2854 100644
--- a/trunk/research/librtmp/srs_publish.c
+++ b/trunk/research/librtmp/srs_publish.c
@@ -32,51 +32,52 @@ gcc srs_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_publish
int main(int argc, char** argv)
{
- srs_rtmp_t rtmp;
-
- // packet data
- int type, size;
- u_int32_t timestamp = 0;
- char* data;
-
+ srs_rtmp_t rtmp;
+
+ // packet data
+ int type, size;
+ u_int32_t timestamp = 0;
+ char* data;
+
printf("publish rtmp stream to server like FMLE/FFMPEG/Encoder\n");
printf("srs(simple-rtmp-server) client librtmp library.\n");
printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live/livestream");
- if (srs_simple_handshake(rtmp) != 0) {
- printf("simple handshake failed.\n");
- goto rtmp_destroy;
- }
- printf("simple handshake success\n");
+ //if (srs_simple_handshake(rtmp) != 0) {
+ if (srs_complex_handshake(rtmp) != 0) {
+ printf("simple handshake failed.\n");
+ goto rtmp_destroy;
+ }
+ printf("simple handshake success\n");
- if (srs_connect_app(rtmp) != 0) {
- printf("connect vhost/app failed.\n");
- goto rtmp_destroy;
- }
- printf("connect vhost/app success\n");
+ if (srs_connect_app(rtmp) != 0) {
+ printf("connect vhost/app failed.\n");
+ goto rtmp_destroy;
+ }
+ printf("connect vhost/app success\n");
+
+ if (srs_publish_stream(rtmp) != 0) {
+ printf("publish stream failed.\n");
+ goto rtmp_destroy;
+ }
+ printf("publish stream success\n");
+
+ for (;;) {
+ type = SRS_RTMP_TYPE_VIDEO;
+ timestamp += 40;
+ size = 4096;
+ data = (char*)malloc(4096);
+
+ if (srs_write_packet(rtmp, type, timestamp, data, size) != 0) {
+ goto rtmp_destroy;
+ }
+ printf("sent packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size);
+
+ usleep(40 * 1000);
+ }
- if (srs_publish_stream(rtmp) != 0) {
- printf("publish stream failed.\n");
- goto rtmp_destroy;
- }
- printf("publish stream success\n");
-
- for (;;) {
- type = SRS_RTMP_TYPE_VIDEO;
- timestamp += 40;
- size = 4096;
- data = (char*)malloc(4096);
-
- if (srs_write_packet(rtmp, type, timestamp, data, size) != 0) {
- goto rtmp_destroy;
- }
- printf("sent packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size);
-
- usleep(40 * 1000);
- }
-
rtmp_destroy:
srs_rtmp_destroy(rtmp);
diff --git a/trunk/src/rtmp/srs_protocol_handshake.hpp b/trunk/src/rtmp/srs_protocol_handshake.hpp
index 6e67c6b5f..4ac93e624 100644
--- a/trunk/src/rtmp/srs_protocol_handshake.hpp
+++ b/trunk/src/rtmp/srs_protocol_handshake.hpp
@@ -34,43 +34,7 @@ class ISrsProtocolReaderWriter;
class SrsComplexHandshake;
class SrsHandshakeBytes;
-/**
-* try complex handshake, if failed, fallback to simple handshake.
-*/
-class SrsSimpleHandshake
-{
-public:
- SrsSimpleHandshake();
- virtual ~SrsSimpleHandshake();
-public:
- /**
- * simple handshake.
- */
- virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
- virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
-};
-
-/**
-* rtmp complex handshake,
-* @see also crtmp(crtmpserver) or librtmp,
-* @see also: http://blog.csdn.net/win_lin/article/details/13006803
-*/
-class SrsComplexHandshake
-{
-public:
- SrsComplexHandshake();
- virtual ~SrsComplexHandshake();
-public:
- /**
- * complex hanshake.
- * @return user must:
- * continue connect app if success,
- * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
- * otherwise, disconnect
- */
- virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
- virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
-};
+#ifdef SRS_SSL
namespace srs
{
@@ -303,4 +267,44 @@ namespace srs
int openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest);
}
+#endif
+
+/**
+* try complex handshake, if failed, fallback to simple handshake.
+*/
+class SrsSimpleHandshake
+{
+public:
+ SrsSimpleHandshake();
+ virtual ~SrsSimpleHandshake();
+public:
+ /**
+ * simple handshake.
+ */
+ virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
+ virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
+};
+
+/**
+* rtmp complex handshake,
+* @see also crtmp(crtmpserver) or librtmp,
+* @see also: http://blog.csdn.net/win_lin/article/details/13006803
+*/
+class SrsComplexHandshake
+{
+public:
+ SrsComplexHandshake();
+ virtual ~SrsComplexHandshake();
+public:
+ /**
+ * complex hanshake.
+ * @return user must:
+ * continue connect app if success,
+ * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
+ * otherwise, disconnect
+ */
+ virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
+ virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
+};
+
#endif
\ No newline at end of file
diff --git a/trunk/src/rtmp/srs_protocol_rtmp.cpp b/trunk/src/rtmp/srs_protocol_rtmp.cpp
index e87183abe..4bbcbd007 100644
--- a/trunk/src/rtmp/srs_protocol_rtmp.cpp
+++ b/trunk/src/rtmp/srs_protocol_rtmp.cpp
@@ -229,7 +229,7 @@ int SrsHandshakeBytes::read_s0s1s2(ISrsProtocolReaderWriter* io)
ssize_t nsize;
- c0c1 = new char[3073];
+ s0s1s2 = new char[3073];
if ((ret = io->read_fully(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) {
srs_warn("read s0s1s2 failed. ret=%d", ret);
return ret;