diff --git a/trunk/src/app/srs_app_rtp_queue.cpp b/trunk/src/app/srs_app_rtp_queue.cpp index 88a72fed9..eb2389760 100644 --- a/trunk/src/app/srs_app_rtp_queue.cpp +++ b/trunk/src/app/srs_app_rtp_queue.cpp @@ -270,7 +270,7 @@ srs_error_t SrsRtpAudioQueue::consume(SrsRtpNackForReceiver* nack, SrsRtpPacket2 } if ((err = SrsRtpQueue::on_consume(nack, pkt)) != srs_success) { - return err; + return srs_error_wrap(err, "consume audio"); } // OK, we got one new RTP packet, which is not in NACK. @@ -336,10 +336,31 @@ void SrsRtpAudioQueue::collect_frames(SrsRtpNackForReceiver* nack, vector(capacity); + queue_ = new SrsRtpRingBuffer(capacity); } SrsRtpVideoQueue::~SrsRtpVideoQueue() @@ -374,25 +395,28 @@ srs_error_t SrsRtpVideoQueue::consume(SrsRtpNackForReceiver* nack, SrsRtpPacket2 { srs_error_t err = srs_success; + SrsRtpVideoPacket* vpkt = new SrsRtpVideoPacket(); + vpkt->pkt = pkt; + uint8_t v = (uint8_t)pkt->nalu_type; if (v == kFuA) { SrsRtpFUAPayload2* payload = dynamic_cast(pkt->payload); if (!payload) { - srs_freep(pkt); + srs_freep(pkt); srs_freep(vpkt); return srs_error_new(ERROR_RTC_RTP_MUXER, "FU-A payload"); } - pkt->video_is_first_packet = payload->start; - pkt->video_is_last_packet = payload->end; - pkt->video_is_idr = (payload->nalu_type == SrsAvcNaluTypeIDR); + vpkt->video_is_first_packet = payload->start; + vpkt->video_is_last_packet = payload->end; + vpkt->video_is_idr = (payload->nalu_type == SrsAvcNaluTypeIDR); } else { - pkt->video_is_first_packet = true; - pkt->video_is_last_packet = true; + vpkt->video_is_first_packet = true; + vpkt->video_is_last_packet = true; if (v == kStapA) { - pkt->video_is_idr = true; + vpkt->video_is_idr = true; } else { - pkt->video_is_idr = (pkt->nalu_type == SrsAvcNaluTypeIDR); + vpkt->video_is_idr = (pkt->nalu_type == SrsAvcNaluTypeIDR); } } @@ -404,7 +428,8 @@ srs_error_t SrsRtpVideoQueue::consume(SrsRtpNackForReceiver* nack, SrsRtpPacket2 } if ((err = SrsRtpQueue::on_consume(nack, pkt)) != srs_success) { - return err; + srs_freep(pkt); srs_freep(vpkt); + return srs_error_wrap(err, "consume video"); } // OK, we got one new RTP packet, which is not in NACK. @@ -421,7 +446,7 @@ srs_error_t SrsRtpVideoQueue::consume(SrsRtpNackForReceiver* nack, SrsRtpPacket2 } // Save packet at the position seq. - queue_->set(seq, pkt); + queue_->set(seq, vpkt); return err; } @@ -430,9 +455,7 @@ void SrsRtpVideoQueue::collect_frames(SrsRtpNackForReceiver* nack, std::vector frame; + vector frame; // When done, next point to the next available packet. uint16_t next = queue_->begin; @@ -488,18 +511,18 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2* // If nack disabled, we ignore any empty packet. if (!nack) { for (; next != queue_->end; ++next) { - SrsRtpPacket2* pkt = queue_->at(next); - if (!pkt) { + SrsRtpVideoPacket* vpkt = queue_->at(next); + if (!vpkt) { continue; } - if (frame.empty() && !pkt->video_is_first_packet) { + if (frame.empty() && !vpkt->video_is_first_packet) { continue; } - frame.push_back(pkt); + frame.push_back(vpkt); - if (pkt->rtp_header.get_marker() || pkt->video_is_last_packet) { + if (vpkt->pkt->rtp_header.get_marker() || vpkt->video_is_last_packet) { found = true; next++; break; @@ -507,26 +530,26 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2* } } else { for (; next != queue_->end; ++next) { - SrsRtpPacket2* pkt = queue_->at(next); + SrsRtpVideoPacket* vpkt = queue_->at(next); // TODO: FIXME: Should not wait for NACK packets. // Not found or in NACK, stop collecting frame. - if (!pkt || nack->find(next) != NULL) { + if (!vpkt || nack->find(next) != NULL) { srs_trace("wait for nack seq=%u", next); return; } // Ignore when the first packet not the start. - if (frame.empty() && !pkt->video_is_first_packet) { + if (frame.empty() && !vpkt->video_is_first_packet) { return; } // OK, collect packet to frame. - frame.push_back(pkt); + frame.push_back(vpkt); // Done, we got the last packet of frame. // @remark Note that the STAP-A is marker false and it's the last packet. - if (pkt->rtp_header.get_marker() || pkt->video_is_last_packet) { + if (vpkt->pkt->rtp_header.get_marker() || vpkt->video_is_last_packet) { found = true; next++; break; @@ -548,38 +571,39 @@ void SrsRtpVideoQueue::collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2* // Merge packets to one packet. covert_frame(frame, ppkt); + + for (int i = 0; i < (int)frame.size(); i++) { + SrsRtpVideoPacket* pkt = frame[i]; + srs_freep(pkt); + } return; } -void SrsRtpVideoQueue::covert_frame(std::vector& frame, SrsRtpPacket2** ppkt) +void SrsRtpVideoQueue::covert_frame(std::vector& frame, SrsRtpPacket2** ppkt) { if (frame.size() == 1) { - *ppkt = frame[0]; + *ppkt = frame[0]->detach(); return; } // If more than one packet in a frame, it must be FU-A. - SrsRtpPacket2* head = frame.at(0); + SrsRtpPacket2* head = frame.at(0)->pkt; SrsAvcNaluType nalu_type = head->nalu_type; // Covert FU-A to one RAW RTP packet. int nn_nalus = 0; for (size_t i = 0; i < frame.size(); ++i) { - SrsRtpPacket2* pkt = frame[i]; - SrsRtpFUAPayload2* payload = dynamic_cast(pkt->payload); + SrsRtpVideoPacket* vpkt = frame[i]; + SrsRtpFUAPayload2* payload = dynamic_cast(vpkt->pkt->payload); if (!payload) { - nn_nalus = 0; - break; + nn_nalus = 0; break; } + nn_nalus += payload->size; } // Invalid packets, ignore. if (nalu_type != (SrsAvcNaluType)kFuA || !nn_nalus) { - for (int i = 0; i < (int)frame.size(); i++) { - SrsRtpPacket2* pkt = frame[i]; - srs_freep(pkt); - } return; } @@ -601,8 +625,8 @@ void SrsRtpVideoQueue::covert_frame(std::vector& frame, SrsRtpPa buf.write_1bytes(head_payload->nri | head_payload->nalu_type); // NALU header. for (size_t i = 0; i < frame.size(); ++i) { - SrsRtpPacket2* pkt = frame[i]; - SrsRtpFUAPayload2* payload = dynamic_cast(pkt->payload); + SrsRtpVideoPacket* vpkt = frame[i]; + SrsRtpFUAPayload2* payload = dynamic_cast(vpkt->pkt->payload); buf.write_bytes(payload->payload, payload->size); } @@ -617,8 +641,8 @@ uint16_t SrsRtpVideoQueue::next_start_of_frame(uint16_t seq) } for (; s != queue_->end; ++s) { - SrsRtpPacket2* pkt = queue_->at(s); - if (pkt && pkt->video_is_first_packet) { + SrsRtpVideoPacket* vpkt = queue_->at(s); + if (vpkt && vpkt->video_is_first_packet) { return s; } } @@ -631,8 +655,8 @@ uint16_t SrsRtpVideoQueue::next_keyframe() uint16_t s = queue_->begin + 1; for (; s != queue_->end; ++s) { - SrsRtpPacket2* pkt = queue_->at(s); - if (pkt && pkt->video_is_idr && pkt->video_is_first_packet) { + SrsRtpVideoPacket* vpkt = queue_->at(s); + if (vpkt && vpkt->video_is_idr && vpkt->video_is_first_packet) { return s; } } diff --git a/trunk/src/app/srs_app_rtp_queue.hpp b/trunk/src/app/srs_app_rtp_queue.hpp index 55628ebf9..b8424f39f 100644 --- a/trunk/src/app/srs_app_rtp_queue.hpp +++ b/trunk/src/app/srs_app_rtp_queue.hpp @@ -270,11 +270,27 @@ public: virtual void collect_frames(SrsRtpNackForReceiver* nack, std::vector& frames); }; +class SrsRtpVideoPacket +{ +public: + // Helper information for video decoder only. + bool video_is_first_packet; + bool video_is_last_packet; + bool video_is_idr; +public: + SrsRtpPacket2* pkt; +public: + SrsRtpVideoPacket(); + virtual ~SrsRtpVideoPacket(); +public: + SrsRtpPacket2* detach(); +}; + class SrsRtpVideoQueue : public SrsRtpQueue { private: bool request_key_frame_; - SrsRtpRingBuffer* queue_; + SrsRtpRingBuffer* queue_; public: SrsRtpVideoQueue(int capacity); virtual ~SrsRtpVideoQueue(); @@ -289,7 +305,7 @@ public: private: virtual void on_overflow(SrsRtpNackForReceiver* nack); virtual void collect_frame(SrsRtpNackForReceiver* nack, SrsRtpPacket2** ppkt); - virtual void covert_frame(std::vector& frame, SrsRtpPacket2** ppkt); + virtual void covert_frame(std::vector& frame, SrsRtpPacket2** ppkt); uint16_t next_start_of_frame(uint16_t seq); uint16_t next_keyframe(); }; diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 7da71f969..bcaac2145 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -277,17 +277,12 @@ SrsRtpPacket2::SrsRtpPacket2() payload = NULL; decode_handler = NULL; - video_is_first_packet = false; - video_is_last_packet = false; - video_is_idr = false; nalu_type = SrsAvcNaluTypeReserved; + original_bytes = NULL; cache_raw = new SrsRtpRawPayload(); cache_fua = new SrsRtpFUAPayload2(); cache_payload = 0; - - original_bytes = NULL; - nn_original_payload = 0; } SrsRtpPacket2::~SrsRtpPacket2() @@ -408,7 +403,6 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) // If user set the decode handler, call it to set the payload. if (decode_handler) { decode_handler->on_before_decode_payload(this, buf, &payload); - nn_original_payload = buf->left(); } // By default, we always use the RAW payload. diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 346077e96..9651edd55 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -114,15 +114,8 @@ public: int padding; // Decoder helper. public: - // TODO: FIXME: Move to video decoder queue SrsRtpVideoQueue. - // Helper information for video decoder only. - bool video_is_first_packet; - bool video_is_last_packet; - bool video_is_idr; // The first byte as nalu type, for video decoder only. SrsAvcNaluType nalu_type; - // The original payload bytes length. - int nn_original_payload; // The original bytes for decoder only, we will free it. char* original_bytes; // Fast cache for performance.