Index: webrtc/modules/rtp_rtcp/source/h264/h264_common.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/h264/h264_common.cc b/webrtc/modules/rtp_rtcp/source/h264/h264_common.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c355c5ce32602f874edf484c6817582cc3e735a6 |
--- /dev/null |
+++ b/webrtc/modules/rtp_rtcp/source/h264/h264_common.cc |
@@ -0,0 +1,100 @@ |
+/* |
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include "webrtc/modules/rtp_rtcp/source/h264/h264_common.h" |
+ |
+namespace webrtc { |
+ |
+const size_t H264Common::kNaluHeaderSize = 4; |
+const size_t H264Common::kNaluHeaderAndTypeSize = kNaluHeaderSize + 1; |
+const uint8_t kNaluTypeMask = 0x1F; |
+ |
+std::vector<size_t> H264Common::FindNaluStartOffsets(const uint8_t* buffer, |
+ size_t buffer_size) { |
+ // This is sorta like Boyer-Moore, but with only the first optimization step: |
+ // given a 4-byte sequence we're looking at, if the 4th byte isn't 1 or 0, |
+ // skip ahead to the next 4-byte sequence. 0s and 1s are relatively rare, so |
+ // this will skip the majority of reads/checks. |
+ RTC_CHECK_GE(buffer_size, kNaluHeaderSize); |
+ std::vector<size_t> sequences; |
+ const uint8_t* end = buffer + buffer_size - 4; |
+ for (const uint8_t* head = buffer; head < end;) { |
+ if (head[3] > 1) { |
+ head += 4; |
+ } else if (head[3] == 1 && head[2] == 0 && head[1] == 0 && head[0] == 0) { |
+ sequences.push_back(static_cast<size_t>(head - buffer)); |
+ head += 4; |
+ } else { |
+ head++; |
+ } |
+ } |
+ |
+ return sequences; |
+} |
+ |
+H264Common::NaluType webrtc::H264Common::ParseNaluType(uint8_t data) { |
+ return static_cast<NaluType>(data & kNaluTypeMask); |
+} |
+ |
+std::unique_ptr<rtc::ByteBufferWriter> webrtc::H264Common::ParseRbsp( |
+ const uint8_t* data, |
+ size_t length) { |
+ // First, parse out rbsp, which is basically the source buffer minus emulation |
+ // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in |
+ // section 7.3.1 of the H.264 standard. |
+ std::unique_ptr<rtc::ByteBufferWriter> rbsp_buffer( |
+ new rtc::ByteBufferWriter()); |
+ const char* sps_bytes = reinterpret_cast<const char*>(data); |
+ for (size_t i = 0; i < length;) { |
+ // Be careful about over/underflow here. byte_length_ - 3 can underflow, and |
+ // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_ |
+ // above, and that expression will produce the number of bytes left in |
+ // the stream including the byte at i. |
+ if (length - i >= 3 && data[i] == 0 && data[i + 1] == 0 && |
+ data[i + 2] == 3) { |
+ // Two rbsp bytes + the emulation byte. |
+ rbsp_buffer->WriteBytes(sps_bytes + i, 2); |
+ i += 3; |
+ } else { |
+ // Single rbsp byte. |
+ rbsp_buffer->WriteBytes(sps_bytes + i, 1); |
+ i++; |
+ } |
+ } |
+ return rbsp_buffer; |
+} |
+ |
+// Writes bytes into RBSP, adding emulation (0x03) bytes where necessary. Also |
+// removes trailing empty bytes. |
+void webrtc::H264Common::WriteRbsp(const uint8_t* bytes, |
+ size_t length, |
+ rtc::ByteBufferWriter* destination) { |
+ // Walk length backwards to remove any empty bytes at the end. |
noahric
2016/05/18 01:35:06
I don't remember if that's generally correct. It w
sprang_webrtc
2016/05/20 16:11:00
Changed things around so this isn't necessary anym
|
+ while (length > 0 && bytes[length - 1] == 0) |
noahric
2016/05/18 01:35:06
Man, webrtc engineers and hating on braces for sin
sprang_webrtc
2016/05/20 16:11:00
I've been slapping in the back of the head by Pete
noahric
2016/05/26 18:56:52
I'd slap him back for you, except geography interv
|
+ --length; |
+ |
+ bool last_byte_was_null = false; |
+ for (size_t i = 0; i < length; ++i) { |
+ uint8_t byte = bytes[i]; |
+ destination->WriteUInt8(byte); |
+ if (byte == 0) { |
+ if (last_byte_was_null) { |
+ destination->WriteUInt8(0x03u); |
+ last_byte_was_null = false; |
+ } else { |
+ last_byte_was_null = true; |
+ } |
+ } else { |
+ last_byte_was_null = false; |
+ } |
+ } |
+} |
+ |
+} // namespace webrtc |