diff --git a/trunk/configure b/trunk/configure index c80250245..df8d863d7 100755 --- a/trunk/configure +++ b/trunk/configure @@ -167,7 +167,7 @@ ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) MODULE_FILES=("srs_protocol_amf0" "srs_protocol_io" "srs_rtmp_stack" "srs_rtmp_handshake" "srs_protocol_utility" "srs_rtmp_msg_array" "srs_protocol_stream" "srs_raw_avc" "srs_rtsp_stack" "srs_http_stack" "srs_protocol_kbps" "srs_protocol_json" - "srs_kafka_stack") + "srs_kafka_stack" "srs_protocol_format") PROTOCOL_INCS="src/protocol"; MODULE_DIR=${PROTOCOL_INCS} . auto/modules.sh PROTOCOL_OBJS="${MODULE_OBJS[@]}" # diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj index 3ea84eaba..e404ce5ab 100644 --- a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj @@ -116,6 +116,7 @@ 3C82802C1BAFF8CC004A1794 /* srs_kafka_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C82802A1BAFF8CC004A1794 /* srs_kafka_stack.cpp */; }; 3C8CE01E1C3F482100548CC6 /* srs_app_hourglass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C8CE01D1C3F482100548CC6 /* srs_app_hourglass.cpp */; }; 3C9F82221E4ECA8200F5B2D2 /* srs_app_dash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C9F82201E4ECA8200F5B2D2 /* srs_app_dash.cpp */; }; + 3C9F82251E4F5D2A00F5B2D2 /* srs_protocol_format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C9F82231E4F5D2A00F5B2D2 /* srs_protocol_format.cpp */; }; 3CA432A81E3F46DD001DA0C6 /* srs_kernel_io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3CA432A61E3F46DD001DA0C6 /* srs_kernel_io.cpp */; }; 3CA432AB1E40AEBC001DA0C6 /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 3CA432A91E40AEBC001DA0C6 /* Makefile */; }; 3CA432AC1E40AEBC001DA0C6 /* srs_ingest_mp4.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CA432AA1E40AEBC001DA0C6 /* srs_ingest_mp4.c */; }; @@ -409,6 +410,8 @@ 3C8CE01D1C3F482100548CC6 /* srs_app_hourglass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_hourglass.cpp; path = ../../../src/app/srs_app_hourglass.cpp; sourceTree = ""; }; 3C9F82201E4ECA8200F5B2D2 /* srs_app_dash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_dash.cpp; path = ../../../src/app/srs_app_dash.cpp; sourceTree = ""; }; 3C9F82211E4ECA8200F5B2D2 /* srs_app_dash.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_dash.hpp; path = ../../../src/app/srs_app_dash.hpp; sourceTree = ""; }; + 3C9F82231E4F5D2A00F5B2D2 /* srs_protocol_format.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_format.cpp; path = ../../../src/protocol/srs_protocol_format.cpp; sourceTree = ""; }; + 3C9F82241E4F5D2A00F5B2D2 /* srs_protocol_format.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_format.hpp; path = ../../../src/protocol/srs_protocol_format.hpp; sourceTree = ""; }; 3CA432A61E3F46DD001DA0C6 /* srs_kernel_io.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_kernel_io.cpp; path = ../../../src/kernel/srs_kernel_io.cpp; sourceTree = ""; }; 3CA432A71E3F46DD001DA0C6 /* srs_kernel_io.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_kernel_io.hpp; path = ../../../src/kernel/srs_kernel_io.hpp; sourceTree = ""; }; 3CA432A91E40AEBC001DA0C6 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = ../../../research/librtmp/Makefile; sourceTree = ""; }; @@ -571,6 +574,8 @@ 3C82802B1BAFF8CC004A1794 /* srs_kafka_stack.hpp */, 3C12322F1AAE81A400CE8F6C /* srs_protocol_amf0.cpp */, 3C1232301AAE81A400CE8F6C /* srs_protocol_amf0.hpp */, + 3C9F82231E4F5D2A00F5B2D2 /* srs_protocol_format.cpp */, + 3C9F82241E4F5D2A00F5B2D2 /* srs_protocol_format.hpp */, 3C1232351AAE81A400CE8F6C /* srs_protocol_io.cpp */, 3C1232361AAE81A400CE8F6C /* srs_protocol_io.hpp */, 3C0D422C1B87165900C2508B /* srs_protocol_json.cpp */, @@ -1037,6 +1042,7 @@ 3C1232411AAE81A400CE8F6C /* srs_raw_avc.cpp in Sources */, 3C1232491AAE81A400CE8F6C /* srs_protocol_utility.cpp in Sources */, 3C663F191AB0155100286D8B /* srs_publish.c in Sources */, + 3C9F82251E4F5D2A00F5B2D2 /* srs_protocol_format.cpp in Sources */, 3C0E1B8D1B0F5ADF003ADEF7 /* srs_http_stack.cpp in Sources */, 3C1232A01AAE81D900CE8F6C /* srs_app_http_client.cpp in Sources */, 3C689F981AB6AAAC00C9CEEE /* key.c in Sources */, diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index e54555d11..73cb1d57e 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -50,6 +50,7 @@ using namespace std; #include #include #include +#include // drop the segment when duration of ts too small. #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 @@ -1117,13 +1118,12 @@ SrsHls::SrsHls() { req = NULL; hub = NULL; + format = NULL; enabled = false; disposable = false; last_update_time = 0; - codec = new SrsAvcAacCodec(); - sample = new SrsCodecSample(); jitter = new SrsRtmpJitter(); muxer = new SrsHlsMuxer(); @@ -1135,8 +1135,6 @@ SrsHls::SrsHls() SrsHls::~SrsHls() { - srs_freep(codec); - srs_freep(sample); srs_freep(jitter); srs_freep(muxer); @@ -1188,12 +1186,13 @@ int SrsHls::cycle() return ret; } -int SrsHls::initialize(SrsOriginHub* h, SrsRequest* r) +int SrsHls::initialize(SrsOriginHub* h, SrsFormat* f, SrsRequest* r) { int ret = ERROR_SUCCESS; hub = h; req = r; + format = f; if ((ret = muxer->initialize()) != ERROR_SUCCESS) { return ret; diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index dc856266c..ec50c1523 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -36,12 +36,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +class SrsFormat; class SrsSharedPtrMessage; -class SrsCodecSample; class SrsAmf0Object; class SrsRtmpJitter; class SrsTSMuxer; -class SrsAvcAacCodec; class SrsRequest; class SrsPithyPrint; class SrsSource; @@ -343,8 +342,7 @@ private: }; /** -* delivery RTMP stream to HLS(m3u8 and ts), -* SrsHls provides interface with SrsSource. +* Transmux RTMP stream to HLS(m3u8 and ts). * TODO: FIXME: add utest for hls. */ class SrsHls @@ -359,8 +357,7 @@ private: int64_t last_update_time; private: SrsOriginHub* hub; - SrsAvcAacCodec* codec; - SrsCodecSample* sample; + SrsFormat* format; SrsRtmpJitter* jitter; SrsPithyPrint* pprint; /** @@ -387,7 +384,7 @@ public: /** * initialize the hls by handler and source. */ - virtual int initialize(SrsOriginHub* h, SrsRequest* r); + virtual int initialize(SrsOriginHub* h, SrsFormat* f, SrsRequest* r); /** * publish stream event, continue to write the m3u8, * for the muxer object not destroyed. diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index f0f51597c..3b4b1fd91 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -48,6 +48,7 @@ using namespace std; #include #include #include +#include #define CONST_MAX_JITTER_MS 250 #define CONST_MAX_JITTER_MS_NEG -250 @@ -853,6 +854,7 @@ SrsOriginHub::SrsOriginHub() hds = new SrsHds(); #endif ng_exec = new SrsNgExec(); + format = new SrsFormat(); _srs_config->subscribe(this); } @@ -871,6 +873,7 @@ SrsOriginHub::~SrsOriginHub() } srs_freep(ng_exec); + srs_freep(format); srs_freep(hls); srs_freep(dash); srs_freep(dvr); @@ -889,7 +892,11 @@ int SrsOriginHub::initialize(SrsSource* s, SrsRequest* r) req = r; source = s; - if ((ret = hls->initialize(this, req)) != ERROR_SUCCESS) { + if ((ret = format->initialize()) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = hls->initialize(this, format, req)) != ERROR_SUCCESS) { return ret; } @@ -924,10 +931,15 @@ int SrsOriginHub::cycle() return ret; } -int SrsOriginHub::on_meta_data(SrsSharedPtrMessage* shared_metadata) +int SrsOriginHub::on_meta_data(SrsSharedPtrMessage* shared_metadata, SrsOnMetaDataPacket* packet) { int ret = ERROR_SUCCESS; + if ((ret = format->on_metadata(packet)) != ERROR_SUCCESS) { + srs_error("Codec parse metadata failed, ret=%d", ret); + return ret; + } + // copy to all forwarders if (true) { std::vector::iterator it; @@ -954,6 +966,11 @@ int SrsOriginHub::on_audio(SrsSharedPtrMessage* shared_audio) SrsSharedPtrMessage* msg = shared_audio; + if ((ret = format->on_audio(msg)) != ERROR_SUCCESS) { + srs_error("Codec parse audio failed, ret=%d", ret); + return ret; + } + if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) { // apply the error strategy for hls. // @see https://github.com/ossrs/srs/issues/264 @@ -1027,6 +1044,11 @@ int SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_h SrsSharedPtrMessage* msg = shared_video; + if ((ret = format->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) { + srs_error("Codec parse video failed, ret=%d", ret); + return ret; + } + if ((ret = hls->on_video(msg, is_sequence_header)) != ERROR_SUCCESS) { // apply the error strategy for hls. // @see https://github.com/ossrs/srs/issues/264 @@ -2048,7 +2070,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata } // Copy to hub to all utilities. - return hub->on_meta_data(meta->data()); + return hub->on_meta_data(meta->data(), metadata); } int SrsSource::on_audio(SrsCommonMessage* shared_audio) diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index 9ef381db5..9d7d09678 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +class SrsFormat; class SrsConsumer; class SrsPlayEdge; class SrsPublishEdge; @@ -421,6 +422,8 @@ private: // Whether the stream hub is active, or stream is publishing. bool is_active; private: + // The format, codec information. + SrsFormat* format; // hls handler. SrsHls* hls; // The DASH encoder. @@ -454,7 +457,7 @@ public: virtual int cycle(); public: // When got a parsed metadata. - virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata); + virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata, SrsOnMetaDataPacket* packet); // When got a parsed audio packet. virtual int on_audio(SrsSharedPtrMessage* shared_audio); // When got a parsed video packet. diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 6404321b8..4cd4383a0 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -36,7 +36,7 @@ using namespace std; string srs_codec_video2str(SrsCodecVideo codec) { switch (codec) { - case SrsCodecVideoAVC: + case SrsCodecVideoAVC: return "H264"; case SrsCodecVideoOn2VP6: case SrsCodecVideoOn2VP6WithAlphaChannel: @@ -78,90 +78,6 @@ string srs_codec_audio2str(SrsCodecAudio codec) } } -string srs_codec_aac_profile2str(SrsAacProfile aac_profile) -{ - switch (aac_profile) { - case SrsAacProfileMain: return "Main"; - case SrsAacProfileLC: return "LC"; - case SrsAacProfileSSR: return "SSR"; - default: return "Other"; - } -} - -string srs_codec_aac_object2str(SrsAacObjectType aac_object) -{ - switch (aac_object) { - case SrsAacObjectTypeAacMain: return "Main"; - case SrsAacObjectTypeAacHE: return "HE"; - case SrsAacObjectTypeAacHEV2: return "HEv2"; - case SrsAacObjectTypeAacLC: return "LC"; - case SrsAacObjectTypeAacSSR: return "SSR"; - default: return "Other"; - } -} - -SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile) -{ - switch (profile) { - case SrsAacProfileMain: return SrsAacObjectTypeAacMain; - case SrsAacProfileLC: return SrsAacObjectTypeAacLC; - case SrsAacProfileSSR: return SrsAacObjectTypeAacSSR; - default: return SrsAacObjectTypeReserved; - } -} - -SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type) -{ - switch (object_type) { - case SrsAacObjectTypeAacMain: return SrsAacProfileMain; - case SrsAacObjectTypeAacHE: - case SrsAacObjectTypeAacHEV2: - case SrsAacObjectTypeAacLC: return SrsAacProfileLC; - case SrsAacObjectTypeAacSSR: return SrsAacProfileSSR; - default: return SrsAacProfileReserved; - } -} - -string srs_codec_avc_profile2str(SrsAvcProfile profile) -{ - switch (profile) { - case SrsAvcProfileBaseline: return "Baseline"; - case SrsAvcProfileConstrainedBaseline: return "Baseline(Constrained)"; - case SrsAvcProfileMain: return "Main"; - case SrsAvcProfileExtended: return "Extended"; - case SrsAvcProfileHigh: return "High"; - case SrsAvcProfileHigh10: return "High(10)"; - case SrsAvcProfileHigh10Intra: return "High(10+Intra)"; - case SrsAvcProfileHigh422: return "High(422)"; - case SrsAvcProfileHigh422Intra: return "High(422+Intra)"; - case SrsAvcProfileHigh444: return "High(444)"; - case SrsAvcProfileHigh444Predictive: return "High(444+Predictive)"; - case SrsAvcProfileHigh444Intra: return "High(444+Intra)"; - default: return "Other"; - } -} - -string srs_codec_avc_level2str(SrsAvcLevel level) -{ - switch (level) { - case SrsAvcLevel_1: return "1"; - case SrsAvcLevel_11: return "1.1"; - case SrsAvcLevel_12: return "1.2"; - case SrsAvcLevel_13: return "1.3"; - case SrsAvcLevel_2: return "2"; - case SrsAvcLevel_21: return "2.1"; - case SrsAvcLevel_22: return "2.2"; - case SrsAvcLevel_3: return "3"; - case SrsAvcLevel_31: return "3.1"; - case SrsAvcLevel_32: return "3.2"; - case SrsAvcLevel_4: return "4"; - case SrsAvcLevel_41: return "4.1"; - case SrsAvcLevel_5: return "5"; - case SrsAvcLevel_51: return "5.1"; - default: return "Other"; - } -} - string srs_codec_audio_samplerate2str(SrsCodecAudioSampleRate v) { switch (v) { @@ -173,25 +89,6 @@ string srs_codec_audio_samplerate2str(SrsCodecAudioSampleRate v) } } -/** -* the public data, event HLS disable, others can use it. -*/ -// 0 = 5.5 kHz = 5512 Hz -// 1 = 11 kHz = 11025 Hz -// 2 = 22 kHz = 22050 Hz -// 3 = 44 kHz = 44100 Hz -int flv_sample_rates[] = {5512, 11025, 22050, 44100}; - -// the sample rates in the codec, -// in the sequence header. -int aac_sample_rates[] = -{ - 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, - 7350, 0, 0, 0 -}; - SrsFlvCodec::SrsFlvCodec() { } @@ -206,7 +103,7 @@ bool SrsFlvCodec::video_is_keyframe(char* data, int size) if (size < 1) { return false; } - + char frame_type = data[0]; frame_type = (frame_type >> 4) & 0x0F; @@ -224,14 +121,14 @@ bool SrsFlvCodec::video_is_sequence_header(char* data, int size) if (size < 2) { return false; } - + char frame_type = data[0]; frame_type = (frame_type >> 4) & 0x0F; - + char avc_packet_type = data[1]; - return frame_type == SrsCodecVideoAVCFrameKeyFrame - && avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader; + return frame_type == SrsCodecVideoAVCFrameKeyFrame + && avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader; } bool SrsFlvCodec::audio_is_sequence_header(char* data, int size) @@ -257,7 +154,7 @@ bool SrsFlvCodec::video_is_h264(char* data, int size) if (size < 1) { return false; } - + char codec_id = data[0]; codec_id = codec_id & 0x0F; @@ -299,6 +196,25 @@ bool SrsFlvCodec::video_is_acceptable(char* data, int size) return true; } +/** + * the public data, event HLS disable, others can use it. + */ +// 0 = 5.5 kHz = 5512 Hz +// 1 = 11 kHz = 11025 Hz +// 2 = 22 kHz = 22050 Hz +// 3 = 44 kHz = 44100 Hz +int flv_sample_rates[] = {5512, 11025, 22050, 44100}; + +// the sample rates in the codec, +// in the sequence header. +int aac_sample_rates[] = +{ + 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, + 7350, 0, 0, 0 +}; + string srs_codec_audio_samplesize2str(SrsCodecAudioSampleSize v) { switch (v) { @@ -341,16 +257,154 @@ string srs_codec_avc_nalu2str(SrsAvcNaluType nalu_type) } } -SrsCodecSampleUnit::SrsCodecSampleUnit() +string srs_codec_aac_profile2str(SrsAacProfile aac_profile) +{ + switch (aac_profile) { + case SrsAacProfileMain: return "Main"; + case SrsAacProfileLC: return "LC"; + case SrsAacProfileSSR: return "SSR"; + default: return "Other"; + } +} + +string srs_codec_aac_object2str(SrsAacObjectType aac_object) +{ + switch (aac_object) { + case SrsAacObjectTypeAacMain: return "Main"; + case SrsAacObjectTypeAacHE: return "HE"; + case SrsAacObjectTypeAacHEV2: return "HEv2"; + case SrsAacObjectTypeAacLC: return "LC"; + case SrsAacObjectTypeAacSSR: return "SSR"; + default: return "Other"; + } +} + +SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile) +{ + switch (profile) { + case SrsAacProfileMain: return SrsAacObjectTypeAacMain; + case SrsAacProfileLC: return SrsAacObjectTypeAacLC; + case SrsAacProfileSSR: return SrsAacObjectTypeAacSSR; + default: return SrsAacObjectTypeReserved; + } +} + +SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type) +{ + switch (object_type) { + case SrsAacObjectTypeAacMain: return SrsAacProfileMain; + case SrsAacObjectTypeAacHE: + case SrsAacObjectTypeAacHEV2: + case SrsAacObjectTypeAacLC: return SrsAacProfileLC; + case SrsAacObjectTypeAacSSR: return SrsAacProfileSSR; + default: return SrsAacProfileReserved; + } +} + +string srs_codec_avc_profile2str(SrsAvcProfile profile) +{ + switch (profile) { + case SrsAvcProfileBaseline: return "Baseline"; + case SrsAvcProfileConstrainedBaseline: return "Baseline(Constrained)"; + case SrsAvcProfileMain: return "Main"; + case SrsAvcProfileExtended: return "Extended"; + case SrsAvcProfileHigh: return "High"; + case SrsAvcProfileHigh10: return "High(10)"; + case SrsAvcProfileHigh10Intra: return "High(10+Intra)"; + case SrsAvcProfileHigh422: return "High(422)"; + case SrsAvcProfileHigh422Intra: return "High(422+Intra)"; + case SrsAvcProfileHigh444: return "High(444)"; + case SrsAvcProfileHigh444Predictive: return "High(444+Predictive)"; + case SrsAvcProfileHigh444Intra: return "High(444+Intra)"; + default: return "Other"; + } +} + +string srs_codec_avc_level2str(SrsAvcLevel level) +{ + switch (level) { + case SrsAvcLevel_1: return "1"; + case SrsAvcLevel_11: return "1.1"; + case SrsAvcLevel_12: return "1.2"; + case SrsAvcLevel_13: return "1.3"; + case SrsAvcLevel_2: return "2"; + case SrsAvcLevel_21: return "2.1"; + case SrsAvcLevel_22: return "2.2"; + case SrsAvcLevel_3: return "3"; + case SrsAvcLevel_31: return "3.1"; + case SrsAvcLevel_32: return "3.2"; + case SrsAvcLevel_4: return "4"; + case SrsAvcLevel_41: return "4.1"; + case SrsAvcLevel_5: return "5"; + case SrsAvcLevel_51: return "5.1"; + default: return "Other"; + } +} + +SrsSample::SrsSample() +{ + nb_unit = 0; + unit = NULL; +} + +SrsSample::~SrsSample() +{ +} + +SrsCodec::SrsCodec() +{ +} + +SrsCodec::~SrsCodec() +{ +} + +SrsAudioCodec::SrsAudioCodec() +{ + acodec = SrsCodecAudioForbidden; + sound_rate = SrsCodecAudioSampleRateForbidden; + sound_size = SrsCodecAudioSampleSizeForbidden; + sound_type = SrsCodecAudioSoundTypeForbidden; + aac_packet_type = SrsCodecAudioTypeForbidden; +} + +SrsAudioCodec::~SrsAudioCodec() +{ +} + +SrsCodecFlvTag SrsAudioCodec::codec() +{ + return SrsCodecFlvTagAudio; +} + +SrsVideoCodec::SrsVideoCodec() { - size = 0; - bytes = NULL; + frame_type = SrsCodecVideoAVCFrameForbidden; + avc_packet_type = SrsCodecVideoAVCTypeForbidden; + has_idr = has_aud = has_sps_pps = false; + first_nalu_type = SrsAvcNaluTypeForbidden; } -SrsCodecSampleUnit::~SrsCodecSampleUnit() +SrsVideoCodec::~SrsVideoCodec() { } +SrsCodecFlvTag SrsVideoCodec::codec() +{ + return SrsCodecFlvTagVideo; +} + +SrsFrame::SrsFrame() +{ + codec = NULL; + nb_samples = 0; +} + +SrsFrame::~SrsFrame() +{ + srs_freep(codec); +} + SrsCodecSample::SrsCodecSample() { clear(); @@ -412,8 +466,6 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size) return ret; } -#if !defined(SRS_EXPORT_LIBRTMP) - SrsAvcAacCodec::SrsAvcAacCodec() { avc_parse_sps = true; @@ -1205,7 +1257,7 @@ int SrsAvcAacCodec::avc_demux_annexb_format(SrsBuffer* stream, SrsCodecSample* s } // got the NALU. - if ((ret = sample->add_sample_unit(p, pp - p)) != ERROR_SUCCESS) { + if ((ret = sample->add_sample_unit(p, (int)(pp - p))) != ERROR_SUCCESS) { srs_error("annexb add video sample failed. ret=%d", ret); return ret; } @@ -1271,5 +1323,3 @@ int SrsAvcAacCodec::avc_demux_ibmf_format(SrsBuffer* stream, SrsCodecSample* sam return ret; } -#endif - diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 79073f58a..66248f165 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -301,6 +301,7 @@ enum SrsAvcNaluType { // Unspecified SrsAvcNaluTypeReserved = 0, + SrsAvcNaluTypeForbidden = 0, // Coded slice of a non-IDR picture slice_layer_without_partitioning_rbsp( ) SrsAvcNaluTypeNonIDR = 1, @@ -340,106 +341,10 @@ enum SrsAvcNaluType std::string srs_codec_avc_nalu2str(SrsAvcNaluType nalu_type); /** -* the codec sample unit. -* for h.264 video packet, a NALU is a sample unit. -* for aac raw audio packet, a NALU is the entire aac raw data. -* for sequence header, it's not a sample unit. -*/ -class SrsCodecSampleUnit -{ -public: - /** - * the sample bytes is directly ptr to packet bytes, - * user should never use it when packet destroyed. - */ - int size; - char* bytes; -public: - SrsCodecSampleUnit(); - virtual ~SrsCodecSampleUnit(); -}; - -/** -* the samples in the flv audio/video packet. -* the sample used to analysis a video/audio packet, -* split the h.264 NALUs to buffers, or aac raw data to a buffer, -* and decode the video/audio specified infos. -* -* the sample unit: -* a video packet codec in h.264 contains many NALUs, each is a sample unit. -* a audio packet codec in aac is a sample unit. -* @remark, the video/audio sequence header is not sample unit, -* all sequence header stores as extra data, -* @see SrsAvcAacCodec.avc_extra_data and SrsAvcAacCodec.aac_extra_data -* @remark, user must clear all samples before decode a new video/audio packet. -*/ -class SrsCodecSample -{ -public: - /** - * each audio/video raw data packet will dumps to one or multiple buffers, - * the buffers will write to hls and clear to reset. - * generally, aac audio packet corresponding to one buffer, - * where avc/h264 video packet may contains multiple buffer. - */ - int nb_sample_units; - SrsCodecSampleUnit sample_units[SRS_MAX_CODEC_SAMPLE]; -public: - /** - * whether the sample is video sample which demux from video packet. - */ - bool is_video; - /** - * CompositionTime, video_file_format_spec_v10_1.pdf, page 78. - * cts = pts - dts, where dts = flvheader->timestamp. - */ - int32_t cts; -public: - // video specified - SrsCodecVideoAVCFrame frame_type; - SrsCodecVideoAVCType avc_packet_type; - // whether sample_units contains IDR frame. - bool has_idr; - // Whether exists AUD NALU. - bool has_aud; - // Whether exists SPS/PPS NALU. - bool has_sps_pps; - // The first nalu type. - SrsAvcNaluType first_nalu_type; -public: - // audio specified - SrsCodecAudio acodec; - // audio aac specified. - SrsCodecAudioSampleRate sound_rate; - SrsCodecAudioSampleSize sound_size; - SrsCodecAudioSoundType sound_type; - SrsCodecAudioType aac_packet_type; -public: - SrsCodecSample(); - virtual ~SrsCodecSample(); -public: - /** - * clear all samples. - * the sample units never copy the bytes, it directly use the ptr, - * so when video/audio packet is destroyed, the sample must be clear. - * in a word, user must clear sample before demux it. - * @remark demux sample use SrsAvcAacCodec.audio_aac_demux or video_avc_demux. - */ - void clear(); - /** - * add the a sample unit, it's a h.264 NALU or aac raw data. - * the sample unit directly use the ptr of packet bytes, - * so user must never use sample unit when packet is destroyed. - * in a word, user must clear sample before demux it. - */ - int add_sample_unit(char* bytes, int size); -}; - -/** -* the avc payload format, must be ibmf or annexb format. -* we guess by annexb first, then ibmf for the first time, -* and we always use the guessed format for the next time. -*/ + * the avc payload format, must be ibmf or annexb format. + * we guess by annexb first, then ibmf for the first time, + * and we always use the guessed format for the next time. + */ enum SrsAvcPayloadFormat { SrsAvcPayloadFormatGuess = 0, @@ -448,9 +353,9 @@ enum SrsAvcPayloadFormat }; /** -* the aac profile, for ADTS(HLS/TS) -* @see https://github.com/ossrs/srs/issues/310 -*/ + * the aac profile, for ADTS(HLS/TS) + * @see https://github.com/ossrs/srs/issues/310 + */ enum SrsAacProfile { SrsAacProfileReserved = 3, @@ -463,10 +368,10 @@ enum SrsAacProfile std::string srs_codec_aac_profile2str(SrsAacProfile aac_profile); /** -* the aac object type, for RTMP sequence header -* for AudioSpecificConfig, @see ISO_IEC_14496-3-AAC-2001.pdf, page 33 -* for audioObjectType, @see ISO_IEC_14496-3-AAC-2001.pdf, page 23 -*/ + * the aac object type, for RTMP sequence header + * for AudioSpecificConfig, @see ISO_IEC_14496-3-AAC-2001.pdf, page 33 + * for audioObjectType, @see ISO_IEC_14496-3-AAC-2001.pdf, page 23 + */ enum SrsAacObjectType { SrsAacObjectTypeReserved = 0, @@ -489,9 +394,9 @@ SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile); SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type); /** -* the profile for avc/h.264. -* @see Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 205. -*/ + * the profile for avc/h.264. + * @see Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 205. + */ enum SrsAvcProfile { SrsAvcProfileReserved = 0, @@ -515,9 +420,9 @@ enum SrsAvcProfile std::string srs_codec_avc_profile2str(SrsAvcProfile profile); /** -* the level for avc/h.264. -* @see Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 207. -*/ + * the level for avc/h.264. + * @see Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 207. + */ enum SrsAvcLevel { SrsAvcLevelReserved = 0, @@ -539,7 +444,175 @@ enum SrsAvcLevel }; std::string srs_codec_avc_level2str(SrsAvcLevel level); -#if !defined(SRS_EXPORT_LIBRTMP) +/** + * A sample is the unit of frame. + * It's a NALU for H.264. + * It's the whole AAC raw data for AAC. + * @remark Neither SPS/PPS or ASC is sample unit, it's codec sequence header. + */ +class SrsSample +{ +public: + // The size of unit. + int nb_unit; + // The ptr of unit, user must manage it. + char* unit; +public: + SrsSample(); + virtual ~SrsSample(); +}; + +/** + * The codec is the information of encoder, + * corresponding to the sequence header of FLV, + * parsed to detail info. + */ +class SrsCodec +{ +public: + SrsCodec(); + virtual ~SrsCodec(); +public: + // Get the codec type. + virtual SrsCodecFlvTag codec() = 0; +}; + +/** + * The audio codec info. + */ +class SrsAudioCodec : public SrsCodec +{ +public: + // audio specified + SrsCodecAudio acodec; + // audio aac specified. + SrsCodecAudioSampleRate sound_rate; + SrsCodecAudioSampleSize sound_size; + SrsCodecAudioSoundType sound_type; + SrsCodecAudioType aac_packet_type; +public: + SrsAudioCodec(); + virtual ~SrsAudioCodec(); +public: + virtual SrsCodecFlvTag codec(); +}; + +/** + * The video codec info. + */ +class SrsVideoCodec : public SrsCodec +{ +public: + // video specified + SrsCodecVideoAVCFrame frame_type; + SrsCodecVideoAVCType avc_packet_type; + // whether sample_units contains IDR frame. + bool has_idr; + // Whether exists AUD NALU. + bool has_aud; + // Whether exists SPS/PPS NALU. + bool has_sps_pps; + // The first nalu type. + SrsAvcNaluType first_nalu_type; +public: + SrsVideoCodec(); + virtual ~SrsVideoCodec(); +public: + virtual SrsCodecFlvTag codec(); +}; + +/** + * A codec frame, consists of a codec and a group of samples. + */ +class SrsFrame +{ +public: + // The codec info of frame. + SrsCodec* codec; + // The actual parsed number of samples. + int nb_samples; + // The sampels cache. + SrsSample samples[SRS_MAX_CODEC_SAMPLE]; +public: + SrsFrame(); + virtual ~SrsFrame(); +}; + +/** +* the samples in the flv audio/video packet. +* the sample used to analysis a video/audio packet, +* split the h.264 NALUs to buffers, or aac raw data to a buffer, +* and decode the video/audio specified infos. +* +* the sample unit: +* a video packet codec in h.264 contains many NALUs, each is a sample unit. +* a audio packet codec in aac is a sample unit. +* @remark, the video/audio sequence header is not sample unit, +* all sequence header stores as extra data, +* @see SrsAvcAacCodec.avc_extra_data and SrsAvcAacCodec.aac_extra_data +* @remark, user must clear all samples before decode a new video/audio packet. +*/ +class SrsCodecSample +{ +public: + /** + * each audio/video raw data packet will dumps to one or multiple buffers, + * the buffers will write to hls and clear to reset. + * generally, aac audio packet corresponding to one buffer, + * where avc/h264 video packet may contains multiple buffer. + */ + int nb_sample_units; + SrsCodecSampleUnit sample_units[SRS_MAX_CODEC_SAMPLE]; +public: + /** + * whether the sample is video sample which demux from video packet. + */ + bool is_video; + /** + * CompositionTime, video_file_format_spec_v10_1.pdf, page 78. + * cts = pts - dts, where dts = flvheader->timestamp. + */ + int32_t cts; +public: + // video specified + SrsCodecVideoAVCFrame frame_type; + SrsCodecVideoAVCType avc_packet_type; + // whether sample_units contains IDR frame. + bool has_idr; + // Whether exists AUD NALU. + bool has_aud; + // Whether exists SPS/PPS NALU. + bool has_sps_pps; + // The first nalu type. + SrsAvcNaluType first_nalu_type; +public: + // audio specified + SrsCodecAudio acodec; + // audio aac specified. + SrsCodecAudioSampleRate sound_rate; + SrsCodecAudioSampleSize sound_size; + SrsCodecAudioSoundType sound_type; + SrsCodecAudioType aac_packet_type; +public: + SrsCodecSample(); + virtual ~SrsCodecSample(); +public: + /** + * clear all samples. + * the sample units never copy the bytes, it directly use the ptr, + * so when video/audio packet is destroyed, the sample must be clear. + * in a word, user must clear sample before demux it. + * @remark demux sample use SrsAvcAacCodec.audio_aac_demux or video_avc_demux. + */ + void clear(); + /** + * add the a sample unit, it's a h.264 NALU or aac raw data. + * the sample unit directly use the ptr of packet bytes, + * so user must never use sample unit when packet is destroyed. + * in a word, user must clear sample before demux it. + */ + int add_sample_unit(char* bytes, int size); +}; /** * the h264/avc and aac codec, for media stream. @@ -682,5 +755,3 @@ private: #endif -#endif - diff --git a/trunk/src/protocol/srs_protocol_format.cpp b/trunk/src/protocol/srs_protocol_format.cpp new file mode 100644 index 000000000..75425233f --- /dev/null +++ b/trunk/src/protocol/srs_protocol_format.cpp @@ -0,0 +1,66 @@ +/* + The MIT License (MIT) + + Copyright (c) 2013-2017 SRS(ossrs) + + 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 + +#include +#include +#include + +SrsFormat::SrsFormat() +{ + audio = video = NULL; +} + +SrsFormat::~SrsFormat() +{ + srs_freep(audio); + srs_freep(video); +} + +int SrsFormat::initialize() +{ + return ERROR_SUCCESS; +} + +int SrsFormat::on_metadata(SrsOnMetaDataPacket* meta) +{ + int ret = ERROR_SUCCESS; + + // TODO: FIXME: Try to initialize format from metadata. + + return ret; +} + +int SrsFormat::on_audio(SrsSharedPtrMessage* shared_audio) +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SrsFormat::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header) +{ + int ret = ERROR_SUCCESS; + return ret; +} + diff --git a/trunk/src/protocol/srs_protocol_format.hpp b/trunk/src/protocol/srs_protocol_format.hpp new file mode 100644 index 000000000..d3f61aa22 --- /dev/null +++ b/trunk/src/protocol/srs_protocol_format.hpp @@ -0,0 +1,62 @@ +/* + The MIT License (MIT) + + Copyright (c) 2013-2017 SRS(ossrs) + + 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_PROTOCOL_FORMAT_HPP +#define SRS_PROTOCOL_FORMAT_HPP + +/* +#include +*/ + +#include + +class SrsFrame; +class SrsOnMetaDataPacket; +class SrsSharedPtrMessage; + +/** + * A codec format, including one or many stream, each stream identified by a frame. + * For example, a typical RTMP stream format, consits of a video and audio frame. + * Maybe some RTMP stream only has a audio stream, for instance, redio application. + */ +class SrsFormat +{ +public: + SrsFrame* audio; + SrsFrame* video; +public: + SrsFormat(); + virtual ~SrsFormat(); +public: + // Initialize the format. + virtual int initialize(); + // Initialize the format from metadata, optional. + virtual int on_metadata(SrsOnMetaDataPacket* meta); + // When got a parsed audio packet. + virtual int on_audio(SrsSharedPtrMessage* shared_audio); + // When got a parsed video packet. + virtual int on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header); +}; + +#endif +