diff options
author | stefan@webrtc.org <stefan@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-07-31 14:59:24 +0000 |
---|---|---|
committer | stefan@webrtc.org <stefan@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-07-31 14:59:24 +0000 |
commit | 2ec560606be6519dc4e32a1e6855b0f362ca498d (patch) | |
tree | 1514bac7209592adb9d466a81135cc964aed3b3f /webrtc/modules/video_coding/main/source/session_info.cc | |
parent | bfe6e081952540bd74b62627a3b910208e33c490 (diff) | |
download | webrtc-2ec560606be6519dc4e32a1e6855b0f362ca498d.tar.gz |
Add H.264 packetization.
This also includes:
- Creating new packetizer and depacketizer interfaces.
- Moved VP8 packetization was H264 packetization and depacketization to these interfaces. This is a work in progress and should be continued to get this 100% generic. This also required changing the return type for RtpFormatVp8::NextPacket(), which now returns bool instead of the index of the first partition.
- Created a Create() factory method for packetizers and depacketizers.
R=niklas.enbom@webrtc.org, pbos@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/21009004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6804 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'webrtc/modules/video_coding/main/source/session_info.cc')
-rw-r--r-- | webrtc/modules/video_coding/main/source/session_info.cc | 141 |
1 files changed, 99 insertions, 42 deletions
diff --git a/webrtc/modules/video_coding/main/source/session_info.cc b/webrtc/modules/video_coding/main/source/session_info.cc index dab3da1383..b50a01ac09 100644 --- a/webrtc/modules/video_coding/main/source/session_info.cc +++ b/webrtc/modules/video_coding/main/source/session_info.cc @@ -14,7 +14,7 @@ #include "webrtc/system_wrappers/interface/logging.h" namespace webrtc { - +namespace { // Used in determining whether a frame is decodable. enum {kRttThreshold = 100}; // Not decodable if Rtt is lower than this. @@ -23,6 +23,11 @@ enum {kRttThreshold = 100}; // Not decodable if Rtt is lower than this. static const float kLowPacketPercentageThreshold = 0.2f; static const float kHighPacketPercentageThreshold = 0.8f; +uint16_t BufferToUWord16(const uint8_t* dataBuffer) { + return (dataBuffer[0] << 8) | dataBuffer[1]; +} +} // namespace + VCMSessionInfo::VCMSessionInfo() : session_nack_(false), complete_(false), @@ -121,9 +126,6 @@ int VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer, VCMPacket& packet = *packet_it; PacketIterator it; - int packet_size = packet.sizeBytes; - packet_size += (packet.insertStartCode ? kH264StartCodeLengthBytes : 0); - // Calculate the offset into the frame buffer for this packet. int offset = 0; for (it = packets_.begin(); it != packet_it; ++it) @@ -131,23 +133,63 @@ int VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer, // Set the data pointer to pointing to the start of this packet in the // frame buffer. - const uint8_t* data = packet.dataPtr; + const uint8_t* packet_buffer = packet.dataPtr; packet.dataPtr = frame_buffer + offset; - packet.sizeBytes = packet_size; - ShiftSubsequentPackets(packet_it, packet_size); + // We handle H.264 STAP-A packets in a special way as we need to remove the + // two length bytes between each NAL unit, and potentially add start codes. + const size_t kH264NALHeaderLengthInBytes = 1; + const size_t kLengthFieldLength = 2; + if (packet.codecSpecificHeader.codecHeader.H264.stap_a) { + size_t required_length = 0; + const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes; + while (nalu_ptr < packet_buffer + packet.sizeBytes) { + uint32_t length = BufferToUWord16(nalu_ptr); + required_length += + length + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0); + nalu_ptr += kLengthFieldLength + length; + } + ShiftSubsequentPackets(packet_it, required_length); + nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes; + uint8_t* frame_buffer_ptr = frame_buffer + offset; + while (nalu_ptr < packet_buffer + packet.sizeBytes) { + uint32_t length = BufferToUWord16(nalu_ptr); + nalu_ptr += kLengthFieldLength; + frame_buffer_ptr += Insert(nalu_ptr, + length, + packet.insertStartCode, + const_cast<uint8_t*>(frame_buffer_ptr)); + nalu_ptr += length; + } + packet.sizeBytes = required_length; + return packet.sizeBytes; + } + ShiftSubsequentPackets( + packet_it, + packet.sizeBytes + + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0)); + + packet.sizeBytes = Insert(packet_buffer, + packet.sizeBytes, + packet.insertStartCode, + const_cast<uint8_t*>(packet.dataPtr)); + return packet.sizeBytes; +} - const unsigned char startCode[] = {0, 0, 0, 1}; - if (packet.insertStartCode) { - memcpy(const_cast<uint8_t*>(packet.dataPtr), startCode, - kH264StartCodeLengthBytes); +size_t VCMSessionInfo::Insert(const uint8_t* buffer, + size_t length, + bool insert_start_code, + uint8_t* frame_buffer) { + if (insert_start_code) { + const unsigned char startCode[] = {0, 0, 0, 1}; + memcpy(frame_buffer, startCode, kH264StartCodeLengthBytes); } - memcpy(const_cast<uint8_t*>(packet.dataPtr - + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0)), - data, - packet.sizeBytes); + memcpy(frame_buffer + (insert_start_code ? kH264StartCodeLengthBytes : 0), + buffer, + length); + length += (insert_start_code ? kH264StartCodeLengthBytes : 0); - return packet_size; + return length; } void VCMSessionInfo::ShiftSubsequentPackets(PacketIterator it, @@ -420,34 +462,49 @@ int VCMSessionInfo::InsertPacket(const VCMPacket& packet, (*rit).seqNum == packet.seqNum && (*rit).sizeBytes > 0) return -2; - // Only insert media packets between first and last packets (when available). - // Placing check here, as to properly account for duplicate packets. - // Check if this is first packet (only valid for some codecs) - // Should only be set for one packet per session. - if (packet.isFirstPacket && first_packet_seq_num_ == -1) { - // The first packet in a frame signals the frame type. - frame_type_ = packet.frameType; - // Store the sequence number for the first packet. - first_packet_seq_num_ = static_cast<int>(packet.seqNum); - } else if (first_packet_seq_num_ != -1 && - !IsNewerSequenceNumber(packet.seqNum, first_packet_seq_num_)) { - LOG(LS_WARNING) << "Received packet with a sequence number which is out of" - "frame boundaries"; - return -3; - } else if (frame_type_ == kFrameEmpty && packet.frameType != kFrameEmpty) { - // Update the frame type with the type of the first media packet. - // TODO(mikhal): Can this trigger? + if (packet.codec == kVideoCodecH264) { frame_type_ = packet.frameType; - } + if (packet.isFirstPacket && + (first_packet_seq_num_ == -1 || + IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum))) { + first_packet_seq_num_ = packet.seqNum; + } + if (packet.markerBit && + (last_packet_seq_num_ == -1 || + IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_))) { + last_packet_seq_num_ = packet.seqNum; + } + } else { + // Only insert media packets between first and last packets (when + // available). + // Placing check here, as to properly account for duplicate packets. + // Check if this is first packet (only valid for some codecs) + // Should only be set for one packet per session. + if (packet.isFirstPacket && first_packet_seq_num_ == -1) { + // The first packet in a frame signals the frame type. + frame_type_ = packet.frameType; + // Store the sequence number for the first packet. + first_packet_seq_num_ = static_cast<int>(packet.seqNum); + } else if (first_packet_seq_num_ != -1 && + !IsNewerSequenceNumber(packet.seqNum, first_packet_seq_num_)) { + LOG(LS_WARNING) << "Received packet with a sequence number which is out " + "of frame boundaries"; + return -3; + } else if (frame_type_ == kFrameEmpty && packet.frameType != kFrameEmpty) { + // Update the frame type with the type of the first media packet. + // TODO(mikhal): Can this trigger? + frame_type_ = packet.frameType; + } - // Track the marker bit, should only be set for one packet per session. - if (packet.markerBit && last_packet_seq_num_ == -1) { - last_packet_seq_num_ = static_cast<int>(packet.seqNum); - } else if (last_packet_seq_num_ != -1 && - IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) { - LOG(LS_WARNING) << "Received packet with a sequence number which is out of" - "frame boundaries"; - return -3; + // Track the marker bit, should only be set for one packet per session. + if (packet.markerBit && last_packet_seq_num_ == -1) { + last_packet_seq_num_ = static_cast<int>(packet.seqNum); + } else if (last_packet_seq_num_ != -1 && + IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) { + LOG(LS_WARNING) << "Received packet with a sequence number which is out " + "of frame boundaries"; + return -3; + } } // The insert operation invalidates the iterator |rit|. |