fix RTMP protocol extended timestamp bug, always trust and use the extended-time…
…stamp for the first chunk of msg
正在显示
3 个修改的文件
包含
43 行增加
和
39 行删除
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR "0" | 32 | #define VERSION_MAJOR "0" |
| 33 | #define VERSION_MINOR "9" | 33 | #define VERSION_MINOR "9" |
| 34 | -#define VERSION_REVISION "86" | 34 | +#define VERSION_REVISION "87" |
| 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION | 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION |
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "srs" | 37 | #define RTMP_SIG_SRS_KEY "srs" |
| @@ -301,7 +301,6 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io) | @@ -301,7 +301,6 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io) | ||
| 301 | skt = io; | 301 | skt = io; |
| 302 | 302 | ||
| 303 | in_chunk_size = out_chunk_size = RTMP_DEFAULT_CHUNK_SIZE; | 303 | in_chunk_size = out_chunk_size = RTMP_DEFAULT_CHUNK_SIZE; |
| 304 | - send_extended_timestamp_for_C3_chunk = true; | ||
| 305 | } | 304 | } |
| 306 | 305 | ||
| 307 | SrsProtocol::~SrsProtocol() | 306 | SrsProtocol::~SrsProtocol() |
| @@ -405,7 +404,7 @@ int SrsProtocol::recv_message(SrsMessage** pmsg) | @@ -405,7 +404,7 @@ int SrsProtocol::recv_message(SrsMessage** pmsg) | ||
| 405 | return ret; | 404 | return ret; |
| 406 | } | 405 | } |
| 407 | 406 | ||
| 408 | - srs_verbose("got a msg, cid=%d, type=%d, size=%d, time=%"PRId64, | 407 | + srs_warn("got a msg, cid=%d, type=%d, size=%d, time=%"PRId64, |
| 409 | msg->header.perfer_cid, msg->header.message_type, msg->header.payload_length, | 408 | msg->header.perfer_cid, msg->header.message_type, msg->header.payload_length, |
| 410 | msg->header.timestamp); | 409 | msg->header.timestamp); |
| 411 | *pmsg = msg; | 410 | *pmsg = msg; |
| @@ -527,7 +526,7 @@ int SrsProtocol::do_send_and_free_message(SrsMessage* msg, SrsPacket* packet) | @@ -527,7 +526,7 @@ int SrsProtocol::do_send_and_free_message(SrsMessage* msg, SrsPacket* packet) | ||
| 527 | // @see: ngx_rtmp_prepare_message | 526 | // @see: ngx_rtmp_prepare_message |
| 528 | // @see: http://blog.csdn.net/win_lin/article/details/13363699 | 527 | // @see: http://blog.csdn.net/win_lin/article/details/13363699 |
| 529 | u_int32_t timestamp = (u_int32_t)msg->header.timestamp; | 528 | u_int32_t timestamp = (u_int32_t)msg->header.timestamp; |
| 530 | - if(send_extended_timestamp_for_C3_chunk && timestamp >= RTMP_EXTENDED_TIMESTAMP){ | 529 | + if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ |
| 531 | pp = (char*)×tamp; | 530 | pp = (char*)×tamp; |
| 532 | *pheader++ = pp[3]; | 531 | *pheader++ = pp[3]; |
| 533 | *pheader++ = pp[2]; | 532 | *pheader++ = pp[2]; |
| @@ -958,8 +957,8 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -958,8 +957,8 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 958 | // the fmt must be 0, a new stream. | 957 | // the fmt must be 0, a new stream. |
| 959 | if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) { | 958 | if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) { |
| 960 | ret = ERROR_RTMP_CHUNK_START; | 959 | ret = ERROR_RTMP_CHUNK_START; |
| 961 | - srs_error("chunk stream is fresh, " | ||
| 962 | - "fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret); | 960 | + srs_error("chunk stream is fresh, fmt must be %d, actual is %d. cid=%d, ret=%d", |
| 961 | + RTMP_FMT_TYPE0, fmt, chunk->cid, ret); | ||
| 963 | return ret; | 962 | return ret; |
| 964 | } | 963 | } |
| 965 | 964 | ||
| @@ -973,7 +972,9 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -973,7 +972,9 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 973 | } | 972 | } |
| 974 | 973 | ||
| 975 | // create msg when new chunk stream start | 974 | // create msg when new chunk stream start |
| 975 | + bool is_first_chunk_of_msg = false; | ||
| 976 | if (!chunk->msg) { | 976 | if (!chunk->msg) { |
| 977 | + is_first_chunk_of_msg = true; | ||
| 977 | chunk->msg = new SrsMessage(); | 978 | chunk->msg = new SrsMessage(); |
| 978 | srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid); | 979 | srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid); |
| 979 | } | 980 | } |
| @@ -992,7 +993,13 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -992,7 +993,13 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 992 | } | 993 | } |
| 993 | char* p = buffer->bytes() + bh_size; | 994 | char* p = buffer->bytes() + bh_size; |
| 994 | 995 | ||
| 995 | - // parse the message header. | 996 | + /** |
| 997 | + * parse the message header. | ||
| 998 | + * 3bytes: timestamp delta, fmt=0,1,2 | ||
| 999 | + * 3bytes: payload length, fmt=0,1 | ||
| 1000 | + * 1bytes: message type, fmt=0,1 | ||
| 1001 | + * 4bytes: stream id, fmt=0 | ||
| 1002 | + */ | ||
| 996 | // see also: ngx_rtmp_recv | 1003 | // see also: ngx_rtmp_recv |
| 997 | if (fmt <= RTMP_FMT_TYPE2) { | 1004 | if (fmt <= RTMP_FMT_TYPE2) { |
| 998 | char* pp = (char*)&chunk->header.timestamp_delta; | 1005 | char* pp = (char*)&chunk->header.timestamp_delta; |
| @@ -1015,7 +1022,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | @@ -1015,7 +1022,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 1015 | // timestamp header’ MUST be present. Otherwise, this value SHOULD be | 1022 | // timestamp header’ MUST be present. Otherwise, this value SHOULD be |
| 1016 | // the entire delta. | 1023 | // the entire delta. |
| 1017 | chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP); | 1024 | chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP); |
| 1018 | - if (chunk->extended_timestamp) { | 1025 | + if (!chunk->extended_timestamp) { |
| 1019 | // Extended timestamp: 0 or 4 bytes | 1026 | // Extended timestamp: 0 or 4 bytes |
| 1020 | // This field MUST be sent when the normal timsestamp is set to | 1027 | // This field MUST be sent when the normal timsestamp is set to |
| 1021 | // 0xffffff, it MUST NOT be sent if the normal timestamp is set to | 1028 | // 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 | @@ -1024,12 +1031,6 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 1024 | // MUST NOT be present. For values greater than or equal to 0xffffff | 1031 | // MUST NOT be present. For values greater than or equal to 0xffffff |
| 1025 | // the normal timestamp field MUST NOT be used and MUST be set to | 1032 | // the normal timestamp field MUST NOT be used and MUST be set to |
| 1026 | // 0xffffff and the extended timestamp MUST be sent. | 1033 | // 0xffffff and the extended timestamp MUST be sent. |
| 1027 | - // | ||
| 1028 | - // if extended timestamp, the timestamp must >= RTMP_EXTENDED_TIMESTAMP | ||
| 1029 | - // we set the timestamp to RTMP_EXTENDED_TIMESTAMP to identify we | ||
| 1030 | - // got an extended timestamp. | ||
| 1031 | - chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP; | ||
| 1032 | - } else { | ||
| 1033 | if (fmt == RTMP_FMT_TYPE0) { | 1034 | if (fmt == RTMP_FMT_TYPE0) { |
| 1034 | // 6.1.2.1. Type 0 | 1035 | // 6.1.2.1. Type 0 |
| 1035 | // For a type-0 chunk, the absolute timestamp of the message is sent | 1036 | // 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 | @@ -1090,7 +1091,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 1090 | } | 1091 | } |
| 1091 | 1092 | ||
| 1092 | // read extended-timestamp | 1093 | // read extended-timestamp |
| 1093 | - if (chunk->extended_timestamp && send_extended_timestamp_for_C3_chunk) { | 1094 | + if (chunk->extended_timestamp) { |
| 1094 | mh_size += 4; | 1095 | mh_size += 4; |
| 1095 | required_size = bh_size + mh_size; | 1096 | required_size = bh_size + mh_size; |
| 1096 | srs_verbose("read header ext time. fmt=%d, ext_time=%d, mh_size=%d", fmt, chunk->extended_timestamp, mh_size); | 1097 | 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 | @@ -1108,14 +1109,35 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz | ||
| 1108 | pp[1] = *p++; | 1109 | pp[1] = *p++; |
| 1109 | pp[0] = *p++; | 1110 | pp[0] = *p++; |
| 1110 | 1111 | ||
| 1111 | - // ffmpeg/librtmp may donot send this filed, need to detect the value. | ||
| 1112 | - // @see also: http://blog.csdn.net/win_lin/article/details/13363699 | ||
| 1113 | - // compare to the chunk timestamp, which is set by chunk message header | ||
| 1114 | - // type 0,1 or 2. | 1112 | + /** |
| 1113 | + * RTMP specification and ffmpeg/librtmp is false, | ||
| 1114 | + * but, adobe changed the specification, so flash/FMLE/FMS always true. | ||
| 1115 | + * default to true to support flash/FMLE/FMS. | ||
| 1116 | + * | ||
| 1117 | + * ffmpeg/librtmp may donot send this filed, need to detect the value. | ||
| 1118 | + * @see also: http://blog.csdn.net/win_lin/article/details/13363699 | ||
| 1119 | + * compare to the chunk timestamp, which is set by chunk message header | ||
| 1120 | + * type 0,1 or 2. | ||
| 1121 | + * | ||
| 1122 | + * @remark, nginx send the extended-timestamp in sequence-header, | ||
| 1123 | + * and timestamp delta in continue C1 chunks, and so compatible with ffmpeg, | ||
| 1124 | + * that is, there is no continue chunks and extended-timestamp in nginx-rtmp. | ||
| 1125 | + * | ||
| 1126 | + * @remark, srs always send the extended-timestamp, to keep simple, | ||
| 1127 | + * and compatible with adobe products. | ||
| 1128 | + */ | ||
| 1115 | u_int32_t chunk_timestamp = chunk->header.timestamp; | 1129 | u_int32_t chunk_timestamp = chunk->header.timestamp; |
| 1116 | - if (chunk_timestamp > RTMP_EXTENDED_TIMESTAMP && chunk_timestamp != timestamp) { | 1130 | + |
| 1131 | + /** | ||
| 1132 | + * if chunk_timestamp<=0, the chunk previous packet has no extended-timestamp, | ||
| 1133 | + * always use the extended timestamp. | ||
| 1134 | + */ | ||
| 1135 | + /** | ||
| 1136 | + * about the is_first_chunk_of_msg. | ||
| 1137 | + * @remark, for the first chunk of message, always use the extended timestamp. | ||
| 1138 | + */ | ||
| 1139 | + if (!is_first_chunk_of_msg && chunk_timestamp > 0 && chunk_timestamp != timestamp) { | ||
| 1117 | mh_size -= 4; | 1140 | mh_size -= 4; |
| 1118 | - send_extended_timestamp_for_C3_chunk = false; | ||
| 1119 | srs_warn("no 4bytes extended timestamp in the continued chunk"); | 1141 | srs_warn("no 4bytes extended timestamp in the continued chunk"); |
| 1120 | } else { | 1142 | } else { |
| 1121 | chunk->header.timestamp = timestamp; | 1143 | chunk->header.timestamp = timestamp; |
| @@ -107,24 +107,6 @@ private: | @@ -107,24 +107,6 @@ private: | ||
| 107 | * value: the request command name | 107 | * value: the request command name |
| 108 | */ | 108 | */ |
| 109 | std::map<double, std::string> requests; | 109 | std::map<double, std::string> requests; |
| 110 | - /** | ||
| 111 | - * RTMP specification and ffmpeg/librtmp is false, | ||
| 112 | - * but, adobe changed the specification, so flash/FMLE/FMS always true. | ||
| 113 | - * default to true to support flash/FMLE/FMS. | ||
| 114 | - * | ||
| 115 | - * ffmpeg/librtmp may donot send this filed, need to detect the value. | ||
| 116 | - * @see also: http://blog.csdn.net/win_lin/article/details/13363699 | ||
| 117 | - * compare to the chunk timestamp, which is set by chunk message header | ||
| 118 | - * type 0,1 or 2. | ||
| 119 | - * | ||
| 120 | - * @remark, nginx send the extended-timestamp in sequence-header, | ||
| 121 | - * and timestamp delta in continue C1 chunks, and so compatible with ffmpeg, | ||
| 122 | - * that is, there is no continue chunks and extended-timestamp in nginx-rtmp. | ||
| 123 | - * | ||
| 124 | - * @remark, srs always send the extended-timestamp, to keep simple, | ||
| 125 | - * and compatible with adobe products. | ||
| 126 | - */ | ||
| 127 | - bool send_extended_timestamp_for_C3_chunk; | ||
| 128 | // peer in | 110 | // peer in |
| 129 | private: | 111 | private: |
| 130 | std::map<int, SrsChunkStream*> chunk_streams; | 112 | std::map<int, SrsChunkStream*> chunk_streams; |
-
请 注册 或 登录 后发表评论