| 1647 | } |
| 1648 | |
| 1649 | int RtmpChunkStream::SerializeMessage(butil::IOBuf* buf, |
| 1650 | const RtmpMessageHeader& mh, |
| 1651 | butil::IOBuf* body) { |
| 1652 | const size_t bh_size = GetBasicHeaderLength(_cs_id); |
| 1653 | if (bh_size == 0) { |
| 1654 | CHECK(false) << "Invalid chunk_stream_id=" << _cs_id; |
| 1655 | return -1; |
| 1656 | } |
| 1657 | // NOTE: body->size() may be longer than mh.message_length; |
| 1658 | uint32_t left_size = mh.message_length; |
| 1659 | CHECK_LE((size_t)left_size, body->size()); |
| 1660 | bool has_extended_ts = false; |
| 1661 | uint32_t timestamp_delta = 0; |
| 1662 | const uint32_t chunk_size_out = connection_context()->_chunk_size_out; |
| 1663 | if (left_size > 0) { |
| 1664 | const uint32_t cur_chunk_size = std::min(chunk_size_out, left_size); |
| 1665 | left_size -= cur_chunk_size; |
| 1666 | char header_buf[32]; // enough |
| 1667 | char* p = header_buf + bh_size; |
| 1668 | RtmpChunkType chunk_type = RTMP_CHUNK_TYPE0; |
| 1669 | if (!_w.last_msg_header.is_valid() || |
| 1670 | mh.stream_id != _w.last_msg_header.stream_id || |
| 1671 | mh.timestamp < _w.last_msg_header.timestamp) { // backward seek |
| 1672 | chunk_type = RTMP_CHUNK_TYPE0; |
| 1673 | timestamp_delta = mh.timestamp; |
| 1674 | uint32_t packed_ts = mh.timestamp; |
| 1675 | if (packed_ts >= 0xFFFFFFu) { |
| 1676 | has_extended_ts = true; |
| 1677 | packed_ts = 0xFFFFFFu; |
| 1678 | } |
| 1679 | WriteBigEndian3Bytes(&p, packed_ts); |
| 1680 | WriteBigEndian3Bytes(&p, mh.message_length); |
| 1681 | *p++ = mh.message_type; |
| 1682 | WriteLittleEndian4Bytes(&p, mh.stream_id); |
| 1683 | } else if (mh.message_length != _w.last_msg_header.message_length || |
| 1684 | mh.message_type != _w.last_msg_header.message_type) { |
| 1685 | chunk_type = RTMP_CHUNK_TYPE1; |
| 1686 | timestamp_delta = mh.timestamp - _w.last_msg_header.timestamp; |
| 1687 | uint32_t packed_ts = timestamp_delta; |
| 1688 | if (packed_ts >= 0xFFFFFFu) { |
| 1689 | has_extended_ts = true; |
| 1690 | packed_ts = 0xFFFFFFu; |
| 1691 | } |
| 1692 | WriteBigEndian3Bytes(&p, packed_ts); |
| 1693 | WriteBigEndian3Bytes(&p, mh.message_length); |
| 1694 | *p++ = mh.message_type; |
| 1695 | } else { |
| 1696 | timestamp_delta = mh.timestamp - _w.last_msg_header.timestamp; |
| 1697 | if (timestamp_delta != _w.last_timestamp_delta) { |
| 1698 | chunk_type = RTMP_CHUNK_TYPE2; |
| 1699 | uint32_t packed_ts = timestamp_delta; |
| 1700 | if (packed_ts >= 0xFFFFFFu) { |
| 1701 | has_extended_ts = true; |
| 1702 | packed_ts = 0xFFFFFFu; |
| 1703 | } |
| 1704 | WriteBigEndian3Bytes(&p, packed_ts); |
| 1705 | } else { |
| 1706 | chunk_type = RTMP_CHUNK_TYPE3; |
no test coverage detected