diff --git a/trunk/research/ts_info.cc b/trunk/research/ts_info.cc index eab6fbe96..dfe682428 100644 --- a/trunk/research/ts_info.cc +++ b/trunk/research/ts_info.cc @@ -585,6 +585,7 @@ public: int64_t pts; // 33bits int64_t dts; // 33bits + int64_t pcr; // header size. int packet_header_size; @@ -596,6 +597,10 @@ public: int packet_data_size; char* packet_data; + // for avc. + u_int8_t nal_ref_idc; + u_int8_t nal_unit_type; + TSMessage(); virtual ~TSMessage(); @@ -709,12 +714,15 @@ TSMessage::TSMessage() stream_type = TSStreamTypeReserved; stream_id = 0; packet_start_code_prefix = 0; - pts = dts = 0; + pts = dts = pcr = 0; PES_packet_length = 0; packet_header_size = 0; parsed_packet_size = 0; packet_data_size = 0; packet_data = NULL; + + nal_ref_idc = 0; + nal_unit_type = 0; } TSMessage::~TSMessage() @@ -1596,6 +1604,10 @@ int TSPayload::demux(TSContext* ctx, TSPacket* pkt, u_int8_t* start, u_int8_t* l } if (pid && (pid->type == TSPidTypeVideo || pid->type == TSPidTypeAudio)) { TSMessage* msg = ctx->get_msg(pkt->header->pid); + + if (pkt->adaption_field->pcr > 0) { + msg->pcr = pkt->adaption_field->pcr; + } // flush previous PES_packet_length(0) packets. if (msg->packet_start_code_prefix == 0x01 @@ -2135,6 +2147,10 @@ int consume(TSMessage* msg, AacMuxer* aac_muxer) int8_t nal_unit_type = *pp++; int8_t nal_ref_idc = (nal_unit_type >> 5) & 0x03; nal_unit_type &= 0x1f; + + msg->nal_ref_idc = nal_ref_idc; + msg->nal_unit_type = nal_unit_type; + if (nal_ref_idc != 0) { trace("ts+h264 got an SPS or PPS."); } @@ -2235,6 +2251,18 @@ int main(int argc, char** argv) return -1; } + int64_t pts = msg->pts; + int64_t dts = (msg->dts == 0)? msg->pts : msg->dts; + int64_t pcr = msg->pcr; + static int64_t last_pcr_dts = 0; + trace("demuxer+report id=%d, type=%s, size=%d, dts=%d, pts=%d, cts=%d, pcr=%d, dts-pcr=%d, ref=%d, unit=%d, dts(diff-pcr)=%d", + ctx.ts_packet_count, (msg->type == TSPidTypeVideo)? "video":"audio", + msg->parsed_packet_size, dts, pts, pts - dts, pcr, pcr? dts - pcr : 0, + msg->nal_ref_idc, msg->nal_unit_type, pcr? dts - last_pcr_dts: 0); + if (pcr > 0) { + last_pcr_dts = dts; + } + srs_freep(msg); } } diff --git a/trunk/src/core/srs_core_codec.cpp b/trunk/src/core/srs_core_codec.cpp index fb15c9331..88b270092 100644 --- a/trunk/src/core/srs_core_codec.cpp +++ b/trunk/src/core/srs_core_codec.cpp @@ -115,6 +115,10 @@ SrsCodec::SrsCodec() avc_extra_data = NULL; aac_extra_size = 0; aac_extra_data = NULL; + sequenceParameterSetLength = 0; + sequenceParameterSetNALUnit = NULL; + pictureParameterSetLength = 0; + pictureParameterSetNALUnit = NULL; stream = new SrsStream(); } @@ -125,6 +129,8 @@ SrsCodec::~SrsCodec() srs_freepa(aac_extra_data); srs_freep(stream); + srs_freepa(sequenceParameterSetNALUnit); + srs_freepa(pictureParameterSetNALUnit); } int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) @@ -315,16 +321,67 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) int8_t lengthSizeMinusOne = stream->read_1bytes(); lengthSizeMinusOne &= 0x03; NAL_unit_length = lengthSizeMinusOne; - /** - * skip the following: - * numOfSequenceParameterSets - * donot parse the following: - * sequenceParameterSetLength - * sequenceParameterSetNALUnit - * numOfPictureParameterSets - * pictureParameterSetLength - * pictureParameterSetNALUnit - */ + + // 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_freepa(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_freepa(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) { diff --git a/trunk/src/core/srs_core_codec.hpp b/trunk/src/core/srs_core_codec.hpp index 17d1e2d49..18cc32a5a 100644 --- a/trunk/src/core/srs_core_codec.hpp +++ b/trunk/src/core/srs_core_codec.hpp @@ -250,6 +250,10 @@ public: 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 */ diff --git a/trunk/src/core/srs_core_hls.cpp b/trunk/src/core/srs_core_hls.cpp index e9665e214..97069c705 100644 --- a/trunk/src/core/srs_core_hls.cpp +++ b/trunk/src/core/srs_core_hls.cpp @@ -512,8 +512,13 @@ SrsTSMuxer::SrsTSMuxer() { fd = -1; + // ffmpeg set the start time to the delay time. + base_dts = SRS_HLS_DELAY; + audio_buffer = new SrsCodecBuffer(); video_buffer = new SrsCodecBuffer(); + + got_iframe = false; } SrsTSMuxer::~SrsTSMuxer() @@ -555,7 +560,7 @@ int SrsTSMuxer::write_audio(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam { int ret = ERROR_SUCCESS; - audio_frame.dts = audio_frame.pts = time * 90; + audio_frame.dts = audio_frame.pts = base_dts + time * 90; audio_frame.pid = TS_AUDIO_PID; audio_frame.sid = TS_AUDIO_AAC; @@ -626,12 +631,19 @@ int SrsTSMuxer::write_video(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam { int ret = ERROR_SUCCESS; - video_frame.dts = time * 90; + video_frame.dts = base_dts + time * 90; video_frame.pts = video_frame.dts + sample->cts * 90; video_frame.pid = TS_VIDEO_PID; video_frame.sid = TS_VIDEO_AVC; video_frame.key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; + if (video_frame.key) { + got_iframe = true; + } + if (!got_iframe) { + return ret; + } + static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; video_buffer->append(aud_nal, sizeof(aud_nal)); @@ -646,12 +658,33 @@ int SrsTSMuxer::write_video(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam return ret; } - if (false && video_frame.key && !sps_pps_sent) { - // sample start prefix - video_buffer->append(aud_nal, 4); - // sps and pps - // TODO: do in right way. - video_buffer->append(codec->avc_extra_data, codec->avc_extra_size); + // 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 &= 0x1f; + + // Table 7-1 – NAL unit type codes, page 61 + // 1: Coded slice + if (nal_unit_type == 1) { + sps_pps_sent = false; + } + // 5: Coded slice of an IDR picture + if (nal_unit_type == 5 && !sps_pps_sent) { + // ngx_rtmp_hls_append_sps_pps + if (codec->sequenceParameterSetLength > 0) { + // AnnexB prefix + video_buffer->append(aud_nal, 4); + // sps + video_buffer->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); + } + if (codec->pictureParameterSetLength > 0) { + // AnnexB prefix + video_buffer->append(aud_nal, 4); + // pps + video_buffer->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); + } + } // sample start prefix, '00 00 00 01' or '00 00 01' diff --git a/trunk/src/core/srs_core_hls.hpp b/trunk/src/core/srs_core_hls.hpp index fa10ed0fe..8f08c42c1 100644 --- a/trunk/src/core/srs_core_hls.hpp +++ b/trunk/src/core/srs_core_hls.hpp @@ -81,6 +81,8 @@ private: int fd; std::string path; private: + bool got_iframe; + int64_t base_dts; mpegts_frame audio_frame; SrsCodecBuffer* audio_buffer; mpegts_frame video_frame;