From a4d3283cdd4c37d24299ac50f5bb3421d1af2089 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 15 Jul 2014 10:44:06 +0800 Subject: [PATCH] refine hls codec sample info. 0.9.161 --- trunk/src/app/srs_app_avc_aac.cpp | 32 +++++--------- trunk/src/app/srs_app_avc_aac.hpp | 70 +++++++++++++++++++++++-------- trunk/src/app/srs_app_hls.cpp | 70 +++++++++++++++---------------- trunk/src/app/srs_app_hls.hpp | 14 +++---- trunk/src/core/srs_core.hpp | 2 +- 5 files changed, 105 insertions(+), 83 deletions(-) diff --git a/trunk/src/app/srs_app_avc_aac.cpp b/trunk/src/app/srs_app_avc_aac.cpp index 93f79a8c2..0d9b622fc 100644 --- a/trunk/src/app/srs_app_avc_aac.cpp +++ b/trunk/src/app/srs_app_avc_aac.cpp @@ -30,26 +30,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -SrsCodecBuffer::SrsCodecBuffer() +SrsCodecSampleUnit::SrsCodecSampleUnit() { size = 0; bytes = NULL; } -void SrsCodecBuffer::append(void* data, int len) +SrsCodecSampleUnit::~SrsCodecSampleUnit() { - 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() @@ -64,7 +52,7 @@ SrsCodecSample::~SrsCodecSample() void SrsCodecSample::clear() { is_video = false; - nb_buffers = 0; + nb_sample_units = 0; cts = 0; frame_type = SrsCodecVideoAVCFrameReserved; @@ -76,20 +64,20 @@ void SrsCodecSample::clear() aac_packet_type = SrsCodecAudioTypeReserved; } -int SrsCodecSample::add_sample(char* bytes, int size) +int SrsCodecSample::add_sample_unit(char* bytes, int size) { int ret = ERROR_SUCCESS; - if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) { + if (nb_sample_units >= 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; + SrsCodecSampleUnit* sample_unit = &sample_units[nb_sample_units++]; + sample_unit->bytes = bytes; + sample_unit->size = size; return ret; } @@ -239,7 +227,7 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample // Raw AAC frame data in UI8 [] // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 - if ((ret = sample->add_sample(stream->data() + stream->pos(), stream->size() - stream->pos())) != ERROR_SUCCESS) { + if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), stream->size() - stream->pos())) != ERROR_SUCCESS) { srs_error("hls add audio sample failed. ret=%d", ret); return ret; } @@ -445,7 +433,7 @@ int SrsAvcAacCodec::video_avc_demux(char* data, int size, SrsCodecSample* sample return ret; } // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. - if ((ret = sample->add_sample(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { + if ((ret = sample->add_sample_unit(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { srs_error("hls add video sample failed. ret=%d", ret); return ret; } diff --git a/trunk/src/app/srs_app_avc_aac.hpp b/trunk/src/app/srs_app_avc_aac.hpp index dff13a36e..4aedaa5cc 100644 --- a/trunk/src/app/srs_app_avc_aac.hpp +++ b/trunk/src/app/srs_app_avc_aac.hpp @@ -89,30 +89,38 @@ enum SrsCodecAudioSoundType }; /** -* buffer indicates the position and size. +* 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 SrsCodecBuffer +class SrsCodecSampleUnit { public: /** - * @remark user must manage the bytes. + * the sample bytes is directly ptr to packet bytes, + * user should never use it when packet destroyed. */ int size; char* bytes; public: - SrsCodecBuffer(); - void append(void* data, int len); -public: - /** - * free the bytes, - * user can invoke it to free the bytes, - * the SrsCodecBuffer never free automatically. - */ - void free(); + 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 { @@ -123,12 +131,14 @@ public: * 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]; + int nb_sample_units; + SrsCodecSampleUnit sample_units[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. + /** + * CompositionTime, video_file_format_spec_v10_1.pdf, page 78. + * cts = pts - dts, where dts = flvheader->timestamp. + */ int32_t cts; public: // video specified @@ -143,13 +153,37 @@ public: 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(); - int add_sample(char* bytes, int size); + /** + * 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. -* to decode the stream of avc/aac for hls. +* +* to demux the FLV/RTMP video/audio packet to sample, +* add each NALUs of h.264 as a sample unit to sample, +* while the entire aac raw data as a sample unit. +* +* for sequence header, +* demux it and save it in the avc_extra_data and aac_extra_data, +* +* for the codec info, such as audio sample rate, +* decode from FLV/RTMP header, then use codec info in sequence +* header to override it. */ class SrsAvcAacCodec { diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 17ea64fab..6138ea75f 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -68,6 +68,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 @@ -195,16 +196,16 @@ public: return ret; } - static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsCodecBuffer* buffer) + static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsBuffer* buffer) { int ret = ERROR_SUCCESS; - if (!buffer->bytes || buffer->size <= 0) { + if (!buffer->bytes() || buffer->length() <= 0) { return ret; } - char* last = buffer->bytes + buffer->size; - char* pos = buffer->bytes; + char* last = buffer->bytes() + buffer->length(); + char* pos = buffer->bytes(); bool first = true; while (pos < last) { @@ -478,7 +479,7 @@ int SrsTSMuxer::open(string _path) return ret; } -int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) +int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsBuffer* ab) { int ret = ERROR_SUCCESS; @@ -489,7 +490,7 @@ int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) return ret; } -int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb) +int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsBuffer* vb) { int ret = ERROR_SUCCESS; @@ -651,7 +652,7 @@ bool SrsHlsMuxer::is_segment_overflow() return current->duration >= hls_fragment; } -int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) +int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsBuffer* ab) { int ret = ERROR_SUCCESS; @@ -661,7 +662,7 @@ int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) return ret; } - if (ab->size <= 0) { + if (ab->length() <= 0) { return ret; } @@ -673,13 +674,12 @@ int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) } // write success, clear and free the buffer - ab->free(); + ab->erase(ab->length()); return ret; } -int SrsHlsMuxer::flush_video( - SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb) +int SrsHlsMuxer::flush_video(SrsMpegtsFrame* af, SrsBuffer* ab, SrsMpegtsFrame* vf, SrsBuffer* vb) { int ret = ERROR_SUCCESS; @@ -699,7 +699,7 @@ int SrsHlsMuxer::flush_video( } // write success, clear and free the buffer - vb->free(); + vb->erase(vb->length()); return ret; } @@ -962,8 +962,8 @@ SrsHlsCache::SrsHlsCache() { aac_jitter = new SrsHlsAacJitter(); - ab = new SrsCodecBuffer(); - vb = new SrsCodecBuffer(); + ab = new SrsBuffer(); + vb = new SrsBuffer(); af = new SrsMpegtsFrame(); vf = new SrsMpegtsFrame(); @@ -975,8 +975,8 @@ SrsHlsCache::~SrsHlsCache() { srs_freep(aac_jitter); - ab->free(); - vb->free(); + ab->erase(ab->length()); + vb->erase(vb->length()); srs_freep(ab); srs_freep(vb); @@ -1051,7 +1051,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t int ret = ERROR_SUCCESS; // start buffer, set the af - if (ab->size == 0) { + if (ab->length() == 0) { pts = aac_jitter->on_buffer_start(pts, sample->sound_rate, codec->aac_sample_rate); af->dts = af->pts = audio_buffer_start_pts = pts; @@ -1067,7 +1067,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t } // flush if buffer exceed max size. - if (ab->size > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) { + if (ab->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) { if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { return ret; } @@ -1159,11 +1159,11 @@ int SrsHlsCache::cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; - for (int i = 0; i < sample->nb_buffers; i++) { - SrsCodecBuffer* buf = &sample->buffers[i]; - int32_t size = buf->size; + for (int i = 0; i < sample->nb_sample_units; i++) { + SrsCodecSampleUnit* sample_unit = &sample->sample_units[i]; + int32_t size = sample_unit->size; - if (!buf->bytes || size <= 0 || size > 0x1fff) { + if (!sample_unit->bytes || size <= 0 || size > 0x1fff) { ret = ERROR_HLS_AAC_FRAME_LENGTH; srs_error("invalid aac frame length=%d, ret=%d", size, ret); return ret; @@ -1215,8 +1215,8 @@ int SrsHlsCache::cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample) adts_header[5] |= 0x1f; // copy to audio buffer - ab->append(adts_header, sizeof(adts_header)); - ab->append(buf->bytes, buf->size); + ab->append((const char*)adts_header, sizeof(adts_header)); + ab->append(sample_unit->bytes, sample_unit->size); } return ret; @@ -1239,11 +1239,11 @@ int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample) * xxxxxxx // data bytes. * so, for each sample, we append header in aud_nal, then appends the bytes in sample. */ - for (int i = 0; i < sample->nb_buffers; i++) { - SrsCodecBuffer* buf = &sample->buffers[i]; - int32_t size = buf->size; + for (int i = 0; i < sample->nb_sample_units; i++) { + SrsCodecSampleUnit* sample_unit = &sample->sample_units[i]; + int32_t size = sample_unit->size; - if (!buf->bytes || size <= 0) { + if (!sample_unit->bytes || size <= 0) { ret = ERROR_HLS_AVC_SAMPLE_SIZE; srs_error("invalid avc sample length=%d, ret=%d", size, ret); return ret; @@ -1259,7 +1259,7 @@ int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample) // 5bits, 7.3.1 NAL unit syntax, // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. u_int8_t nal_unit_type; - nal_unit_type = *buf->bytes; + nal_unit_type = *sample_unit->bytes; nal_unit_type &= 0x1f; // @see: ngx_rtmp_hls_video @@ -1277,7 +1277,7 @@ int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample) } if (nal_unit_type == 1 || nal_unit_type == 5 || nal_unit_type == 6) { // for type 6, append a aud with type 9. - vb->append(aud_nal, sizeof(aud_nal)); + vb->append((const char*)aud_nal, sizeof(aud_nal)); aud_sent = true; } } @@ -1290,13 +1290,13 @@ int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample) // @see: ngx_rtmp_hls_append_sps_pps if (codec->sequenceParameterSetLength > 0) { // AnnexB prefix, for sps always 4 bytes header - vb->append(aud_nal, 4); + vb->append((const char*)aud_nal, 4); // sps vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); } if (codec->pictureParameterSetLength > 0) { // AnnexB prefix, for pps always 4 bytes header - vb->append(aud_nal, 4); + vb->append((const char*)aud_nal, 4); // pps vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); } @@ -1318,13 +1318,13 @@ int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample) u_int8_t* end = p + 3; // first AnnexB prefix is long (4 bytes) - if (vb->size == 0) { + if (vb->length() == 0) { p = aud_nal; } - vb->append(p, end - p); + vb->append((const char*)p, end - p); // sample data - vb->append(buf->bytes, buf->size); + vb->append(sample_unit->bytes, sample_unit->size); } return ret; diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 5197f5d1e..8a52cef70 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -50,9 +50,9 @@ extern int aac_sample_rates[]; #include #include +class SrsBuffer; class SrsSharedPtrMessage; class SrsCodecSample; -class SrsCodecBuffer; class SrsMpegtsFrame; class SrsAmf0Object; class SrsRtmpJitter; @@ -109,8 +109,8 @@ public: virtual ~SrsTSMuxer(); public: virtual int open(std::string _path); - virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); - virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb); + virtual int write_audio(SrsMpegtsFrame* af, SrsBuffer* ab); + virtual int write_video(SrsMpegtsFrame* vf, SrsBuffer* vb); virtual void close(); }; @@ -196,8 +196,8 @@ public: * that is whether the current segment duration >= the segment in config */ virtual bool is_segment_overflow(); - virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); - virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb); + virtual int flush_audio(SrsMpegtsFrame* af, SrsBuffer* ab); + virtual int flush_video(SrsMpegtsFrame* af, SrsBuffer* ab, SrsMpegtsFrame* vf, SrsBuffer* vb); /** * close segment(ts). * @param log_desc the description for log. @@ -231,9 +231,9 @@ class SrsHlsCache private: // current frame and buffer SrsMpegtsFrame* af; - SrsCodecBuffer* ab; + SrsBuffer* ab; SrsMpegtsFrame* vf; - SrsCodecBuffer* vb; + SrsBuffer* vb; private: // the audio cache buffer start pts, to flush audio if full. int64_t audio_buffer_start_pts; diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 8a238e58b..f9a3bacbc 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR "0" #define VERSION_MINOR "9" -#define VERSION_REVISION "160" +#define VERSION_REVISION "161" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "SRS"