mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
fix RTMP protocol extended timestamp bug, always trust and use the extended-timestamp for the first chunk of msg
This commit is contained in:
parent
37476df704
commit
0945c2b441
3 changed files with 43 additions and 39 deletions
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR "0"
|
#define VERSION_MAJOR "0"
|
||||||
#define VERSION_MINOR "9"
|
#define VERSION_MINOR "9"
|
||||||
#define VERSION_REVISION "86"
|
#define VERSION_REVISION "87"
|
||||||
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "srs"
|
#define RTMP_SIG_SRS_KEY "srs"
|
||||||
|
|
|
@ -301,7 +301,6 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io)
|
||||||
skt = io;
|
skt = io;
|
||||||
|
|
||||||
in_chunk_size = out_chunk_size = RTMP_DEFAULT_CHUNK_SIZE;
|
in_chunk_size = out_chunk_size = RTMP_DEFAULT_CHUNK_SIZE;
|
||||||
send_extended_timestamp_for_C3_chunk = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsProtocol::~SrsProtocol()
|
SrsProtocol::~SrsProtocol()
|
||||||
|
@ -405,7 +404,7 @@ int SrsProtocol::recv_message(SrsMessage** pmsg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_verbose("got a msg, cid=%d, type=%d, size=%d, time=%"PRId64,
|
srs_warn("got a msg, cid=%d, type=%d, size=%d, time=%"PRId64,
|
||||||
msg->header.perfer_cid, msg->header.message_type, msg->header.payload_length,
|
msg->header.perfer_cid, msg->header.message_type, msg->header.payload_length,
|
||||||
msg->header.timestamp);
|
msg->header.timestamp);
|
||||||
*pmsg = msg;
|
*pmsg = msg;
|
||||||
|
@ -527,7 +526,7 @@ int SrsProtocol::do_send_and_free_message(SrsMessage* msg, SrsPacket* packet)
|
||||||
// @see: ngx_rtmp_prepare_message
|
// @see: ngx_rtmp_prepare_message
|
||||||
// @see: http://blog.csdn.net/win_lin/article/details/13363699
|
// @see: http://blog.csdn.net/win_lin/article/details/13363699
|
||||||
u_int32_t timestamp = (u_int32_t)msg->header.timestamp;
|
u_int32_t timestamp = (u_int32_t)msg->header.timestamp;
|
||||||
if(send_extended_timestamp_for_C3_chunk && timestamp >= RTMP_EXTENDED_TIMESTAMP){
|
if(timestamp >= RTMP_EXTENDED_TIMESTAMP){
|
||||||
pp = (char*)×tamp;
|
pp = (char*)×tamp;
|
||||||
*pheader++ = pp[3];
|
*pheader++ = pp[3];
|
||||||
*pheader++ = pp[2];
|
*pheader++ = pp[2];
|
||||||
|
@ -958,8 +957,8 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
// the fmt must be 0, a new stream.
|
// the fmt must be 0, a new stream.
|
||||||
if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) {
|
if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) {
|
||||||
ret = ERROR_RTMP_CHUNK_START;
|
ret = ERROR_RTMP_CHUNK_START;
|
||||||
srs_error("chunk stream is fresh, "
|
srs_error("chunk stream is fresh, fmt must be %d, actual is %d. cid=%d, ret=%d",
|
||||||
"fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret);
|
RTMP_FMT_TYPE0, fmt, chunk->cid, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,7 +972,9 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
}
|
}
|
||||||
|
|
||||||
// create msg when new chunk stream start
|
// create msg when new chunk stream start
|
||||||
|
bool is_first_chunk_of_msg = false;
|
||||||
if (!chunk->msg) {
|
if (!chunk->msg) {
|
||||||
|
is_first_chunk_of_msg = true;
|
||||||
chunk->msg = new SrsMessage();
|
chunk->msg = new SrsMessage();
|
||||||
srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid);
|
srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid);
|
||||||
}
|
}
|
||||||
|
@ -992,7 +993,13 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
}
|
}
|
||||||
char* p = buffer->bytes() + bh_size;
|
char* p = buffer->bytes() + bh_size;
|
||||||
|
|
||||||
// parse the message header.
|
/**
|
||||||
|
* parse the message header.
|
||||||
|
* 3bytes: timestamp delta, fmt=0,1,2
|
||||||
|
* 3bytes: payload length, fmt=0,1
|
||||||
|
* 1bytes: message type, fmt=0,1
|
||||||
|
* 4bytes: stream id, fmt=0
|
||||||
|
*/
|
||||||
// see also: ngx_rtmp_recv
|
// see also: ngx_rtmp_recv
|
||||||
if (fmt <= RTMP_FMT_TYPE2) {
|
if (fmt <= RTMP_FMT_TYPE2) {
|
||||||
char* pp = (char*)&chunk->header.timestamp_delta;
|
char* pp = (char*)&chunk->header.timestamp_delta;
|
||||||
|
@ -1015,7 +1022,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
// timestamp header’ MUST be present. Otherwise, this value SHOULD be
|
// timestamp header’ MUST be present. Otherwise, this value SHOULD be
|
||||||
// the entire delta.
|
// the entire delta.
|
||||||
chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
|
chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
|
||||||
if (chunk->extended_timestamp) {
|
if (!chunk->extended_timestamp) {
|
||||||
// Extended timestamp: 0 or 4 bytes
|
// Extended timestamp: 0 or 4 bytes
|
||||||
// This field MUST be sent when the normal timsestamp is set to
|
// 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
|
// 0xffffff, it MUST NOT be sent if the normal timestamp is set to
|
||||||
|
@ -1024,12 +1031,6 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
// MUST NOT be present. For values greater than or equal to 0xffffff
|
// MUST NOT be present. For values greater than or equal to 0xffffff
|
||||||
// the normal timestamp field MUST NOT be used and MUST be set to
|
// the normal timestamp field MUST NOT be used and MUST be set to
|
||||||
// 0xffffff and the extended timestamp MUST be sent.
|
// 0xffffff and the extended timestamp MUST be sent.
|
||||||
//
|
|
||||||
// if extended timestamp, the timestamp must >= RTMP_EXTENDED_TIMESTAMP
|
|
||||||
// we set the timestamp to RTMP_EXTENDED_TIMESTAMP to identify we
|
|
||||||
// got an extended timestamp.
|
|
||||||
chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP;
|
|
||||||
} else {
|
|
||||||
if (fmt == RTMP_FMT_TYPE0) {
|
if (fmt == RTMP_FMT_TYPE0) {
|
||||||
// 6.1.2.1. Type 0
|
// 6.1.2.1. Type 0
|
||||||
// For a type-0 chunk, the absolute timestamp of the message is sent
|
// For a type-0 chunk, the absolute timestamp of the message is sent
|
||||||
|
@ -1090,7 +1091,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
}
|
}
|
||||||
|
|
||||||
// read extended-timestamp
|
// read extended-timestamp
|
||||||
if (chunk->extended_timestamp && send_extended_timestamp_for_C3_chunk) {
|
if (chunk->extended_timestamp) {
|
||||||
mh_size += 4;
|
mh_size += 4;
|
||||||
required_size = bh_size + mh_size;
|
required_size = bh_size + mh_size;
|
||||||
srs_verbose("read header ext time. fmt=%d, ext_time=%d, mh_size=%d", fmt, chunk->extended_timestamp, mh_size);
|
srs_verbose("read header ext time. fmt=%d, ext_time=%d, mh_size=%d", fmt, chunk->extended_timestamp, mh_size);
|
||||||
|
@ -1108,14 +1109,35 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
pp[1] = *p++;
|
pp[1] = *p++;
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
|
|
||||||
// ffmpeg/librtmp may donot send this filed, need to detect the value.
|
/**
|
||||||
// @see also: http://blog.csdn.net/win_lin/article/details/13363699
|
* RTMP specification and ffmpeg/librtmp is false,
|
||||||
// compare to the chunk timestamp, which is set by chunk message header
|
* but, adobe changed the specification, so flash/FMLE/FMS always true.
|
||||||
// type 0,1 or 2.
|
* default to true to support flash/FMLE/FMS.
|
||||||
|
*
|
||||||
|
* ffmpeg/librtmp may donot send this filed, need to detect the value.
|
||||||
|
* @see also: http://blog.csdn.net/win_lin/article/details/13363699
|
||||||
|
* compare to the chunk timestamp, which is set by chunk message header
|
||||||
|
* type 0,1 or 2.
|
||||||
|
*
|
||||||
|
* @remark, nginx send the extended-timestamp in sequence-header,
|
||||||
|
* and timestamp delta in continue C1 chunks, and so compatible with ffmpeg,
|
||||||
|
* that is, there is no continue chunks and extended-timestamp in nginx-rtmp.
|
||||||
|
*
|
||||||
|
* @remark, srs always send the extended-timestamp, to keep simple,
|
||||||
|
* and compatible with adobe products.
|
||||||
|
*/
|
||||||
u_int32_t chunk_timestamp = chunk->header.timestamp;
|
u_int32_t chunk_timestamp = chunk->header.timestamp;
|
||||||
if (chunk_timestamp > RTMP_EXTENDED_TIMESTAMP && chunk_timestamp != timestamp) {
|
|
||||||
|
/**
|
||||||
|
* if chunk_timestamp<=0, the chunk previous packet has no extended-timestamp,
|
||||||
|
* always use the extended timestamp.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
mh_size -= 4;
|
mh_size -= 4;
|
||||||
send_extended_timestamp_for_C3_chunk = false;
|
|
||||||
srs_warn("no 4bytes extended timestamp in the continued chunk");
|
srs_warn("no 4bytes extended timestamp in the continued chunk");
|
||||||
} else {
|
} else {
|
||||||
chunk->header.timestamp = timestamp;
|
chunk->header.timestamp = timestamp;
|
||||||
|
|
|
@ -107,24 +107,6 @@ private:
|
||||||
* value: the request command name
|
* value: the request command name
|
||||||
*/
|
*/
|
||||||
std::map<double, std::string> requests;
|
std::map<double, std::string> requests;
|
||||||
/**
|
|
||||||
* RTMP specification and ffmpeg/librtmp is false,
|
|
||||||
* but, adobe changed the specification, so flash/FMLE/FMS always true.
|
|
||||||
* default to true to support flash/FMLE/FMS.
|
|
||||||
*
|
|
||||||
* ffmpeg/librtmp may donot send this filed, need to detect the value.
|
|
||||||
* @see also: http://blog.csdn.net/win_lin/article/details/13363699
|
|
||||||
* compare to the chunk timestamp, which is set by chunk message header
|
|
||||||
* type 0,1 or 2.
|
|
||||||
*
|
|
||||||
* @remark, nginx send the extended-timestamp in sequence-header,
|
|
||||||
* and timestamp delta in continue C1 chunks, and so compatible with ffmpeg,
|
|
||||||
* that is, there is no continue chunks and extended-timestamp in nginx-rtmp.
|
|
||||||
*
|
|
||||||
* @remark, srs always send the extended-timestamp, to keep simple,
|
|
||||||
* and compatible with adobe products.
|
|
||||||
*/
|
|
||||||
bool send_extended_timestamp_for_C3_chunk;
|
|
||||||
// peer in
|
// peer in
|
||||||
private:
|
private:
|
||||||
std::map<int, SrsChunkStream*> chunk_streams;
|
std::map<int, SrsChunkStream*> chunk_streams;
|
||||||
|
|
Loading…
Reference in a new issue