diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index c714eac8c4..9817cae300 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -145,6 +145,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_RTSP_TOKEN_NOT_NORMAL 2042 #define ERROR_RTSP_REQUEST_HEADER_EOF 2043 #define ERROR_RTP_HEADER_CORRUPT 2044 +#define ERROR_RTP_TYPE96_CORRUPT 2045 +#define ERROR_RTP_TYPE97_CORRUPT 2046 // // system control message, // not an error, but special control logic. diff --git a/trunk/src/protocol/srs_rtsp_stack.cpp b/trunk/src/protocol/srs_rtsp_stack.cpp index 0f0c2b7fc6..74374b135f 100644 --- a/trunk/src/protocol/srs_rtsp_stack.cpp +++ b/trunk/src/protocol/srs_rtsp_stack.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include #include +#include #ifdef SRS_AUTO_STREAM_CASTER @@ -133,6 +134,7 @@ SrsRtpPacket::SrsRtpPacket() ssrc = 0; payload = new SrsSimpleBuffer(); + audio_samples = new SrsCodecSample(); chunked = false; completed = false; } @@ -140,6 +142,7 @@ SrsRtpPacket::SrsRtpPacket() SrsRtpPacket::~SrsRtpPacket() { srs_freep(payload); + srs_freep(audio_samples); } void SrsRtpPacket::copy(SrsRtpPacket* src) @@ -156,22 +159,28 @@ void SrsRtpPacket::copy(SrsRtpPacket* src) chunked = src->chunked; completed = src->completed; + audio_samples = new SrsCodecSample(); } void SrsRtpPacket::reap(SrsRtpPacket* src) { copy(src); + srs_freep(payload); payload = src->payload; src->payload = NULL; + + srs_freep(audio_samples); + audio_samples = src->audio_samples; + src->audio_samples = NULL; } int SrsRtpPacket::decode(SrsStream* stream) { int ret = ERROR_SUCCESS; - // 12bytes header, atleast 2bytes content. - if (!stream->require(14)) { + // 12bytes header + if (!stream->require(12)) { ret = ERROR_RTP_HEADER_CORRUPT; srs_error("rtsp: rtp header corrupt. ret=%d", ret); return ret; @@ -191,6 +200,92 @@ int SrsRtpPacket::decode(SrsStream* stream) timestamp = stream->read_4bytes(); ssrc = stream->read_4bytes(); + // video codec. + if (payload_type == 96) { + return decode_96(stream); + } else if (payload_type == 97) { + return decode_97(stream); + } + + return ret; +} + +int SrsRtpPacket::decode_97(SrsStream* stream) +{ + int ret = ERROR_SUCCESS; + + // atleast 2bytes content. + if (!stream->require(2)) { + ret = ERROR_RTP_TYPE97_CORRUPT; + srs_error("rtsp: rtp type97 corrupt. ret=%d", ret); + return ret; + } + + int8_t hasv = stream->read_1bytes(); + int8_t lasv = stream->read_1bytes(); + u_int16_t au_size = ((hasv << 5) & 0xE0) | ((lasv >> 3) & 0x1f); + + if (!stream->require(au_size)) { + ret = ERROR_RTP_TYPE97_CORRUPT; + srs_error("rtsp: rtp type97 au_size corrupt. ret=%d", ret); + return ret; + } + + int nb_samples = au_size / 2; + int guess_sample_size = (stream->size() - stream->pos() - au_size) / nb_samples; + int required_size = 0; + + // append left bytes to payload. + payload->append( + stream->data() + stream->pos() + au_size, + stream->size() - stream->pos() - au_size + ); + char* p = payload->bytes(); + + for (int i = 0; i < au_size; i += 2) { + hasv = stream->read_1bytes(); + lasv = stream->read_1bytes(); + + u_int16_t sample_size = ((hasv << 5) & 0xE0) | ((lasv >> 3) & 0x1f); + if (sample_size != guess_sample_size) { + // guess the size lost 0x100. + if (guess_sample_size == (sample_size | 0x100)) { + sample_size = guess_sample_size; + } + } + + char* sample = p + required_size; + required_size += sample_size; + + if (!stream->require(required_size)) { + ret = ERROR_RTP_TYPE97_CORRUPT; + srs_error("rtsp: rtp type97 samples corrupt. ret=%d", ret); + return ret; + } + + if ((ret = audio_samples->add_sample_unit(sample, sample_size)) != ERROR_SUCCESS) { + srs_error("rtsp: rtp type97 add sample failed. ret=%d", ret); + return ret; + } + } + + // parsed ok. + completed = true; + + return ret; +} + +int SrsRtpPacket::decode_96(SrsStream* stream) +{ + int ret = ERROR_SUCCESS; + + // atleast 2bytes content. + if (!stream->require(2)) { + ret = ERROR_RTP_TYPE96_CORRUPT; + srs_error("rtsp: rtp type96 corrupt. ret=%d", ret); + return ret; + } + // frame type // 0... .... reserverd // .11. .... NALU[0]&0x60 diff --git a/trunk/src/protocol/srs_rtsp_stack.hpp b/trunk/src/protocol/srs_rtsp_stack.hpp index 1cd1adcc35..da7a1af541 100644 --- a/trunk/src/protocol/srs_rtsp_stack.hpp +++ b/trunk/src/protocol/srs_rtsp_stack.hpp @@ -39,6 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsStream; class SrsSimpleBuffer; +class SrsCodecSample; class ISrsProtocolReaderWriter; // rtsp specification @@ -292,6 +293,11 @@ class SrsRtpPacket // normal message always completed. // while chunked completed when the last chunk arriaved. bool completed; + + /** + * the audio samples, one rtp packets may contains multiple audio samples. + */ + SrsCodecSample* audio_samples; public: SrsRtpPacket(); virtual ~SrsRtpPacket(); @@ -308,6 +314,9 @@ class SrsRtpPacket * decode rtp packet from stream. */ virtual int decode(SrsStream* stream); +private: + virtual int decode_97(SrsStream* stream); + virtual int decode_96(SrsStream* stream); }; /**