From 598aaa5c988308d492b8b5137e5bcfff1fe7a286 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 24 Oct 2013 22:29:12 +0800 Subject: [PATCH] detect the video/audio codec, only cache the h264/aac sequence header --- trunk/configure | 2 +- trunk/src/core/srs_core_codec.cpp | 146 +++++++++++++++++++++++++++++ trunk/src/core/srs_core_codec.hpp | 49 ++++++++++ trunk/src/core/srs_core_rtmp.cpp | 2 +- trunk/src/core/srs_core_source.cpp | 14 +-- trunk/src/core/srs_core_source.hpp | 2 + trunk/src/srs/srs.upp | 2 + 7 files changed, 209 insertions(+), 8 deletions(-) create mode 100755 trunk/src/core/srs_core_codec.cpp create mode 100755 trunk/src/core/srs_core_codec.hpp diff --git a/trunk/configure b/trunk/configure index 07f5e62f8..d2512f1a0 100755 --- a/trunk/configure +++ b/trunk/configure @@ -86,7 +86,7 @@ MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" "srs_core_error" "srs_core_conn" "srs_core_client" "srs_core_rtmp" "srs_core_socket" "srs_core_buffer" "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0" - "srs_core_stream" "srs_core_source") + "srs_core_stream" "srs_core_source" "srs_core_codec") MODULE_DIR="src/core" . auto/modules.sh CORE_OBJS="${MODULE_OBJS[@]}" diff --git a/trunk/src/core/srs_core_codec.cpp b/trunk/src/core/srs_core_codec.cpp new file mode 100755 index 000000000..bd445d740 --- /dev/null +++ b/trunk/src/core/srs_core_codec.cpp @@ -0,0 +1,146 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +SrsCodec::SrsCodec() +{ +} + +SrsCodec::~SrsCodec() +{ +} + +bool SrsCodec::video_is_sequence_header(int8_t* data, int size) +{ + // E.4.3.1 VIDEODATA + // Frame Type UB [4] + // Type of video frame. The following values are defined: + // 1 = key frame (for AVC, a seekable frame) + // 2 = inter frame (for AVC, a non-seekable frame) + // 3 = disposable inter frame (H.263 only) + // 4 = generated key frame (reserved for server use only) + // 5 = video info/command frame + // + // AVCPacketType IF CodecID == 7 UI8 + // The following values are defined: + // 0 = AVC sequence header + // 1 = AVC NALU + // 2 = AVC end of sequence (lower level NALU sequence ender is + // not required or supported) + + // sequence header only for h264 + if (!video_is_h264(data, size)) { + return false; + } + + // 2bytes required. + if (size < 2) { + return false; + } + + char frame_type = *(char*)data; + frame_type = (frame_type >> 4) & 0x0F; + + char avc_packet_type = *(char*)(data + 1); + + return frame_type == 1 && avc_packet_type == 0; +} + +bool SrsCodec::audio_is_sequence_header(int8_t* data, int size) +{ + // AACPacketType IF SoundFormat == 10 UI8 + // The following values are defined: + // 0 = AAC sequence header + // 1 = AAC raw + + // sequence header only for aac + if (!audio_is_aac(data, size)) { + return false; + } + + // 2bytes required. + if (size < 2) { + return false; + } + + char aac_packet_type = *(char*)(data + 1); + + return aac_packet_type == 0; +} + +bool SrsCodec::video_is_h264(int8_t* data, int size) +{ + // E.4.3.1 VIDEODATA + // CodecID UB [4] + // Codec Identifier. The following values are defined: + // 2 = Sorenson H.263 + // 3 = Screen video + // 4 = On2 VP6 + // 5 = On2 VP6 with alpha channel + // 6 = Screen video version 2 + // 7 = AVC + + // 1bytes required. + if (size < 1) { + return false; + } + + char codec_id = *(char*)data; + codec_id = codec_id & 0x0F; + + return codec_id == 7; +} + +bool SrsCodec::audio_is_aac(int8_t* data, int size) +{ + // SoundFormat UB [4] + // Format of SoundData. The following values are defined: + // 0 = Linear PCM, platform endian + // 1 = ADPCM + // 2 = MP3 + // 3 = Linear PCM, little endian + // 4 = Nellymoser 16 kHz mono + // 5 = Nellymoser 8 kHz mono + // 6 = Nellymoser + // 7 = G.711 A-law logarithmic PCM + // 8 = G.711 mu-law logarithmic PCM + // 9 = reserved + // 10 = AAC + // 11 = Speex + // 14 = MP3 8 kHz + // 15 = Device-specific sound + // Formats 7, 8, 14, and 15 are reserved. + // AAC is supported in Flash Player 9,0,115,0 and higher. + // Speex is supported in Flash Player 10 and higher. + + // 1bytes required. + if (size < 1) { + return false; + } + + char sound_format = *(char*)data; + sound_format = (sound_format >> 4) & 0x0F; + + return sound_format == 10; +} diff --git a/trunk/src/core/srs_core_codec.hpp b/trunk/src/core/srs_core_codec.hpp new file mode 100755 index 000000000..a16e95a71 --- /dev/null +++ b/trunk/src/core/srs_core_codec.hpp @@ -0,0 +1,49 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SRS_CORE_CODEC_HPP +#define SRS_CORE_CODEC_HPP + +/* +#include +*/ + +#include + +/** +* Annex E. The FLV File Format +*/ +class SrsCodec +{ +public: + SrsCodec(); + virtual ~SrsCodec(); +public: + virtual bool video_is_sequence_header(int8_t* data, int size); + virtual bool audio_is_sequence_header(int8_t* data, int size); +private: + virtual bool video_is_h264(int8_t* data, int size); + virtual bool audio_is_aac(int8_t* data, int size); +}; + +#endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_rtmp.cpp b/trunk/src/core/srs_core_rtmp.cpp index d654df9d1..5441970a3 100755 --- a/trunk/src/core/srs_core_rtmp.cpp +++ b/trunk/src/core/srs_core_rtmp.cpp @@ -173,7 +173,7 @@ int SrsRtmp::handshake() ssize_t nsize; SrsSocket skt(stfd); - // TODO: complex handshake for h264 codec. + // TODO: complex handshake for h264/aac codec. char* c0c1 = new char[1537]; SrsAutoFree(char, c0c1, true); if ((ret = skt.read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { diff --git a/trunk/src/core/srs_core_source.cpp b/trunk/src/core/srs_core_source.cpp index d89b9015e..e39ee300b 100755 --- a/trunk/src/core/srs_core_source.cpp +++ b/trunk/src/core/srs_core_source.cpp @@ -29,6 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #define CONST_MAX_JITTER_MS 500 #define DEFAULT_FRAME_TIME_MS 10 @@ -135,6 +136,7 @@ SrsSource::SrsSource(std::string _stream_url) cache_metadata = NULL; cache_sh_video = NULL; cache_sh_audio = NULL; + codec = new SrsCodec(); } SrsSource::~SrsSource() @@ -149,6 +151,8 @@ SrsSource::~SrsSource() srs_freep(cache_metadata); srs_freep(cache_sh_video); srs_freep(cache_sh_audio); + + srs_freep(codec); } int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata) @@ -227,9 +231,8 @@ int SrsSource::on_audio(SrsCommonMessage* audio) } srs_info("dispatch audio success."); - // TODO: always update the sh. - // TODO: cache last gop. - if (!cache_sh_audio) { + // cache the sequence header if h264 + if (codec->audio_is_sequence_header(msg->payload, msg->size)) { srs_freep(cache_sh_audio); cache_sh_audio = msg->copy(); } @@ -264,9 +267,8 @@ int SrsSource::on_video(SrsCommonMessage* video) } srs_info("dispatch video success."); - // TODO: always update the sh. - // TODO: cache last gop. - if (!cache_sh_video) { + // cache the sequence header if h264 + if (codec->video_is_sequence_header(msg->payload, msg->size)) { srs_freep(cache_sh_video); cache_sh_video = msg->copy(); } diff --git a/trunk/src/core/srs_core_source.hpp b/trunk/src/core/srs_core_source.hpp index 49c797051..40419a9af 100755 --- a/trunk/src/core/srs_core_source.hpp +++ b/trunk/src/core/srs_core_source.hpp @@ -34,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +class SrsCodec; class SrsSource; class SrsCommonMessage; class SrsOnMetaDataPacket; @@ -82,6 +83,7 @@ public: */ static SrsSource* find(std::string stream_url); private: + SrsCodec* codec; std::string stream_url; std::vector consumers; private: diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index 6307a0a4d..e8a64aedb 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -16,6 +16,8 @@ file ..\core\srs_core_client.cpp, ..\core\srs_core_source.hpp, ..\core\srs_core_source.cpp, + ..\core\srs_core_codec.hpp, + ..\core\srs_core_codec.cpp, ..\core\srs_core_rtmp.hpp, ..\core\srs_core_rtmp.cpp, ..\core\srs_core_protocol.hpp,