RTMP: Use extended timestamp as delta when chunk fmt=1/2. v6.0.167 v7.0.37 (#4356)
1. When the chunk message header employs type 1 and type 2, the extended timestamp denotes the time delta. 2. When the DTS (Decoding Time Stamp) experiences a jump and exceeds 16777215, there can be errors in DTS calculation, and if the audio and video delta differs, it may result in audio-video synchronization issues. --------- `TRANS_BY_GPT4` --------- Co-authored-by: 彭治湘 <zuolengchan@douyu.tv> Co-authored-by: Haibo Chen(陈海博) <495810242@qq.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: winlin <winlinvip@gmail.com>
This commit is contained in:
parent
33b0a0fe7d
commit
9b942fafcc
|
|
@ -7,6 +7,7 @@ The changelog for SRS.
|
|||
<a name="v7-changes"></a>
|
||||
|
||||
## SRS 7.0 Changelog
|
||||
* v7.0, 2025-05-29, Merge [#4356](https://github.com/ossrs/srs/pull/4356): RTMP: Use extended timestamp as delta when chunk fmt=1/2. v7.0.37 (#4356)
|
||||
* v7.0, 2025-05-29, Merge [#4363](https://github.com/ossrs/srs/pull/4363): Fix error about TestRtcPublish_HttpFlvPlay. v7.0.36 (#4363)
|
||||
* v7.0, 2025-05-29, Merge [#4362](https://github.com/ossrs/srs/pull/4362): Update VSCode launch configuration to support GDB on Linux and LLDB on macOS. v7.0.35 (#4362)
|
||||
* v7.0, 2025-05-26, Merge [#4359](https://github.com/ossrs/srs/pull/4359): update pion/webrtc to v4. v7.0.34 (#4359)
|
||||
|
|
@ -47,6 +48,7 @@ The changelog for SRS.
|
|||
<a name="v6-changes"></a>
|
||||
|
||||
## SRS 6.0 Changelog
|
||||
* v6.0, 2025-05-29, Merge [#4356](https://github.com/ossrs/srs/pull/4356): RTMP: Use extended timestamp as delta when chunk fmt=1/2. v6.0.167 (#4356)
|
||||
* v6.0, 2025-03-21, Merge [#4303](https://github.com/ossrs/srs/pull/4303): replace values with enums. v6.0.165 (#4303)
|
||||
* v6.0, 2025-03-20, Merge [#4305](https://github.com/ossrs/srs/pull/4305): free sample to prevent memory leak. v6.0.164 (#4305)
|
||||
* v6.0, 2025-03-18, Merge [#4302](https://github.com/ossrs/srs/pull/4302): update geekyeggo/delete-artifact to 5.0.0. v6.0.163 (#4302)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 6
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 166
|
||||
#define VERSION_REVISION 167
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 7
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 36
|
||||
#define VERSION_REVISION 37
|
||||
|
||||
#endif
|
||||
|
|
@ -1032,8 +1032,8 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
// 0x00ffffff), this value MUST be 16777215, and the 'extended
|
||||
// timestamp header' MUST be present. Otherwise, this value SHOULD be
|
||||
// the entire delta.
|
||||
chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
|
||||
if (!chunk->extended_timestamp) {
|
||||
chunk->has_extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
|
||||
if (!chunk->has_extended_timestamp) {
|
||||
// Extended timestamp: 0 or 4 bytes
|
||||
// This field MUST be sent when the normal timsestamp is set to
|
||||
// 0xffffff, it MUST NOT be sent if the normal timestamp is set to
|
||||
|
|
@ -1085,13 +1085,13 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
}
|
||||
} else {
|
||||
// update the timestamp even fmt=3 for first chunk packet
|
||||
if (is_first_chunk_of_msg && !chunk->extended_timestamp) {
|
||||
if (is_first_chunk_of_msg && !chunk->has_extended_timestamp) {
|
||||
chunk->header.timestamp += chunk->header.timestamp_delta;
|
||||
}
|
||||
}
|
||||
|
||||
// read extended-timestamp
|
||||
if (chunk->extended_timestamp) {
|
||||
if (chunk->has_extended_timestamp) {
|
||||
mh_size += 4;
|
||||
if ((err = in_buffer->grow(skt, 4)) != srs_success) {
|
||||
return srs_error_wrap(err, "read 4 bytes ext timestamp");
|
||||
|
|
@ -1127,7 +1127,7 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
* @remark, srs always send the extended-timestamp, to keep simple,
|
||||
* and compatible with adobe products.
|
||||
*/
|
||||
uint32_t chunk_timestamp = (uint32_t)chunk->header.timestamp;
|
||||
uint32_t chunk_extended_timestamp = (uint32_t)chunk->extended_timestamp;
|
||||
|
||||
/**
|
||||
* if chunk_timestamp<=0, the chunk previous packet has no extended-timestamp,
|
||||
|
|
@ -1137,11 +1137,16 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt)
|
|||
* about the is_first_chunk_of_msg.
|
||||
* @remark, for the first chunk of message, always use the extended timestamp.
|
||||
*/
|
||||
if (!is_first_chunk_of_msg && chunk_timestamp > 0 && chunk_timestamp != timestamp) {
|
||||
if (!is_first_chunk_of_msg && chunk_extended_timestamp > 0 && chunk_extended_timestamp != timestamp) {
|
||||
mh_size -= 4;
|
||||
in_buffer->skip(-4);
|
||||
} else {
|
||||
chunk->header.timestamp = timestamp;
|
||||
chunk->extended_timestamp = timestamp;
|
||||
if (fmt == RTMP_FMT_TYPE0) {
|
||||
chunk->header.timestamp = timestamp;
|
||||
} else if (is_first_chunk_of_msg) {
|
||||
chunk->header.timestamp += timestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1439,9 +1444,10 @@ SrsChunkStream::SrsChunkStream(int _cid)
|
|||
{
|
||||
fmt = 0;
|
||||
cid = _cid;
|
||||
extended_timestamp = false;
|
||||
has_extended_timestamp = false;
|
||||
msg = NULL;
|
||||
msg_count = 0;
|
||||
extended_timestamp = 0;
|
||||
}
|
||||
|
||||
SrsChunkStream::~SrsChunkStream()
|
||||
|
|
|
|||
|
|
@ -380,11 +380,16 @@ public:
|
|||
// Cached message header
|
||||
SrsMessageHeader header;
|
||||
// Whether the chunk message header has extended timestamp.
|
||||
bool extended_timestamp;
|
||||
bool has_extended_timestamp;
|
||||
// The partially read message.
|
||||
SrsCommonMessage* msg;
|
||||
// Decoded msg count, to identify whether the chunk stream is fresh.
|
||||
int64_t msg_count;
|
||||
// Because the extended timestamp may be a delta timestamp, it can differ
|
||||
// from the timestamp in the header, so it should be stored as a distinct field
|
||||
// for comparison with the extended timestamp of subsequent chunks.
|
||||
// See https://github.com/ossrs/srs/pull/4356 for details.
|
||||
int32_t extended_timestamp;
|
||||
public:
|
||||
SrsChunkStream(int _cid);
|
||||
virtual ~SrsChunkStream();
|
||||
|
|
|
|||
|
|
@ -1199,6 +1199,373 @@ VOID TEST(ProtocolStackTest, ProtocolRecvVExtTime2Trunk2)
|
|||
EXPECT_EQ(0x00010203, msg->header.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 2 audio and video packet, fmt 1/2
|
||||
* first audio packet: dts:10000
|
||||
* first video packet: dts:11000
|
||||
* second audio packet: dts : 16787216 delta: 16777216
|
||||
* second video packet: dts : 16787216 delta: 16776216
|
||||
*/
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvAVExtTimedeltaStream)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
MockBufferIO bio;
|
||||
SrsProtocol proto(&bio);
|
||||
|
||||
// audio message
|
||||
uint8_t audio_data1[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x03, // fmt 0
|
||||
0x00, 0x27, 0x10, // timestamp 10000
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x08, // message_type
|
||||
0x00, 0x00, 0x00, 0x00, // stream_id
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
uint8_t audio_data2[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x43, // fmt 1
|
||||
0xff, 0xff, 0xff, // means extended timestamp
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x08, // message_type
|
||||
0x01, 0x00, 0x00, 0x00, // extended timestamp delta:16777216
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
// video message
|
||||
uint8_t video_data1[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x04, // fmt 0
|
||||
0x00, 0x2a, 0xf8, // timestamp 11000
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x09, // message_type
|
||||
0x00, 0x00, 0x00, 0x01, // stream_id
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
uint8_t video_data2[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x44, // fmt 1
|
||||
0xff, 0xff, 0xff, // means extended timestamp
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x09, // message_type
|
||||
0x00, 0xff, 0xfc, 0x18, // extended timestamp delta:16776216
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)audio_data1, sizeof(audio_data1));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_audio());
|
||||
EXPECT_EQ(0x00002710, msg->header.timestamp);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)video_data1, sizeof(video_data1));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_video());
|
||||
EXPECT_EQ(0x00002af8, msg->header.timestamp);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)audio_data2, sizeof(audio_data2));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_audio());
|
||||
EXPECT_EQ(0x01002710, msg->header.timestamp);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)video_data2, sizeof(video_data2));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_video());
|
||||
EXPECT_EQ(0x01002710, msg->header.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 2 audio packet, fmt 1/2
|
||||
* first audio packet: dts:10000
|
||||
* second audio packet: dts : 16787216 delta: 16777216
|
||||
*/
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvAVExtTimedeltaAudio)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
MockBufferIO bio;
|
||||
SrsProtocol proto(&bio);
|
||||
|
||||
// audio message
|
||||
uint8_t audio_data1[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x03, // fmt 0
|
||||
0x00, 0x27, 0x10, // timestamp 10000
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x08, // message_type
|
||||
0x00, 0x00, 0x00, 0x00, // stream_id
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
uint8_t audio_data2[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x43, // fmt 1
|
||||
0xff, 0xff, 0xff, // means extended timestamp
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x08, // message_type
|
||||
0x01, 0x00, 0x00, 0x00, // extended timestamp delta:16777216
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)audio_data1, sizeof(audio_data1));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_audio());
|
||||
EXPECT_EQ(0x00002710, msg->header.timestamp);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)audio_data2, sizeof(audio_data2));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_audio());
|
||||
EXPECT_EQ(0x01002710, msg->header.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 2 video packet, fmt 1/2
|
||||
* first video packet: dts:11000
|
||||
* second video packet: dts : 16787216 delta: 16776216
|
||||
*/
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvAVExtTimedeltaVideo)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
MockBufferIO bio;
|
||||
SrsProtocol proto(&bio);
|
||||
|
||||
// video message
|
||||
uint8_t video_data1[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x04, // fmt 0
|
||||
0x00, 0x2a, 0xf8, // timestamp 11000
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x09, // message_type
|
||||
0x00, 0x00, 0x00, 0x01, // stream_id
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
uint8_t video_data2[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x44, // fmt 1
|
||||
0xff, 0xff, 0xff, // means extended timestamp
|
||||
0x00, 0x00, 0x80, // length, 128
|
||||
0x09, // message_type
|
||||
0x00, 0xff, 0xfc, 0x18, // extended timestamp delta:16776216
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
};
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)video_data1, sizeof(video_data1));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_video());
|
||||
EXPECT_EQ(0x00002af8, msg->header.timestamp);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)video_data2, sizeof(video_data2));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_video());
|
||||
EXPECT_EQ(0x01002710, msg->header.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 2 video packet, fmt 3
|
||||
* first video packet: dts:11000
|
||||
* second video packet: dts : 16787216 delta: 16776216
|
||||
*/
|
||||
VOID TEST(ProtocolStackTest, ProtocolRecvAVExtTimedeltaVideoFmt3)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
MockBufferIO bio;
|
||||
SrsProtocol proto(&bio);
|
||||
|
||||
// video message
|
||||
uint8_t video_data1[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x04, // fmt 0
|
||||
0x00, 0x2a, 0xf8, // timestamp 11000
|
||||
0x00, 0x01, 0x00, // length, 256
|
||||
0x09, // message_type
|
||||
0x00, 0x00, 0x00, 0x01, // stream_id
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
// chunk #2
|
||||
0xC4, // fmt 3
|
||||
/*next chunk.*/ 0x61, 0x79, 0x65, 0x72,
|
||||
0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e,
|
||||
0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70,
|
||||
0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69,
|
||||
0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65,
|
||||
0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
uint8_t video_data2[] = {
|
||||
// 12bytes header, 1byts chunk header, 11bytes msg heder
|
||||
0x44, // fmt 1
|
||||
0xff, 0xff, 0xff, // means extended timestamp
|
||||
0x00, 0x01, 0x10, // length, 272
|
||||
0x09, // message_type
|
||||
0x00, 0xff, 0xfc, 0x18, // extended timestamp delta:16776216
|
||||
// msg payload start
|
||||
0x02, 0x00, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c,
|
||||
0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c,
|
||||
0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00,
|
||||
0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65,
|
||||
0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c,
|
||||
// chunk #2
|
||||
0xC4, // fmt 3
|
||||
0x00, 0xff, 0xfc, 0x18, // extended timestamp delta:16776216
|
||||
/*next chunk.*/ 0x61, 0x79, 0x65, 0x72,
|
||||
0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e,
|
||||
0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70,
|
||||
0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69,
|
||||
0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65,
|
||||
0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// chunk #2
|
||||
0xC4,
|
||||
/*next chunk.*/
|
||||
0x00, 0xff, 0xfc, 0x18, // extended timestamp delta:16776216
|
||||
0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e
|
||||
};
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)video_data1, sizeof(video_data1));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_video());
|
||||
EXPECT_EQ(0x00002af8, msg->header.timestamp);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
bio.in_buffer.append((char*)video_data2, sizeof(video_data2));
|
||||
SrsCommonMessage* msg_raw = NULL;
|
||||
HELPER_ASSERT_SUCCESS(proto.recv_message(&msg_raw));
|
||||
SrsUniquePtr<SrsCommonMessage> msg(msg_raw);
|
||||
EXPECT_TRUE(msg->header.is_video());
|
||||
EXPECT_EQ(0x01002710, msg->header.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* a video message, in 2 chunks packet.
|
||||
* use 1B chunk header, min chunk id is 2.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user