diff --git a/trunk/configure b/trunk/configure index 3ee86171d..a680ad704 100755 --- a/trunk/configure +++ b/trunk/configure @@ -469,7 +469,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks" "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" - "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client") + "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_avc_aac") APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh APP_OBJS="${MODULE_OBJS[@]}" # diff --git a/trunk/src/app/srs_app_avc_aac.cpp b/trunk/src/app/srs_app_avc_aac.cpp new file mode 100644 index 000000000..6ad4e816d --- /dev/null +++ b/trunk/src/app/srs_app_avc_aac.cpp @@ -0,0 +1,453 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 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 + +#include + +#include +#include +#include +#include + +SrsCodecBuffer::SrsCodecBuffer() +{ + size = 0; + bytes = NULL; +} + +void SrsCodecBuffer::append(void* data, int len) +{ + srs_assert(data); + srs_assert(len > 0); + + bytes = (char*)realloc(bytes, size + len); + memcpy(bytes + size, data, len); + size += len; +} + +void SrsCodecBuffer::free() +{ + size = 0; + srs_freep(bytes); +} + +SrsCodecSample::SrsCodecSample() +{ + clear(); +} + +SrsCodecSample::~SrsCodecSample() +{ +} + +void SrsCodecSample::clear() +{ + is_video = false; + nb_buffers = 0; + + cts = 0; + frame_type = SrsCodecVideoAVCFrameReserved; + avc_packet_type = SrsCodecVideoAVCTypeReserved; + + sound_rate = SrsCodecAudioSampleRateReserved; + sound_size = SrsCodecAudioSampleSizeReserved; + sound_type = SrsCodecAudioSoundTypeReserved; + aac_packet_type = SrsCodecAudioTypeReserved; +} + +int SrsCodecSample::add_sample(char* bytes, int size) +{ + int ret = ERROR_SUCCESS; + + if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode samples error, " + "exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret); + return ret; + } + + SrsCodecBuffer* buf = &buffers[nb_buffers++]; + buf->bytes = bytes; + buf->size = size; + + return ret; +} + +SrsAvcAacCodec::SrsAvcAacCodec() +{ + width = 0; + height = 0; + duration = 0; + NAL_unit_length = 0; + frame_rate = 0; + video_data_rate = 0; + video_codec_id = 0; + audio_data_rate = 0; + audio_codec_id = 0; + avc_profile = 0; + avc_level = 0; + aac_profile = 0; + aac_sample_rate = 0; + aac_channels = 0; + avc_extra_size = 0; + avc_extra_data = NULL; + aac_extra_size = 0; + aac_extra_data = NULL; + sequenceParameterSetLength = 0; + sequenceParameterSetNALUnit = NULL; + pictureParameterSetLength = 0; + pictureParameterSetNALUnit = NULL; + + stream = new SrsStream(); +} + +SrsAvcAacCodec::~SrsAvcAacCodec() +{ + srs_freep(avc_extra_data); + srs_freep(aac_extra_data); + + srs_freep(stream); + srs_freep(sequenceParameterSetNALUnit); + srs_freep(pictureParameterSetNALUnit); +} + +int SrsAvcAacCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) +{ + int ret = ERROR_SUCCESS; + + sample->is_video = false; + + if (!data || size <= 0) { + srs_trace("no audio present, hls ignore it."); + return ret; + } + + if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { + return ret; + } + + // audio decode + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio sound_format failed. ret=%d", ret); + return ret; + } + + int8_t sound_format = stream->read_1bytes(); + + int8_t sound_type = sound_format & 0x01; + int8_t sound_size = (sound_format >> 1) & 0x01; + int8_t sound_rate = (sound_format >> 2) & 0x03; + sound_format = (sound_format >> 4) & 0x0f; + + audio_codec_id = sound_format; + sample->sound_type = (SrsCodecAudioSoundType)sound_type; + sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; + sample->sound_size = (SrsCodecAudioSampleSize)sound_size; + + // reset the sample rate by sequence header + static int aac_sample_rates[] = { + 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, + 7350, 0, 0, 0 + }; + switch (aac_sample_rates[aac_sample_rate]) { + case 11025: + sample->sound_rate = SrsCodecAudioSampleRate11025; + break; + case 22050: + sample->sound_rate = SrsCodecAudioSampleRate22050; + break; + case 44100: + sample->sound_rate = SrsCodecAudioSampleRate44100; + break; + }; + + // only support aac + if (audio_codec_id != SrsCodecAudioAAC) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls only support audio aac codec. actual=%d, ret=%d", audio_codec_id, ret); + return ret; + } + + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac_packet_type failed. ret=%d", ret); + return ret; + } + + int8_t aac_packet_type = stream->read_1bytes(); + sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type; + + if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) { + // AudioSpecificConfig + // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. + aac_extra_size = stream->left(); + if (aac_extra_size > 0) { + srs_freep(aac_extra_data); + aac_extra_data = new char[aac_extra_size]; + memcpy(aac_extra_data, stream->current(), aac_extra_size); + } + + // only need to decode the first 2bytes: + // audioObjectType, aac_profile, 5bits. + // samplingFrequencyIndex, aac_sample_rate, 4bits. + // channelConfiguration, aac_channels, 4bits + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac sequence header failed. ret=%d", ret); + return ret; + } + aac_profile = stream->read_1bytes(); + aac_sample_rate = stream->read_1bytes(); + + aac_channels = (aac_sample_rate >> 3) & 0x0f; + aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); + aac_profile = (aac_profile >> 3) & 0x1f; + + if (aac_profile == 0 || aac_profile == 0x1f) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac sequence header failed, " + "adts object=%d invalid. ret=%d", aac_profile, ret); + return ret; + } + + // aac_profile = audioObjectType - 1 + aac_profile--; + + if (aac_profile > 3) { + // Mark all extended profiles as LC + // to make Android as happy as possible. + // @see: ngx_rtmp_hls_parse_aac_header + aac_profile = 1; + } + } else if (aac_packet_type == SrsCodecAudioTypeRawData) { + // ensure the sequence header demuxed + if (aac_extra_size <= 0 || !aac_extra_data) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret); + return ret; + } + + // Raw AAC frame data in UI8 [] + // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 + if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) { + srs_error("hls add audio sample failed. ret=%d", ret); + return ret; + } + } else { + // ignored. + } + + srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", + sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size); + + return ret; +} + +int SrsAvcAacCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) +{ + int ret = ERROR_SUCCESS; + + sample->is_video = true; + + if (!data || size <= 0) { + srs_trace("no video present, hls ignore it."); + return ret; + } + + if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { + return ret; + } + + // video decode + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video frame_type failed. ret=%d", ret); + return ret; + } + + int8_t frame_type = stream->read_1bytes(); + int8_t codec_id = frame_type & 0x0f; + frame_type = (frame_type >> 4) & 0x0f; + + sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; + + // only support h.264/avc + if (codec_id != SrsCodecVideoAVC) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret); + return ret; + } + video_codec_id = codec_id; + + if (!stream->require(4)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc_packet_type failed. ret=%d", ret); + return ret; + } + int8_t avc_packet_type = stream->read_1bytes(); + int32_t composition_time = stream->read_3bytes(); + + // pts = dts + cts. + sample->cts = composition_time; + sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; + + if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { + // AVCDecoderConfigurationRecord + // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + avc_extra_size = stream->left(); + if (avc_extra_size > 0) { + srs_freep(avc_extra_data); + avc_extra_data = new char[avc_extra_size]; + memcpy(avc_extra_data, stream->current(), avc_extra_size); + } + + if (!stream->require(6)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header failed. ret=%d", ret); + return ret; + } + //int8_t configurationVersion = stream->read_1bytes(); + //int8_t AVCProfileIndication = stream->read_1bytes(); + //int8_t profile_compatibility = stream->read_1bytes(); + //int8_t AVCLevelIndication = stream->read_1bytes(); + stream->skip(4); + // parse the NALU size. + int8_t lengthSizeMinusOne = stream->read_1bytes(); + lengthSizeMinusOne &= 0x03; + NAL_unit_length = lengthSizeMinusOne; + + // 1 sps + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); + return ret; + } + int8_t numOfSequenceParameterSets = stream->read_1bytes(); + numOfSequenceParameterSets &= 0x1f; + if (numOfSequenceParameterSets != 1) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); + return ret; + } + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); + return ret; + } + sequenceParameterSetLength = stream->read_2bytes(); + if (!stream->require(sequenceParameterSetLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); + return ret; + } + if (sequenceParameterSetLength > 0) { + srs_freep(sequenceParameterSetNALUnit); + sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; + memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength); + stream->skip(sequenceParameterSetLength); + } + // 1 pps + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); + return ret; + } + int8_t numOfPictureParameterSets = stream->read_1bytes(); + numOfPictureParameterSets &= 0x1f; + if (numOfPictureParameterSets != 1) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); + return ret; + } + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); + return ret; + } + pictureParameterSetLength = stream->read_2bytes(); + if (!stream->require(pictureParameterSetLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); + return ret; + } + if (pictureParameterSetLength > 0) { + srs_freep(pictureParameterSetNALUnit); + pictureParameterSetNALUnit = new char[pictureParameterSetLength]; + memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength); + stream->skip(pictureParameterSetLength); + } + } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ + // ensure the sequence header demuxed + if (avc_extra_size <= 0 || !avc_extra_data) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret); + return ret; + } + + // One or more NALUs (Full frames are required) + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 + int PictureLength = stream->left(); + for (int i = 0; i < PictureLength;) { + if (!stream->require(NAL_unit_length + 1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc NALU size failed. ret=%d", ret); + return ret; + } + int32_t NALUnitLength = 0; + if (NAL_unit_length == 3) { + NALUnitLength = stream->read_4bytes(); + } else if (NALUnitLength == 2) { + NALUnitLength = stream->read_3bytes(); + } else if (NALUnitLength == 1) { + NALUnitLength = stream->read_2bytes(); + } else { + NALUnitLength = stream->read_1bytes(); + } + // NALUnit + if (!stream->require(NALUnitLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc NALU data failed. ret=%d", ret); + return ret; + } + // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. + if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) { + srs_error("hls add video sample failed. ret=%d", ret); + return ret; + } + stream->skip(NALUnitLength); + + i += NAL_unit_length + 1 + NALUnitLength; + } + } else { + // ignored. + } + + srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d", + frame_type, video_codec_id, avc_packet_type, composition_time, size); + + return ret; +} diff --git a/trunk/src/app/srs_app_avc_aac.hpp b/trunk/src/app/srs_app_avc_aac.hpp new file mode 100644 index 000000000..a196051de --- /dev/null +++ b/trunk/src/app/srs_app_avc_aac.hpp @@ -0,0 +1,198 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 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_APP_AVC_AAC_HPP +#define SRS_APP_AVC_AAC_HPP + +/* +#include +*/ + +#include + +#include + +#define SRS_MAX_CODEC_SAMPLE 128 + +// Sampling rate. The following values are defined: +// 0 = 5.5 kHz = 5512 Hz +// 1 = 11 kHz = 11025 Hz +// 2 = 22 kHz = 22050 Hz +// 3 = 44 kHz = 44100 Hz +enum SrsCodecAudioSampleRate +{ + SrsCodecAudioSampleRateReserved = -1, + + SrsCodecAudioSampleRate5512 = 0, + SrsCodecAudioSampleRate11025 = 1, + SrsCodecAudioSampleRate22050 = 2, + SrsCodecAudioSampleRate44100 = 3, +}; + +// Size of each audio sample. This parameter only pertains to +// uncompressed formats. Compressed formats always decode +// to 16 bits internally. +// 0 = 8-bit samples +// 1 = 16-bit samples +enum SrsCodecAudioSampleSize +{ + SrsCodecAudioSampleSizeReserved = -1, + + SrsCodecAudioSampleSize8bit = 0, + SrsCodecAudioSampleSize16bit = 1, +}; + +// Mono or stereo sound +// 0 = Mono sound +// 1 = Stereo sound +enum SrsCodecAudioSoundType +{ + SrsCodecAudioSoundTypeReserved = -1, + + SrsCodecAudioSoundTypeMono = 0, + SrsCodecAudioSoundTypeStereo = 1, +}; + +/** +* buffer indicates the position and size. +*/ +class SrsCodecBuffer +{ +public: + /** + * @remark user must manage the bytes. + */ + int size; + char* bytes; + + SrsCodecBuffer(); + void append(void* data, int len); + + /** + * free the bytes, + * user can invoke it to free the bytes, + * the SrsCodecBuffer never free automatically. + */ + void free(); +}; + +/** +* the samples in the flv audio/video 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_buffers; + SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; +public: + 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; +public: + // audio specified + SrsCodecAudioSampleRate sound_rate; + SrsCodecAudioSampleSize sound_size; + SrsCodecAudioSoundType sound_type; + SrsCodecAudioType aac_packet_type; +public: + SrsCodecSample(); + virtual ~SrsCodecSample(); + void clear(); + int add_sample(char* bytes, int size); +}; + +/** +* the h264/avc and aac codec, for media stream. +* to decode the stream of avc/aac for hls. +*/ +class SrsAvcAacCodec +{ +private: + SrsStream* stream; +public: + /** + * video specified + */ + // @see: SrsCodecVideo + int video_codec_id; + // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. + u_int8_t avc_profile; + // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. + u_int8_t avc_level; + int width; + int height; + int video_data_rate; // in bps + int frame_rate; + int duration; + // lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + int8_t NAL_unit_length; + u_int16_t sequenceParameterSetLength; + char* sequenceParameterSetNALUnit; + u_int16_t pictureParameterSetLength; + char* pictureParameterSetNALUnit; +public: + /** + * audio specified + */ + // @see: SrsCodecAudioType + int audio_codec_id; + int audio_data_rate; // in bps + // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. + // audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40. + u_int8_t aac_profile; + // samplingFrequencyIndex + u_int8_t aac_sample_rate; + // channelConfiguration + u_int8_t aac_channels; +public: + // the avc extra data, the AVC sequence header, + // without the flv codec header, + // @see: ffmpeg, AVCodecContext::extradata + int avc_extra_size; + char* avc_extra_data; + // the aac extra data, the AAC sequence header, + // without the flv codec header, + // @see: ffmpeg, AVCodecContext::extradata + int aac_extra_size; + char* aac_extra_data; +public: + SrsAvcAacCodec(); + virtual ~SrsAvcAacCodec(); +// the following function used for hls to build the codec info. +public: + virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample); + virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample); +}; + +#endif diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index e6d7fde05..f605e4372 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -228,9 +228,9 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video) int size = (int)video->size; #ifdef SRS_AUTO_HTTP_CALLBACK - bool is_key_frame = SrsCodec::video_is_h264((int8_t*)payload, size) - && SrsCodec::video_is_keyframe((int8_t*)payload, size) - && !SrsCodec::video_is_sequence_header((int8_t*)payload, size); + bool is_key_frame = SrsFlvCodec::video_is_h264((int8_t*)payload, size) + && SrsFlvCodec::video_is_keyframe((int8_t*)payload, size) + && !SrsFlvCodec::video_is_sequence_header((int8_t*)payload, size); if (is_key_frame) { segment->has_keyframe = true; if ((ret = on_video_keyframe()) != ERROR_SUCCESS) { diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 8c375efec..6d91026d4 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -44,6 +44,7 @@ using namespace std; #include #include #include +#include // max PES packets size to flush the video. #define SRS_AUTO_HLS_AUDIO_CACHE_SIZE 1024 * 1024 @@ -1014,7 +1015,7 @@ int SrsHlsCache::on_sequence_header(SrsHlsMuxer* muxer) return muxer->on_sequence_header(); } -int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample) +int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; @@ -1062,7 +1063,7 @@ int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, S } int SrsHlsCache::write_video( - SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample) + SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; @@ -1123,7 +1124,7 @@ int SrsHlsCache::reap_segment(string log_desc, SrsHlsMuxer* muxer, int64_t segme return ret; } -int SrsHlsCache::cache_audio(SrsCodec* codec, SrsCodecSample* sample) +int SrsHlsCache::cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; @@ -1190,7 +1191,7 @@ int SrsHlsCache::cache_audio(SrsCodec* codec, SrsCodecSample* sample) return ret; } -int SrsHlsCache::cache_video(SrsCodec* codec, SrsCodecSample* sample) +int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; @@ -1262,7 +1263,7 @@ SrsHls::SrsHls(SrsSource* _source) hls_enabled = false; source = _source; - codec = new SrsCodec(); + codec = new SrsAvcAacCodec(); sample = new SrsCodecSample(); jitter = new SrsRtmpJitter(); diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index e97928dcc..fdb76364b 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -41,7 +41,7 @@ class SrsMpegtsFrame; class SrsAmf0Object; class SrsRtmpJitter; class SrsTSMuxer; -class SrsCodec; +class SrsAvcAacCodec; class SrsRequest; class SrsPithyPrint; class SrsSource; @@ -247,11 +247,11 @@ public: /** * write audio to cache, if need to flush, flush to muxer. */ - virtual int write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample); + virtual int write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample); /** * write video to muxer. */ - virtual int write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample); + virtual int write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample); private: /** * reopen the muxer for a new hls segment, @@ -260,8 +260,8 @@ private: * so, user must reap_segment then flush_video to hls muxer. */ virtual int reap_segment(std::string log_desc, SrsHlsMuxer* muxer, int64_t segment_start_dts); - virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample); - virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample); + virtual int cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample); + virtual int cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample); }; /** @@ -277,7 +277,7 @@ private: private: bool hls_enabled; SrsSource* source; - SrsCodec* codec; + SrsAvcAacCodec* codec; SrsCodecSample* sample; SrsRtmpJitter* jitter; SrsPithyPrint* pithy_print; diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 1ae43d8dc..dbcd64aaa 100644 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -201,7 +201,7 @@ void SrsMessageQueue::shrink() SrsSharedPtrMessage* msg = msgs[i]; if (msg->header.is_video()) { - if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) { + if (SrsFlvCodec::video_is_keyframe(msg->payload, msg->size)) { // the max frame index to remove. iframe_index = i; @@ -363,7 +363,7 @@ int SrsGopCache::cache(SrsSharedPtrMessage* msg) } // clear gop cache when got key frame - if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) { + if (msg->header.is_video() && SrsFlvCodec::video_is_keyframe(msg->payload, msg->size)) { srs_info("clear gop cache when got keyframe. vcount=%d, count=%d", cached_video_count, (int)gop_cache.size()); @@ -1012,7 +1012,7 @@ int SrsSource::on_audio(SrsMessage* audio) // cache the sequence header if h264 // donot cache the sequence header to gop_cache, return here. - if (SrsCodec::audio_is_sequence_header(msg->payload, msg->size)) { + if (SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size)) { srs_freep(cache_sh_audio); cache_sh_audio = msg->copy(); srs_trace("got audio sh, size=%d", msg->header.payload_length); @@ -1102,7 +1102,7 @@ int SrsSource::on_video(SrsMessage* video) // cache the sequence header if h264 // donot cache the sequence header to gop_cache, return here. - if (SrsCodec::video_is_sequence_header(msg->payload, msg->size)) { + if (SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size)) { srs_freep(cache_sh_video); cache_sh_video = msg->copy(); srs_trace("got video sh, size=%d", msg->header.payload_length); diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index b01dcd617..11b8532dc 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -31,429 +31,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -SrsCodecBuffer::SrsCodecBuffer() -{ - size = 0; - bytes = NULL; -} - -void SrsCodecBuffer::append(void* data, int len) -{ - srs_assert(data); - srs_assert(len > 0); - - bytes = (char*)realloc(bytes, size + len); - memcpy(bytes + size, data, len); - size += len; -} - -void SrsCodecBuffer::free() -{ - size = 0; - srs_freep(bytes); -} - -SrsCodecSample::SrsCodecSample() -{ - clear(); -} - -SrsCodecSample::~SrsCodecSample() +SrsFlvCodec::SrsFlvCodec() { } -void SrsCodecSample::clear() +SrsFlvCodec::~SrsFlvCodec() { - is_video = false; - nb_buffers = 0; - - cts = 0; - frame_type = SrsCodecVideoAVCFrameReserved; - avc_packet_type = SrsCodecVideoAVCTypeReserved; - - sound_rate = SrsCodecAudioSampleRateReserved; - sound_size = SrsCodecAudioSampleSizeReserved; - sound_type = SrsCodecAudioSoundTypeReserved; - aac_packet_type = SrsCodecAudioTypeReserved; } -int SrsCodecSample::add_sample(char* bytes, int size) -{ - int ret = ERROR_SUCCESS; - - if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode samples error, " - "exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret); - return ret; - } - - SrsCodecBuffer* buf = &buffers[nb_buffers++]; - buf->bytes = bytes; - buf->size = size; - - return ret; -} - -SrsCodec::SrsCodec() -{ - width = 0; - height = 0; - duration = 0; - NAL_unit_length = 0; - frame_rate = 0; - video_data_rate = 0; - video_codec_id = 0; - audio_data_rate = 0; - audio_codec_id = 0; - avc_profile = 0; - avc_level = 0; - aac_profile = 0; - aac_sample_rate = 0; - aac_channels = 0; - avc_extra_size = 0; - avc_extra_data = NULL; - aac_extra_size = 0; - aac_extra_data = NULL; - sequenceParameterSetLength = 0; - sequenceParameterSetNALUnit = NULL; - pictureParameterSetLength = 0; - pictureParameterSetNALUnit = NULL; - - stream = new SrsStream(); -} - -SrsCodec::~SrsCodec() -{ - srs_freep(avc_extra_data); - srs_freep(aac_extra_data); - - srs_freep(stream); - srs_freep(sequenceParameterSetNALUnit); - srs_freep(pictureParameterSetNALUnit); -} - -int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) -{ - int ret = ERROR_SUCCESS; - - sample->is_video = false; - - if (!data || size <= 0) { - srs_trace("no audio present, hls ignore it."); - return ret; - } - - if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { - return ret; - } - - // audio decode - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio sound_format failed. ret=%d", ret); - return ret; - } - - int8_t sound_format = stream->read_1bytes(); - - int8_t sound_type = sound_format & 0x01; - int8_t sound_size = (sound_format >> 1) & 0x01; - int8_t sound_rate = (sound_format >> 2) & 0x03; - sound_format = (sound_format >> 4) & 0x0f; - - audio_codec_id = sound_format; - sample->sound_type = (SrsCodecAudioSoundType)sound_type; - sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; - sample->sound_size = (SrsCodecAudioSampleSize)sound_size; - - // reset the sample rate by sequence header - static int aac_sample_rates[] = { - 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, - 7350, 0, 0, 0 - }; - switch (aac_sample_rates[aac_sample_rate]) { - case 11025: - sample->sound_rate = SrsCodecAudioSampleRate11025; - break; - case 22050: - sample->sound_rate = SrsCodecAudioSampleRate22050; - break; - case 44100: - sample->sound_rate = SrsCodecAudioSampleRate44100; - break; - }; - - // only support aac - if (audio_codec_id != SrsCodecAudioAAC) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls only support audio aac codec. actual=%d, ret=%d", audio_codec_id, ret); - return ret; - } - - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac_packet_type failed. ret=%d", ret); - return ret; - } - - int8_t aac_packet_type = stream->read_1bytes(); - sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type; - - if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) { - // AudioSpecificConfig - // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. - aac_extra_size = stream->left(); - if (aac_extra_size > 0) { - srs_freep(aac_extra_data); - aac_extra_data = new char[aac_extra_size]; - memcpy(aac_extra_data, stream->current(), aac_extra_size); - } - - // only need to decode the first 2bytes: - // audioObjectType, aac_profile, 5bits. - // samplingFrequencyIndex, aac_sample_rate, 4bits. - // channelConfiguration, aac_channels, 4bits - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac sequence header failed. ret=%d", ret); - return ret; - } - aac_profile = stream->read_1bytes(); - aac_sample_rate = stream->read_1bytes(); - - aac_channels = (aac_sample_rate >> 3) & 0x0f; - aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); - aac_profile = (aac_profile >> 3) & 0x1f; - - if (aac_profile == 0 || aac_profile == 0x1f) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac sequence header failed, " - "adts object=%d invalid. ret=%d", aac_profile, ret); - return ret; - } - - // aac_profile = audioObjectType - 1 - aac_profile--; - - if (aac_profile > 3) { - // Mark all extended profiles as LC - // to make Android as happy as possible. - // @see: ngx_rtmp_hls_parse_aac_header - aac_profile = 1; - } - } else if (aac_packet_type == SrsCodecAudioTypeRawData) { - // ensure the sequence header demuxed - if (aac_extra_size <= 0 || !aac_extra_data) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret); - return ret; - } - - // Raw AAC frame data in UI8 [] - // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 - if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) { - srs_error("hls add audio sample failed. ret=%d", ret); - return ret; - } - } else { - // ignored. - } - - srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", - sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size); - - return ret; -} - -int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) -{ - int ret = ERROR_SUCCESS; - - sample->is_video = true; - - if (!data || size <= 0) { - srs_trace("no video present, hls ignore it."); - return ret; - } - - if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { - return ret; - } - - // video decode - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video frame_type failed. ret=%d", ret); - return ret; - } - - int8_t frame_type = stream->read_1bytes(); - int8_t codec_id = frame_type & 0x0f; - frame_type = (frame_type >> 4) & 0x0f; - - sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; - - // only support h.264/avc - if (codec_id != SrsCodecVideoAVC) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret); - return ret; - } - video_codec_id = codec_id; - - if (!stream->require(4)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc_packet_type failed. ret=%d", ret); - return ret; - } - int8_t avc_packet_type = stream->read_1bytes(); - int32_t composition_time = stream->read_3bytes(); - - // pts = dts + cts. - sample->cts = composition_time; - sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; - - if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { - // AVCDecoderConfigurationRecord - // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 - avc_extra_size = stream->left(); - if (avc_extra_size > 0) { - srs_freep(avc_extra_data); - avc_extra_data = new char[avc_extra_size]; - memcpy(avc_extra_data, stream->current(), avc_extra_size); - } - - if (!stream->require(6)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header failed. ret=%d", ret); - return ret; - } - //int8_t configurationVersion = stream->read_1bytes(); - //int8_t AVCProfileIndication = stream->read_1bytes(); - //int8_t profile_compatibility = stream->read_1bytes(); - //int8_t AVCLevelIndication = stream->read_1bytes(); - stream->skip(4); - // parse the NALU size. - int8_t lengthSizeMinusOne = stream->read_1bytes(); - lengthSizeMinusOne &= 0x03; - NAL_unit_length = lengthSizeMinusOne; - - // 1 sps - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); - return ret; - } - int8_t numOfSequenceParameterSets = stream->read_1bytes(); - numOfSequenceParameterSets &= 0x1f; - if (numOfSequenceParameterSets != 1) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); - return ret; - } - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); - return ret; - } - sequenceParameterSetLength = stream->read_2bytes(); - if (!stream->require(sequenceParameterSetLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); - return ret; - } - if (sequenceParameterSetLength > 0) { - srs_freep(sequenceParameterSetNALUnit); - sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; - memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength); - stream->skip(sequenceParameterSetLength); - } - // 1 pps - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); - return ret; - } - int8_t numOfPictureParameterSets = stream->read_1bytes(); - numOfPictureParameterSets &= 0x1f; - if (numOfPictureParameterSets != 1) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); - return ret; - } - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); - return ret; - } - pictureParameterSetLength = stream->read_2bytes(); - if (!stream->require(pictureParameterSetLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); - return ret; - } - if (pictureParameterSetLength > 0) { - srs_freep(pictureParameterSetNALUnit); - pictureParameterSetNALUnit = new char[pictureParameterSetLength]; - memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength); - stream->skip(pictureParameterSetLength); - } - } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ - // ensure the sequence header demuxed - if (avc_extra_size <= 0 || !avc_extra_data) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret); - return ret; - } - - // One or more NALUs (Full frames are required) - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 - int PictureLength = stream->left(); - for (int i = 0; i < PictureLength;) { - if (!stream->require(NAL_unit_length + 1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc NALU size failed. ret=%d", ret); - return ret; - } - int32_t NALUnitLength = 0; - if (NAL_unit_length == 3) { - NALUnitLength = stream->read_4bytes(); - } else if (NALUnitLength == 2) { - NALUnitLength = stream->read_3bytes(); - } else if (NALUnitLength == 1) { - NALUnitLength = stream->read_2bytes(); - } else { - NALUnitLength = stream->read_1bytes(); - } - // NALUnit - if (!stream->require(NALUnitLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc NALU data failed. ret=%d", ret); - return ret; - } - // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. - if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) { - srs_error("hls add video sample failed. ret=%d", ret); - return ret; - } - stream->skip(NALUnitLength); - - i += NAL_unit_length + 1 + NALUnitLength; - } - } else { - // ignored. - } - - srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d", - frame_type, video_codec_id, avc_packet_type, composition_time, size); - - return ret; -} - -bool SrsCodec::video_is_keyframe(int8_t* data, int size) +bool SrsFlvCodec::video_is_keyframe(int8_t* data, int size) { // 2bytes required. if (size < 1) { @@ -466,7 +52,7 @@ bool SrsCodec::video_is_keyframe(int8_t* data, int size) return frame_type == SrsCodecVideoAVCFrameKeyFrame; } -bool SrsCodec::video_is_sequence_header(int8_t* data, int size) +bool SrsFlvCodec::video_is_sequence_header(int8_t* data, int size) { // sequence header only for h264 if (!video_is_h264(data, size)) { @@ -487,7 +73,7 @@ bool SrsCodec::video_is_sequence_header(int8_t* data, int size) && avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader; } -bool SrsCodec::audio_is_sequence_header(int8_t* data, int size) +bool SrsFlvCodec::audio_is_sequence_header(int8_t* data, int size) { // sequence header only for aac if (!audio_is_aac(data, size)) { @@ -504,7 +90,7 @@ bool SrsCodec::audio_is_sequence_header(int8_t* data, int size) return aac_packet_type == SrsCodecAudioTypeSequenceHeader; } -bool SrsCodec::video_is_h264(int8_t* data, int size) +bool SrsFlvCodec::video_is_h264(int8_t* data, int size) { // 1bytes required. if (size < 1) { @@ -517,7 +103,7 @@ bool SrsCodec::video_is_h264(int8_t* data, int size) return codec_id == SrsCodecVideoAVC; } -bool SrsCodec::audio_is_aac(int8_t* data, int size) +bool SrsFlvCodec::audio_is_aac(int8_t* data, int size) { // 1bytes required. if (size < 1) { diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index a313afd05..d447288c1 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -30,29 +30,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include -#define SRS_MAX_CODEC_SAMPLE 128 - class SrsStream; -// 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 -enum SrsCodecVideo +// AACPacketType IF SoundFormat == 10 UI8 +// The following values are defined: +// 0 = AAC sequence header +// 1 = AAC raw +enum SrsCodecAudioType { - SrsCodecVideoReserved = 0, - - SrsCodecVideoSorensonH263 = 2, - SrsCodecVideoScreenVideo = 3, - SrsCodecVideoOn2VP6 = 4, - SrsCodecVideoOn2VP6WithAlphaChannel = 5, - SrsCodecVideoScreenVideoVersion2 = 6, - SrsCodecVideoAVC = 7, + SrsCodecAudioTypeReserved = -1, + SrsCodecAudioTypeSequenceHeader = 0, + SrsCodecAudioTypeRawData = 1, }; // E.4.3.1 VIDEODATA @@ -89,6 +77,27 @@ enum SrsCodecVideoAVCType SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, }; +// 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 +enum SrsCodecVideo +{ + SrsCodecVideoReserved = 0, + + SrsCodecVideoSorensonH263 = 2, + SrsCodecVideoScreenVideo = 3, + SrsCodecVideoOn2VP6 = 4, + SrsCodecVideoOn2VP6WithAlphaChannel = 5, + SrsCodecVideoScreenVideoVersion2 = 6, + SrsCodecVideoAVC = 7, +}; + // SoundFormat UB [4] // Format of SoundData. The following values are defined: // 0 = Linear PCM, platform endian @@ -126,165 +135,15 @@ enum SrsCodecAudio SrsCodecAudioReservedDeviceSpecificSound = 15, }; -// AACPacketType IF SoundFormat == 10 UI8 -// The following values are defined: -// 0 = AAC sequence header -// 1 = AAC raw -enum SrsCodecAudioType -{ - SrsCodecAudioTypeReserved = -1, - SrsCodecAudioTypeSequenceHeader = 0, - SrsCodecAudioTypeRawData = 1, -}; - -// Sampling rate. The following values are defined: -// 0 = 5.5 kHz = 5512 Hz -// 1 = 11 kHz = 11025 Hz -// 2 = 22 kHz = 22050 Hz -// 3 = 44 kHz = 44100 Hz -enum SrsCodecAudioSampleRate -{ - SrsCodecAudioSampleRateReserved = -1, - - SrsCodecAudioSampleRate5512 = 0, - SrsCodecAudioSampleRate11025 = 1, - SrsCodecAudioSampleRate22050 = 2, - SrsCodecAudioSampleRate44100 = 3, -}; - -// Size of each audio sample. This parameter only pertains to -// uncompressed formats. Compressed formats always decode -// to 16 bits internally. -// 0 = 8-bit samples -// 1 = 16-bit samples -enum SrsCodecAudioSampleSize -{ - SrsCodecAudioSampleSizeReserved = -1, - - SrsCodecAudioSampleSize8bit = 0, - SrsCodecAudioSampleSize16bit = 1, -}; - -// Mono or stereo sound -// 0 = Mono sound -// 1 = Stereo sound -enum SrsCodecAudioSoundType -{ - SrsCodecAudioSoundTypeReserved = -1, - - SrsCodecAudioSoundTypeMono = 0, - SrsCodecAudioSoundTypeStereo = 1, -}; - -/** -* buffer indicates the position and size. -*/ -class SrsCodecBuffer -{ -public: - /** - * @remark user must manage the bytes. - */ - int size; - char* bytes; - - SrsCodecBuffer(); - void append(void* data, int len); - - /** - * free the bytes, - * user can invoke it to free the bytes, - * the SrsCodecBuffer never free automatically. - */ - void free(); -}; - -/** -* the samples in the flv audio/video packet. -*/ -class SrsCodecSample -{ -public: - int nb_buffers; - SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; -public: - bool is_video; - // video specified - SrsCodecVideoAVCFrame frame_type; - SrsCodecVideoAVCType avc_packet_type; - // CompositionTime, video_file_format_spec_v10_1.pdf, page 78. - // cts = pts - dts, where dts = flvheader->timestamp. - int32_t cts; - // audio specified - SrsCodecAudioSampleRate sound_rate; - SrsCodecAudioSampleSize sound_size; - SrsCodecAudioSoundType sound_type; - SrsCodecAudioType aac_packet_type; -public: - SrsCodecSample(); - virtual ~SrsCodecSample(); - void clear(); - int add_sample(char* bytes, int size); -}; - /** * Annex E. The FLV File Format +* @see SrsAvcAacCodec for the media stream codec. */ -class SrsCodec +class SrsFlvCodec { -private: - SrsStream* stream; public: - /** - * video specified - */ - // @see: SrsCodecVideo - int video_codec_id; - // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. - u_int8_t avc_profile; - // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. - u_int8_t avc_level; - int width; - int height; - int video_data_rate; // in bps - int frame_rate; - int duration; - // lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 - int8_t NAL_unit_length; - u_int16_t sequenceParameterSetLength; - char* sequenceParameterSetNALUnit; - u_int16_t pictureParameterSetLength; - char* pictureParameterSetNALUnit; - /** - * audio specified - */ - // @see: SrsCodecAudioType - int audio_codec_id; - int audio_data_rate; // in bps - // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. - // audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40. - u_int8_t aac_profile; - // samplingFrequencyIndex - u_int8_t aac_sample_rate; - // channelConfiguration - u_int8_t aac_channels; - // the avc extra data, the AVC sequence header, - // without the flv codec header, - // @see: ffmpeg, AVCodecContext::extradata - int avc_extra_size; - char* avc_extra_data; - // the aac extra data, the AAC sequence header, - // without the flv codec header, - // @see: ffmpeg, AVCodecContext::extradata - int aac_extra_size; - char* aac_extra_data; -public: - SrsCodec(); - virtual ~SrsCodec(); -// the following function used for hls to build the codec info. -public: - virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample); - virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample); + SrsFlvCodec(); + virtual ~SrsFlvCodec(); // the following function used to finger out the flv/rtmp packet detail. public: /** diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index df263b584..7acb5cae6 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -540,12 +540,12 @@ flv_bool srs_flv_is_eof(int error_code) flv_bool srs_flv_is_sequence_header(char* data, int32_t size) { - return SrsCodec::video_is_sequence_header((int8_t*)data, (int)size); + return SrsFlvCodec::video_is_sequence_header((int8_t*)data, (int)size); } flv_bool srs_flv_is_keyframe(char* data, int32_t size) { - return SrsCodec::video_is_keyframe((int8_t*)data, (int)size); + return SrsFlvCodec::video_is_keyframe((int8_t*)data, (int)size); } srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed) diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index cf6e2c437..228c37241 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -43,6 +43,8 @@ file ..\rtmp\srs_protocol_utility.hpp, ..\rtmp\srs_protocol_utility.cpp, app readonly separator, + ..\app\srs_app_avc_aac.hpp, + ..\app\srs_app_avc_aac.cpp, ..\app\srs_app_bandwidth.hpp, ..\app\srs_app_bandwidth.cpp, ..\app\srs_app_conn.hpp,