aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/video_coding/main/source/session_info.cc
diff options
context:
space:
mode:
authorstefan@webrtc.org <stefan@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2014-07-31 14:59:24 +0000
committerstefan@webrtc.org <stefan@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2014-07-31 14:59:24 +0000
commit2ec560606be6519dc4e32a1e6855b0f362ca498d (patch)
tree1514bac7209592adb9d466a81135cc964aed3b3f /webrtc/modules/video_coding/main/source/session_info.cc
parentbfe6e081952540bd74b62627a3b910208e33c490 (diff)
downloadwebrtc-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.cc141
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|.