diff --git a/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.cc b/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.cc deleted file mode 100644 index 3551782f36..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.cc +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (c) 2011 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 "bitstream_builder.h" - -#include - -namespace webrtc { -BitstreamBuilder::BitstreamBuilder(uint8_t* data, const uint32_t dataSize) : - _data(data), - _dataSize(dataSize), - _byteOffset(0), - _bitOffset(0) -{ - memset(data, 0, dataSize); -} - -uint32_t -BitstreamBuilder::Length() const -{ - return _byteOffset+ (_bitOffset?1:0); -} - -int32_t -BitstreamBuilder::Add1Bit(const uint8_t bit) -{ - // sanity - if(_bitOffset + 1 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bit); - return 0; -} - -void -BitstreamBuilder::Add1BitWithoutSanity(const uint8_t bit) -{ - if(bit & 0x1) - { - _data[_byteOffset] += (1 << (7-_bitOffset)); - } - - if(_bitOffset == 7) - { - // last bit in byte - _bitOffset = 0; - _byteOffset++; - } else - { - _bitOffset++; - } -} - -int32_t -BitstreamBuilder::Add2Bits(const uint8_t bits) -{ - // sanity - if(_bitOffset + 2 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bits >> 1); - Add1BitWithoutSanity(bits); - return 0; -} - -int32_t -BitstreamBuilder::Add3Bits(const uint8_t bits) -{ - // sanity - if(_bitOffset + 3 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bits >> 2); - Add1BitWithoutSanity(bits >> 1); - Add1BitWithoutSanity(bits); - return 0; -} - -int32_t -BitstreamBuilder::Add4Bits(const uint8_t bits) -{ - // sanity - if(_bitOffset + 4 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bits >> 3); - Add1BitWithoutSanity(bits >> 2); - Add1BitWithoutSanity(bits >> 1); - Add1BitWithoutSanity(bits); - return 0; -} - -int32_t -BitstreamBuilder::Add5Bits(const uint8_t bits) -{ - // sanity - if(_bitOffset + 5 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bits >> 4); - Add1BitWithoutSanity(bits >> 3); - Add1BitWithoutSanity(bits >> 2); - Add1BitWithoutSanity(bits >> 1); - Add1BitWithoutSanity(bits); - return 0; -} - -int32_t -BitstreamBuilder::Add6Bits(const uint8_t bits) -{ - // sanity - if(_bitOffset + 6 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bits >> 5); - Add1BitWithoutSanity(bits >> 4); - Add1BitWithoutSanity(bits >> 3); - Add1BitWithoutSanity(bits >> 2); - Add1BitWithoutSanity(bits >> 1); - Add1BitWithoutSanity(bits); - return 0; -} - -int32_t -BitstreamBuilder::Add7Bits(const uint8_t bits) -{ - // sanity - if(_bitOffset + 7 > 8) - { - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - } - Add1BitWithoutSanity(bits >> 6); - Add1BitWithoutSanity(bits >> 5); - Add1BitWithoutSanity(bits >> 4); - Add1BitWithoutSanity(bits >> 3); - Add1BitWithoutSanity(bits >> 2); - Add1BitWithoutSanity(bits >> 1); - Add1BitWithoutSanity(bits); - return 0; -} - -int32_t -BitstreamBuilder::Add8Bits(const uint8_t bits) -{ - // sanity - if(_dataSize < Length()+1) - { - // not enough space in buffer - return -1; - } - if(_bitOffset == 0) - { - _data[_byteOffset] = bits; - } else - { - _data[_byteOffset] += (bits >> _bitOffset); - _data[_byteOffset+1] += (bits << (8-_bitOffset)); - } - _byteOffset++; - return 0; -} - -int32_t -BitstreamBuilder::Add16Bits(const uint16_t bits) -{ - // sanity - if(_dataSize < Length()+2) - { - // not enough space in buffer - return -1; - } - if(_bitOffset == 0) - { - _data[_byteOffset] = (uint8_t)(bits >> 8); - _data[_byteOffset+1] = (uint8_t)(bits); - } else - { - _data[_byteOffset] += (uint8_t)(bits >> (_bitOffset + 8)); - _data[_byteOffset+1] += (uint8_t)(bits >> _bitOffset); - _data[_byteOffset+2] += (uint8_t)(bits << (8-_bitOffset)); - } - _byteOffset += 2; - return 0; -} - -int32_t -BitstreamBuilder::Add24Bits(const uint32_t bits) -{ - // sanity - if(_dataSize < Length()+3) - { - // not enough space in buffer - return -1; - } - if(_bitOffset == 0) - { - _data[_byteOffset] = (uint8_t)(bits >> 16); - _data[_byteOffset+1] = (uint8_t)(bits >> 8); - _data[_byteOffset+2] = (uint8_t)(bits); - } else - { - _data[_byteOffset] += (uint8_t)(bits >> (_bitOffset+16)); - _data[_byteOffset+1] += (uint8_t)(bits >> (_bitOffset+8)); - _data[_byteOffset+2] += (uint8_t)(bits >> (_bitOffset)); - _data[_byteOffset+3] += (uint8_t)(bits << (8-_bitOffset)); - } - _byteOffset += 3; - return 0; -} - -int32_t -BitstreamBuilder::Add32Bits(const uint32_t bits) -{ - // sanity - if(_dataSize < Length()+4) - { - // not enough space in buffer - return -1; - } - if(_bitOffset == 0) - { - _data[_byteOffset] = (uint8_t)(bits >> 24); - _data[_byteOffset+1] = (uint8_t)(bits >> 16); - _data[_byteOffset+2] = (uint8_t)(bits >> 8); - _data[_byteOffset+3] = (uint8_t)(bits); - } else - { - _data[_byteOffset] += (uint8_t)(bits >> (_bitOffset+24)); - _data[_byteOffset+1] += (uint8_t)(bits >> (_bitOffset+16)); - _data[_byteOffset+2] += (uint8_t)(bits >> (_bitOffset+8)); - _data[_byteOffset+3] += (uint8_t)(bits >> (_bitOffset)); - _data[_byteOffset+4] += (uint8_t)(bits << (8-_bitOffset)); - } - _byteOffset += 4; - return 0; -} - -// Exp-Golomb codes -/* - with "prefix" and "suffix" bits and assignment to codeNum ranges (informative) - Bit string form Range of codeNum - 1 0 - 0 1 x0 1..2 2bits-1 - 0 0 1 x1 x0 3..6 3bits-1 - 0 0 0 1 x2 x1 x0 7..14 4bits-1 - 0 0 0 0 1 x3 x2 x1 x0 15..30 - 0 0 0 0 0 1 x4 x3 x2 x1 x0 31..62 -*/ -int32_t -BitstreamBuilder::AddUE(const uint32_t value) -{ - // un-rolled on 8 bit base to avoid too deep if else chain - if(value < 0x0000ffff) - { - if(value < 0x000000ff) - { - if(value == 0) - { - if(AddPrefix(0) != 0) - { - return -1; - } - } else if(value < 3) - { - if(AddPrefix(1) != 0) - { - return -1; - } - AddSuffix(1, value-1); - } else if(value < 7) - { - if(AddPrefix(2) != 0) - { - return -1; - } - AddSuffix(2, value-3); - } else if(value < 15) - { - if(AddPrefix(3) != 0) - { - return -1; - } - AddSuffix(3, value-7); - } else if(value < 31) - { - if(AddPrefix(4) != 0) - { - return -1; - } - AddSuffix(4, value-15); - } else if(value < 63) - { - if(AddPrefix(5) != 0) - { - return -1; - } - AddSuffix(5, value-31); - } else if(value < 127) - { - if(AddPrefix(6) != 0) - { - return -1; - } - AddSuffix(6, value-63); - } else - { - if(AddPrefix(7) != 0) - { - return -1; - } - AddSuffix(7, value-127); - } - }else - { - if(value < 0x000001ff) - { - if(AddPrefix(8) != 0) - { - return -1; - } - AddSuffix(8, value-0x000000ff); - } else if(value < 0x000003ff) - { - if(AddPrefix(9) != 0) - { - return -1; - } - AddSuffix(9, value-0x000001ff); - } else if(value < 0x000007ff) - { - if(AddPrefix(10) != 0) - { - return -1; - } - AddSuffix(10, value-0x000003ff); - } else if(value < 0x00000fff) - { - if(AddPrefix(11) != 0) - { - return -1; - } - AddSuffix(1, value-0x000007ff); - } else if(value < 0x00001fff) - { - if(AddPrefix(12) != 0) - { - return -1; - } - AddSuffix(12, value-0x00000fff); - } else if(value < 0x00003fff) - { - if(AddPrefix(13) != 0) - { - return -1; - } - AddSuffix(13, value-0x00001fff); - } else if(value < 0x00007fff) - { - if(AddPrefix(14) != 0) - { - return -1; - } - AddSuffix(14, value-0x00003fff); - } else - { - if(AddPrefix(15) != 0) - { - return -1; - } - AddSuffix(15, value-0x00007fff); - } - } - }else - { - if(value < 0x00ffffff) - { - if(value < 0x0001ffff) - { - if(AddPrefix(16) != 0) - { - return -1; - } - AddSuffix(16, value-0x0000ffff); - } else if(value < 0x0003ffff) - { - if(AddPrefix(17) != 0) - { - return -1; - } - AddSuffix(17, value-0x0001ffff); - } else if(value < 0x0007ffff) - { - if(AddPrefix(18) != 0) - { - return -1; - } - AddSuffix(18, value-0x0003ffff); - } else if(value < 0x000fffff) - { - if(AddPrefix(19) != 0) - { - return -1; - } - AddSuffix(19, value-0x0007ffff); - } else if(value < 0x001fffff) - { - if(AddPrefix(20) != 0) - { - return -1; - } - AddSuffix(20, value-0x000fffff); - } else if(value < 0x003fffff) - { - if(AddPrefix(21) != 0) - { - return -1; - } - AddSuffix(21, value-0x001fffff); - } else if(value < 0x007fffff) - { - if(AddPrefix(22) != 0) - { - return -1; - } - AddSuffix(22, value-0x003fffff); - } else - { - if(AddPrefix(23) != 0) - { - return -1; - } - AddSuffix(23, value-0x007fffff); - } - } else - { - if(value < 0x01ffffff) - { - if(AddPrefix(24) != 0) - { - return -1; - } - AddSuffix(24, value-0x00ffffff); - } else if(value < 0x03ffffff) - { - if(AddPrefix(25) != 0) - { - return -1; - } - AddSuffix(25, value-0x01ffffff); - } else if(value < 0x07ffffff) - { - if(AddPrefix(26) != 0) - { - return -1; - } - AddSuffix(26, value-0x03ffffff); - } else if(value < 0x0fffffff) - { - if(AddPrefix(27) != 0) - { - return -1; - } - AddSuffix(27, value-0x07ffffff); - } else if(value < 0x1fffffff) - { - if(AddPrefix(28) != 0) - { - return -1; - } - AddSuffix(28, value-0x0fffffff); - } else if(value < 0x3fffffff) - { - if(AddPrefix(29) != 0) - { - return -1; - } - AddSuffix(29, value-0x1fffffff); - } else if(value < 0x7fffffff) - { - if(AddPrefix(30) != 0) - { - return -1; - } - AddSuffix(30, value-0x3fffffff); - } else if(value < 0xffffffff) - { - if(AddPrefix(31) != 0) - { - return -1; - } - AddSuffix(31, value-0x7ffffff); - } else - { - if(AddPrefix(32) != 0) - { - return -1; - } - AddSuffix(32, 0); // exactly 0xffffffff - } - } - } - return 0; -} - -int32_t -BitstreamBuilder::AddPrefix(const uint8_t numZeros) -{ - // sanity for the sufix too - uint32_t numBitsToAdd = numZeros * 2 + 1; - if(((_dataSize - _byteOffset) *8 + 8-_bitOffset) < numBitsToAdd) - { - return -1; - } - - // add numZeros - for (uint32_t i = 0; i < numZeros; i++) - { - Add1Bit(0); - } - Add1Bit(1); - return 0; -} - -void -BitstreamBuilder::AddSuffix(const uint8_t numBits, const uint32_t rest) -{ - // most significant bit first - for(int32_t i = numBits - 1; i >= 0; i--) - { - if(( rest >> i) & 0x1) - { - Add1Bit(1); - }else - { - Add1Bit(0); - } - } -} -} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.h b/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.h deleted file mode 100644 index bf1efaf7c9..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/bitstream_builder.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_BUILDER_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_BUILDER_H_ - -#include "webrtc/typedefs.h" - -namespace webrtc { -class BitstreamBuilder -{ -public: - BitstreamBuilder(uint8_t* data, const uint32_t dataSize); - - uint32_t Length() const; - - int32_t Add1Bit(const uint8_t bit); - int32_t Add2Bits(const uint8_t bits); - int32_t Add3Bits(const uint8_t bits); - int32_t Add4Bits(const uint8_t bits); - int32_t Add5Bits(const uint8_t bits); - int32_t Add6Bits(const uint8_t bits); - int32_t Add7Bits(const uint8_t bits); - int32_t Add8Bits(const uint8_t bits); - int32_t Add16Bits(const uint16_t bits); - int32_t Add24Bits(const uint32_t bits); - int32_t Add32Bits(const uint32_t bits); - - // Exp-Golomb codes - int32_t AddUE(const uint32_t value); - -private: - int32_t AddPrefix(const uint8_t numZeros); - void AddSuffix(const uint8_t numBits, const uint32_t rest); - void Add1BitWithoutSanity(const uint8_t bit); - - uint8_t* _data; - uint32_t _dataSize; - - uint32_t _byteOffset; - uint8_t _bitOffset; -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_BUILDER_H_ diff --git a/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.cc b/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.cc deleted file mode 100644 index d6505d2139..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.cc +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2011 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 "bitstream_parser.h" - -namespace webrtc { -BitstreamParser::BitstreamParser(const uint8_t* data, const uint32_t dataLength) : - _data(data), - _dataLength(dataLength), - _byteOffset(0), - _bitOffset(0) -{ -} - // todo should we have any error codes from this? - -uint8_t -BitstreamParser::Get1Bit() -{ - uint8_t retVal = 0x1 & (_data[_byteOffset] >> (7-_bitOffset++)); - - // prepare next byte - if(_bitOffset == 8) - { - _bitOffset = 0; - _byteOffset++; - } - return retVal; -} - -uint8_t -BitstreamParser::Get2Bits() -{ - uint8_t retVal = (Get1Bit() << 1); - retVal += Get1Bit(); - return retVal; -} - -uint8_t -BitstreamParser::Get3Bits() -{ - uint8_t retVal = (Get1Bit() << 2); - retVal += (Get1Bit() << 1); - retVal += Get1Bit(); - return retVal; -} - -uint8_t -BitstreamParser::Get4Bits() -{ - uint8_t retVal = (Get1Bit() << 3); - retVal += (Get1Bit() << 2); - retVal += (Get1Bit() << 1); - retVal += Get1Bit(); - return retVal; -} - -uint8_t -BitstreamParser::Get5Bits() -{ - uint8_t retVal = (Get1Bit() << 4); - retVal += (Get1Bit() << 3); - retVal += (Get1Bit() << 2); - retVal += (Get1Bit() << 1); - retVal += Get1Bit(); - return retVal; -} - -uint8_t -BitstreamParser::Get6Bits() -{ - uint8_t retVal = (Get1Bit() << 5); - retVal += (Get1Bit() << 4); - retVal += (Get1Bit() << 3); - retVal += (Get1Bit() << 2); - retVal += (Get1Bit() << 1); - retVal += Get1Bit(); - return retVal; -} - -uint8_t -BitstreamParser::Get7Bits() -{ - uint8_t retVal = (Get1Bit() << 6); - retVal += (Get1Bit() << 5); - retVal += (Get1Bit() << 4); - retVal += (Get1Bit() << 3); - retVal += (Get1Bit() << 2); - retVal += (Get1Bit() << 1); - retVal += Get1Bit(); - return retVal; -} - -uint8_t -BitstreamParser::Get8Bits() -{ - uint16_t retVal; - - if(_bitOffset != 0) - { - // read 16 bits - retVal = (_data[_byteOffset] << 8)+ (_data[_byteOffset+1]) ; - retVal = retVal >> (8-_bitOffset); - } else - { - retVal = _data[_byteOffset]; - } - _byteOffset++; - return (uint8_t)retVal; -} - -uint16_t -BitstreamParser::Get16Bits() -{ - uint32_t retVal; - - if(_bitOffset != 0) - { - // read 24 bits - retVal = (_data[_byteOffset] << 16) + (_data[_byteOffset+1] << 8) + (_data[_byteOffset+2]); - retVal = retVal >> (8-_bitOffset); - }else - { - // read 16 bits - retVal = (_data[_byteOffset] << 8) + (_data[_byteOffset+1]) ; - } - _byteOffset += 2; - return (uint16_t)retVal; -} - -uint32_t -BitstreamParser::Get24Bits() -{ - uint32_t retVal; - - if(_bitOffset != 0) - { - // read 32 bits - retVal = (_data[_byteOffset] << 24) + (_data[_byteOffset+1] << 16) + (_data[_byteOffset+2] << 8) + (_data[_byteOffset+3]); - retVal = retVal >> (8-_bitOffset); - }else - { - // read 24 bits - retVal = (_data[_byteOffset] << 16) + (_data[_byteOffset+1] << 8) + (_data[_byteOffset+2]) ; - } - _byteOffset += 3; - return retVal & 0x00ffffff; // we need to clean up the high 8 bits -} - -uint32_t -BitstreamParser::Get32Bits() -{ - uint32_t retVal; - - if(_bitOffset != 0) - { - // read 40 bits - uint64_t tempVal = _data[_byteOffset]; - tempVal <<= 8; - tempVal += _data[_byteOffset+1]; - tempVal <<= 8; - tempVal += _data[_byteOffset+2]; - tempVal <<= 8; - tempVal += _data[_byteOffset+3]; - tempVal <<= 8; - tempVal += _data[_byteOffset+4]; - tempVal >>= (8-_bitOffset); - - retVal = uint32_t(tempVal); - }else - { - // read 32 bits - retVal = (_data[_byteOffset]<< 24) + (_data[_byteOffset+1] << 16) + (_data[_byteOffset+2] << 8) + (_data[_byteOffset+3]) ; - } - _byteOffset += 4; - return retVal; -} - -// Exp-Golomb codes -/* - with "prefix" and "suffix" bits and assignment to codeNum ranges (informative) - Bit string form Range of codeNum - 1 0 - 0 1 x0 1..2 - 0 0 1 x1 x0 3..6 - 0 0 0 1 x2 x1 x0 7..14 - 0 0 0 0 1 x3 x2 x1 x0 15..30 - 0 0 0 0 0 1 x4 x3 x2 x1 x0 31..62 -*/ - -uint32_t -BitstreamParser::GetUE() -{ - uint32_t retVal = 0; - uint8_t numLeadingZeros = 0; - - while (Get1Bit() != 1) - { - numLeadingZeros++; - } - // prefix - retVal = (1 << numLeadingZeros) - 1; - - // suffix - while (numLeadingZeros) - { - retVal += (Get1Bit() << --numLeadingZeros); - } - return retVal; -} -} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.h b/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.h deleted file mode 100644 index 6e3d307710..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/bitstream_parser.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ - -#include "webrtc/typedefs.h" - -namespace webrtc { -class BitstreamParser -{ -public: - BitstreamParser(const uint8_t* data, const uint32_t dataLength); - - uint8_t Get1Bit(); - uint8_t Get2Bits(); - uint8_t Get3Bits(); - uint8_t Get4Bits(); - uint8_t Get5Bits(); - uint8_t Get6Bits(); - uint8_t Get7Bits(); - uint8_t Get8Bits(); - uint16_t Get16Bits(); - uint32_t Get24Bits(); - uint32_t Get32Bits(); - - // Exp-Golomb codes - uint32_t GetUE(); - -private: - const uint8_t* _data; - const uint32_t _dataLength; - - uint32_t _byteOffset; - uint8_t _bitOffset; -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ diff --git a/webrtc/modules/rtp_rtcp/source/H264/h264_information.cc b/webrtc/modules/rtp_rtcp/source/H264/h264_information.cc deleted file mode 100644 index ddb34eb6d9..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/h264_information.cc +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright (c) 2011 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 -#include "h264_information.h" - -//#define DEBUG_SEI_MESSAGE 1 - -#ifdef DEBUG_SEI_MESSAGE - #include "bitstream_parser.h" - #include - #include - - uint32_t BitRateBPS(uint16_t x ) - { - return (x & 0x3fff) * uint32_t(pow(10.0f,(2 + (x >> 14)))); - } - -#endif - -namespace webrtc { -H264Information::H264Information(const bool SVC) - : _SVC(SVC) - -{ -} - -H264Information::~H264Information() -{ - -} - -void -H264Information::Reset() -{ - _parsedLength = 0; - _remLength = 0; - _length = 0; - _info.numNALUs = 0; - _info.numLayers = 0; - - memset(_info.startCodeSize, 0, sizeof(_info.startCodeSize)); - memset(_info.payloadSize, 0, sizeof(_info.payloadSize)); - memset(_info.NRI, 0, sizeof(_info.NRI)); - memset(_info.type, 0, sizeof(_info.type)); - memset(_info.accLayerSize, 0, sizeof(_info.accLayerSize)); - - for (int32_t i = 0; i < KMaxNumberOfNALUs; i++) - { - _info.SVCheader[i].idr = 0; - _info.SVCheader[i].priorityID = 0; - _info.SVCheader[i].interLayerPred = 0; - _info.SVCheader[i].dependencyID = 0; - _info.SVCheader[i].qualityID = 0; - _info.SVCheader[i].temporalID = 0; - _info.SVCheader[i].useRefBasePic = 0; - _info.SVCheader[i].discardable = 0; - _info.SVCheader[i].output = 0; - - _info.PACSI[i].X = 0; - _info.PACSI[i].Y = 0; -// _info.PACSI[i].T = 0; - _info.PACSI[i].A = 0; - _info.PACSI[i].P = 0; - _info.PACSI[i].C = 0; - _info.PACSI[i].S = 0; - _info.PACSI[i].E = 0; - _info.PACSI[i].TL0picIDx = 0; - _info.PACSI[i].IDRpicID = 0; - _info.PACSI[i].DONC = 0; - _info.PACSI[i].numSEINALUs = 0; - _info.PACSI[i].NALlength = 5; - } -} - -/******************************************************************************* - * int32_t GetInfo(const uint8_t* ptrEncodedBuffer, - * const uint32_t length, - * const H264Info*& ptrInfo); - * - * Gets information from an encoded stream. - * - * Input: - * - ptrEncodedBuffer : Pointer to encoded stream. - * - length : Length in bytes of encoded stream. - * - * Output: - * - ptrInfo : Pointer to struct with H.264 info. - * - * Return value: - * - 0 : ok - * - (-1) : Error - */ -int32_t -H264Information::GetInfo(const uint8_t* ptrEncodedBuffer, - const uint32_t length, - const H264Info*& ptrInfo) -{ - if (!ptrEncodedBuffer || length < 4) - { - return -1; - } - - if (!HasInfo(length)) - { - if (-1 == FindInfo(ptrEncodedBuffer, length)) - { - Reset(); - return -1; - } - } - ptrInfo = &_info; - return 0; -} - -RtpVideoCodecTypes -H264Information::Type() -{ - if(_SVC) - { - return RTP_H264_SVCVideo; - } - return RTP_H264Video; -} - - -/******************************************************************************* - * bool HasInfo(const uint32_t length); - * - * Checks if information has already been stored for this encoded stream. - * - * Input: - * - length : Length in bytes of encoded stream. - * - * Return value: - * - true (false) : Information has (not) been stored. - */ - -bool -H264Information::HasInfo(const uint32_t length) -{ - if (!_info.numNALUs) - { - return false; - } - - // has info, make sure current length matches info length - if (length != _length) - { - Reset(); - return false; - } - - return true; -} - -/******************************************************************************* - * int32_t FindInfo(const uint8_t* ptrEncodedBuffer, - * const uint32_t length); - * - * Parses the encoded stream. - * - * Input: - * - ptrEncodedBuffer : Pointer to encoded stream. - * - length : Length in bytes of encoded stream. - * - * Return value: - * - 0 : ok - * - (-1) : Error - */ -int32_t -H264Information::FindInfo(const uint8_t* ptrEncodedBuffer, const uint32_t length) -{ - _ptrData = ptrEncodedBuffer; - _length = length; - _parsedLength = 0; - _remLength = length; - - do - { - // Get start code length - if (FindNALUStartCodeSize() == -1) - { - Reset(); - return -1; - } - - // Get NAL unit payload size - int32_t foundLast = FindNALU(); - if (foundLast == -1) - { - Reset(); - return -1; - } - - // Validate parsed length - if (_parsedLength > _length) - { - Reset(); - return -1; - } - - // Get NRI - GetNRI(); - - // Get type - if (FindNALUType() == -1) - { - Reset(); - return -1; - } - - // Set layer start end bit - SetLayerSEBit(foundLast); - - - // Last NAL unit found? - if (foundLast == 1) - { - if (_parsedLength != _length) - { - Reset(); - return -1; - } - _info.numNALUs++; - return SetLayerLengths(); - } - - // Next NAL unit - _ptrData += (_info.startCodeSize[_info.numNALUs] + _info.payloadSize[_info.numNALUs]); - _remLength -= (_info.startCodeSize[_info.numNALUs] + _info.payloadSize[_info.numNALUs]); - _info.numNALUs++; - - // Validate memory allocation - if (_info.numNALUs >= KMaxNumberOfNALUs) - { - Reset(); - return -1; - } - } - while(true); - - return 0; -} - -/******************************************************************************* - * int32_t FindNALUStartCodeSize(); - * - * Finds the start code length of the current NAL unit. - * - * Output: - * - _info.startCodeSize[currentNALU] : Start code length in bytes of NAL unit. - * - * Return value: - * - 0 : ok - * - (-1) : Error - */ -int32_t -H264Information::FindNALUStartCodeSize() -{ - // NAL unit start code. Ex. {0,0,1} or {0,0,0,1} - for (uint32_t i = 2; i < _remLength; i++) - { - if (_ptrData[i] == 1 && _ptrData[i - 1] == 0 && _ptrData[i - 2] == 0) - { - _info.startCodeSize[_info.numNALUs] = uint8_t(i + 1); - return 0; - } - } - return -1; -} - -/******************************************************************************* - * int32_t FindNALU(); - * - * Finds the length of the current NAL unit. - * - * Output: - * - _info.payloadSize[currentNALU] : Payload length in bytes of NAL unit - * (start code length not included). - * - _parsedLength : Current parsed length in bytes. - * - * Return value: - * - 1 : ok. Last NAL unit found. - * - 0 : ok - * - (-1) : Error - */ -int32_t -H264Information::FindNALU() -{ - for (uint32_t i = _info.startCodeSize[_info.numNALUs]; i < _remLength - 2; i += 2) - { - if (_ptrData[i] == 0) - { - int32_t size = 0; - if ((_ptrData[i + 1] == 1 && _ptrData[i - 1] == 0) || - (_ptrData[i + 2] == 1 && _ptrData[i + 1] == 0)) - { - // Found a header - // Reduce size by preceding zeroes - while (_ptrData[i - 1] == 0) - { - i--; - } - size = i; - } - if (size > 0) - { - _info.payloadSize[_info.numNALUs] = size - _info.startCodeSize[_info.numNALUs]; - _parsedLength += _info.startCodeSize[_info.numNALUs] + _info.payloadSize[_info.numNALUs]; - return 0; - } - } - } - // Last NAL unit - _info.payloadSize[_info.numNALUs] = _remLength - _info.startCodeSize[_info.numNALUs]; - if (_info.payloadSize[_info.numNALUs] > 0) - { - _parsedLength += _info.startCodeSize[_info.numNALUs] + _info.payloadSize[_info.numNALUs]; - return 1; - } - return -1; -} - -/******************************************************************************* - * void GetNRI(); - * - * Finds the NRI of the current NAL unit. - * - * Output: - * - _info.NRI[currentNALU] : NRI of NAL unit. - * - * Return value: - * - 0 : ok - * - (-1) : Error - */ -void -H264Information::GetNRI() -{ - // NAL unit header (1 byte) - // --------------------------------- - // | start code |F|NRI| Type | - // --------------------------------- - - // NRI (2 bits) - nal_ref_idc. '00' - the NAL unit is not used to reconstruct reference pictures. - // >00 - the NAL unit is required to reconstruct reference pictures - // in the same layer, or contains a parameter set. - - - const uint8_t type = _ptrData[_info.startCodeSize[_info.numNALUs]] & 0x1f; - - // NALU type of 5, 7 and 8 shoud have NRI to b011 - if( type == 5 || - type == 7 || - type == 8) - { - _info.NRI[_info.numNALUs] = 0x60; - }else - { - _info.NRI[_info.numNALUs] = _ptrData[_info.startCodeSize[_info.numNALUs]] & 0x60; - } -} - - -/******************************************************************************* - * int32_t FindNALUType(); - * - * Finds the type of the current NAL unit. - * - * Output: - * - _info.type[currentNALU] : Type of NAL unit - * - * Return value: - * - 0 : ok - * - (-1) : Error - */ -int32_t -H264Information::FindNALUType() -{ - // NAL unit header (1 byte) - // --------------------------------- - // | start code |F|NRI| Type | - // --------------------------------- - - _info.type[_info.numNALUs] = _ptrData[_info.startCodeSize[_info.numNALUs]] & 0x1f; - - if (_info.type[_info.numNALUs] == 0) - { - return -1; - } - - // SVC NAL units, extended header - if (ParseSVCNALUHeader() == -1) - { - return -1; - } - - return 0; -} - -/******************************************************************************* - * int32_t ParseSVCNALUHeader(); - * - * Finds the extended header of the current NAL unit. Included for NAL unit types 14 and 20. - * - * Output: - * - _info.SVCheader[currentNALU] : SVC header of NAL unit. - * - * Return value: - * - 0 : ok - * - (-1) : Error - */ -int32_t -H264Information::ParseSVCNALUHeader() -{ - if (_info.type[_info.numNALUs] == 5) - { - _info.SVCheader[_info.numNALUs].idr = 1; - } - if (_info.type[_info.numNALUs] == 6) - { - uint32_t seiPayloadSize; - do - { - // SEI message - seiPayloadSize = 0; - - uint32_t curByte = _info.startCodeSize[_info.numNALUs] + 1; - const uint32_t seiStartOffset = curByte; - - uint32_t seiPayloadType = 0; - while(_ptrData[curByte] == 0xff) - { - seiPayloadType += 255; - curByte++; - } - seiPayloadType += _ptrData[curByte++]; - - while(_ptrData[curByte] == 0xff) - { - seiPayloadSize += 255; - curByte++; - } - seiPayloadSize += _ptrData[curByte++]; - - if(_info.payloadSize[_info.numNALUs] < _info.startCodeSize[_info.numNALUs] + seiPayloadSize) - { - // sanity of remaining buffer - // return 0 since no one "need" SEI messages - assert(false); - return 0; - } - - if(seiPayloadType == 24) - { - // we add this to NALU 0 to be signaled in the first PACSI packet - _info.PACSI[0].numSEINALUs = 1; // we allways add this to NALU 0 to send it in the first packet - if(_info.PACSI[0].seiMessageLength[0] != seiPayloadSize) - { - _info.PACSI[0].seiMessageLength[0] = seiPayloadSize; - delete [] _info.PACSI[0].seiMessageData[0]; - _info.PACSI[0].seiMessageData[0] = new uint8_t[seiPayloadSize]; - } - memcpy(_info.PACSI[0].seiMessageData[0], _ptrData+seiStartOffset, seiPayloadSize); - - _info.PACSI[0].NALlength += seiPayloadSize + 2; // additional 2 is the length - -#ifdef DEBUG_SEI_MESSAGE - const uint8_t numberOfLayers = 10; - uint16_t avgBitrate[numberOfLayers]= {0,0,0,0,0,0,0,0,0,0}; - uint16_t maxBitrateLayer[numberOfLayers]= {0,0,0,0,0,0,0,0,0,0}; - uint16_t maxBitrateLayerRepresentation[numberOfLayers] = {0,0,0,0,0,0,0,0,0,0}; - uint16_t maxBitrareCalcWindow[numberOfLayers] = {0,0,0,0,0,0,0,0,0,0}; - - BitstreamParser parserScalabilityInfo(_ptrData+curByte, seiPayloadSize); - - parserScalabilityInfo.Get1Bit(); // not used in futher parsing - const uint8_t priority_layer_info_present = parserScalabilityInfo.Get1Bit(); - const uint8_t priority_id_setting_flag = parserScalabilityInfo.Get1Bit(); - - uint32_t numberOfLayersMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t j = 0; j<= numberOfLayersMinusOne; j++) - { - printf("\nLayer ID:%d \n",parserScalabilityInfo.GetUE()); - printf("Priority ID:%d \n", parserScalabilityInfo.Get6Bits()); - printf("Discardable:%d \n", parserScalabilityInfo.Get1Bit()); - - printf("Dependency ID:%d \n", parserScalabilityInfo.Get3Bits()); - printf("Quality ID:%d \n", parserScalabilityInfo.Get4Bits()); - printf("Temporal ID:%d \n", parserScalabilityInfo.Get3Bits()); - - const uint8_t sub_pic_layer_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t sub_region_layer_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t iroi_division_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t profile_level_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t bitrate_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t frm_rate_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t frm_size_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t layer_dependency_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t parameter_sets_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t bitstream_restriction_info_present_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t exact_inter_layer_pred_flag = parserScalabilityInfo.Get1Bit(); // not used in futher parsing - - if(sub_pic_layer_flag || iroi_division_info_present_flag) - { - parserScalabilityInfo.Get1Bit(); - } - const uint8_t layer_conversion_flag = parserScalabilityInfo.Get1Bit(); - const uint8_t layer_output_flag = parserScalabilityInfo.Get1Bit(); // not used in futher parsing - - if(profile_level_info_present_flag) - { - parserScalabilityInfo.Get24Bits(); - } - if(bitrate_info_present_flag) - { - // this is what we want - avgBitrate[j] = parserScalabilityInfo.Get16Bits(); - maxBitrateLayer[j] = parserScalabilityInfo.Get16Bits(); - maxBitrateLayerRepresentation[j] = parserScalabilityInfo.Get16Bits(); - maxBitrareCalcWindow[j] = parserScalabilityInfo.Get16Bits(); - - printf("\tAvg:%d\n", BitRateBPS(avgBitrate[j])); - printf("\tmaxBitrate:%d\n", BitRateBPS(maxBitrateLayer[j])); - printf("\tmaxBitrate rep:%d\n", BitRateBPS(maxBitrateLayerRepresentation[j])); - printf("\tCalcWindow:%d\n", maxBitrareCalcWindow[j]); - } - if(frm_rate_info_present_flag) - { - printf("\tFrame rate constant:%d\n", parserScalabilityInfo.Get2Bits()); // 0 = not constant, 1 = constant, 2 = maybe... - printf("\tFrame rate avg:%d\n", parserScalabilityInfo.Get16Bits()/256); - } - if(frm_size_info_present_flag || iroi_division_info_present_flag) - { - printf("\tFrame Width:%d\n",(parserScalabilityInfo.GetUE()+1)*16); - printf("\tFrame Height:%d\n",(parserScalabilityInfo.GetUE()+1)*16); - } - if(sub_region_layer_flag) - { - parserScalabilityInfo.GetUE(); - if(parserScalabilityInfo.Get1Bit()) - { - parserScalabilityInfo.Get16Bits(); - parserScalabilityInfo.Get16Bits(); - parserScalabilityInfo.Get16Bits(); - parserScalabilityInfo.Get16Bits(); - } - } - if(sub_pic_layer_flag) - { - parserScalabilityInfo.GetUE(); - } - if(iroi_division_info_present_flag) - { - if(parserScalabilityInfo.Get1Bit()) - { - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - }else - { - const uint32_t numRoisMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t k = 0; k <= numRoisMinusOne; k++) - { - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - } - } - } - if(layer_dependency_info_present_flag) - { - const uint32_t numDirectlyDependentLayers = parserScalabilityInfo.GetUE(); - for(uint32_t k = 0; k < numDirectlyDependentLayers; k++) - { - parserScalabilityInfo.GetUE(); - } - } else - { - parserScalabilityInfo.GetUE(); - } - if(parameter_sets_info_present_flag) - { - const uint32_t numSeqParameterSetMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t k = 0; k <= numSeqParameterSetMinusOne; k++) - { - parserScalabilityInfo.GetUE(); - } - const uint32_t numSubsetSeqParameterSetMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t l = 0; l <= numSubsetSeqParameterSetMinusOne; l++) - { - parserScalabilityInfo.GetUE(); - } - const uint32_t numPicParameterSetMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t m = 0; m <= numPicParameterSetMinusOne; m++) - { - parserScalabilityInfo.GetUE(); - } - }else - { - parserScalabilityInfo.GetUE(); - } - if(bitstream_restriction_info_present_flag) - { - parserScalabilityInfo.Get1Bit(); - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.GetUE(); - } - if(layer_conversion_flag) - { - parserScalabilityInfo.GetUE(); - for(uint32_t k = 0; k <2;k++) - { - if(parserScalabilityInfo.Get1Bit()) - { - parserScalabilityInfo.Get24Bits(); - parserScalabilityInfo.Get16Bits(); - parserScalabilityInfo.Get16Bits(); - } - } - } - } - if(priority_layer_info_present) - { - const uint32_t prNumDidMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t k = 0; k <= prNumDidMinusOne;k++) - { - parserScalabilityInfo.Get3Bits(); - const uint32_t prNumMinusOne = parserScalabilityInfo.GetUE(); - for(uint32_t l = 0; l <= prNumMinusOne; l++) - { - parserScalabilityInfo.GetUE(); - parserScalabilityInfo.Get24Bits(); - parserScalabilityInfo.Get16Bits(); - parserScalabilityInfo.Get16Bits(); - } - } - } - if(priority_id_setting_flag) - { - uint8_t priorityIdSettingUri; - uint32_t priorityIdSettingUriIdx = 0; - do - { - priorityIdSettingUri = parserScalabilityInfo.Get8Bits(); - } while (priorityIdSettingUri != 0); - } -#endif - } else - { - // not seiPayloadType 24 ignore - } - //check if we have more SEI in NALU - } while (_info.payloadSize[_info.numNALUs] > _info.startCodeSize[_info.numNALUs] + seiPayloadSize); - } - - // Extended NAL unit header (3 bytes). - // +---------------+---------------+---------------+ - // |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // |R|I| PRID |N| DID | QID | TID |U|D|O| RR| - // +---------------+---------------+---------------+ - - // R - Reserved for future extensions (MUST be 1). Receivers SHOULD ignore the value of R. - // I - Is layer representation an IDR layer (1) or not (0). - // PRID - Priority identifier for the NAL unit. - // N - Specifies whether inter-layer prediction may be used for decoding the coded slice (1) or not (0). - // DID - Indicates the inter-layer coding dependency level of a layer representation. - // QID - Indicates the quality level of an MGS layer representation. - // TID - Indicates the temporal level of a layer representation. - // U - Use only reference base pictures during the inter prediction process (1) or not (0). - // D - Discardable flag. - // O - Output_flag. Affects the decoded picture output process as defined in Annex C of [H.264]. - // RR - Reserved_three_2bits (MUST be '11'). Receivers SHOULD ignore the value of RR. - - if (_info.type[_info.numNALUs] == 14 || - _info.type[_info.numNALUs] == 20) - { - uint32_t curByte = _info.startCodeSize[_info.numNALUs] + 1; - - if (_remLength < curByte + 3) - { - return -1; - } - - _info.SVCheader[_info.numNALUs].idr = (_ptrData[curByte] >> 6) & 0x01; - _info.SVCheader[_info.numNALUs].priorityID = (_ptrData[curByte++] & 0x3F); - - _info.SVCheader[_info.numNALUs].interLayerPred = (_ptrData[curByte] >> 7) & 0x01; - _info.SVCheader[_info.numNALUs].dependencyID = (_ptrData[curByte] >> 4) & 0x07; - _info.SVCheader[_info.numNALUs].qualityID = (_ptrData[curByte++] & 0x0F); - - _info.SVCheader[_info.numNALUs].temporalID = (_ptrData[curByte] >> 5) & 0x07; - _info.SVCheader[_info.numNALUs].useRefBasePic = (_ptrData[curByte] >> 4) & 0x01; - _info.SVCheader[_info.numNALUs].discardable = (_ptrData[curByte] >> 3) & 0x01; - _info.SVCheader[_info.numNALUs].output = (_ptrData[curByte] >> 2) & 0x01; - - if (_info.type[_info.numNALUs] == 14) - { - // inform the next NALU - memcpy(&(_info.SVCheader[_info.numNALUs+1]), &(_info.SVCheader[_info.numNALUs]), sizeof(_H264_SVC_NALUHeader)); - } - } - return 0; -} - - -/******************************************************************************* - * void SetLayerSEBit(); - * - * Sets start and end bits for the current NAL unit. - * - * Output: - * - _info.PACSI[currentNALU].S : First NAL unit in a layer (S = 1). - * - _info.PACSI[currentNALU].E : Last NAL unit in a layer (E = 1). - * - */ -void -H264Information::SetLayerSEBit(int32_t foundLast) -{ - if (_info.numNALUs == 0) - { - // First NAL unit - _info.PACSI[_info.numNALUs].S = 1; - } - - if (_info.numNALUs > 0) - { - if (_info.type[_info.numNALUs] != _info.type[_info.numNALUs-1] && - (_info.type[_info.numNALUs] == 20)) - { - // First layer in scalable extension - _info.PACSI[_info.numNALUs].S = 1; - _info.PACSI[_info.numNALUs-1].E = 1; - } - - if (_info.type[_info.numNALUs] == 20 && _info.type[_info.numNALUs-1] == 20) - { - if (_info.SVCheader[_info.numNALUs].temporalID != _info.SVCheader[_info.numNALUs-1].temporalID || - _info.SVCheader[_info.numNALUs].dependencyID != _info.SVCheader[_info.numNALUs-1].dependencyID || - _info.SVCheader[_info.numNALUs].qualityID != _info.SVCheader[_info.numNALUs-1].qualityID) - { - // New layer in scalable extension - _info.PACSI[_info.numNALUs].S = 1; - _info.PACSI[_info.numNALUs-1].E = 1; - } - } - } - - if (foundLast) - { - // Last NAL unit - _info.PACSI[_info.numNALUs].E = 1; - } - -} - -/******************************************************************************* - * int32_t SetLayerLengths(); - * - * Sets the accumulated layer length. - * - * Output: - * - _info.accLayerSize[currentLayer] : Size in bytes of layer: 0 - currentLayer. - * - * Return value: - * - 0 : ok - * - (-1) : Error - * - */ -int32_t -H264Information::SetLayerLengths() -{ - for (uint32_t curNALU = 0; curNALU < _info.numNALUs; curNALU++) - { - _info.accLayerSize[_info.numLayers] += _info.startCodeSize[curNALU] + _info.payloadSize[curNALU]; - - if (_info.PACSI[curNALU].E == 1) - { - _info.numLayers++; - if (curNALU == uint32_t(_info.numNALUs - 1)) - { - break; - } - if (_info.numLayers >= KMaxNumberOfLayers) - { - Reset(); - return -1; - } - _info.accLayerSize[_info.numLayers] += _info.accLayerSize[_info.numLayers - 1]; - } - } - - if (_info.numLayers < 1 && _info.numLayers > KMaxNumberOfLayers) - { - Reset(); - return -1; - } - - if (_info.accLayerSize[_info.numLayers - 1] != int32_t(_length)) - { - Reset(); - return -1; - } - - return 0; -} -} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/H264/h264_information.h b/webrtc/modules/rtp_rtcp/source/H264/h264_information.h deleted file mode 100644 index 356a026ec6..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/h264_information.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_H264_INFORMATION_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_H264_INFORMATION_H_ - -#include "VideoCodecInformation.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -enum -{ - KMaxNumberOfNALUs = 128, - KMaxNumberOfSEINALUs = 2, - KMaxNumberOfLayers = 16 -}; - -struct H264_SVC_NALUHeader -{ - H264_SVC_NALUHeader() - : - r(1), - idr(0), - priorityID(0), - interLayerPred(0), - dependencyID(0), - qualityID(0), - temporalID(0), - useRefBasePic(0), - discardable(0), - output(0), - rr(3), - length(3) - { - } - const uint8_t r; - uint8_t idr; - uint8_t priorityID; - uint8_t interLayerPred; - uint8_t dependencyID; - uint8_t qualityID; - uint8_t temporalID; - uint8_t useRefBasePic; - uint8_t discardable; - uint8_t output; - const uint8_t rr; - const uint8_t length; -}; - -class H264_PACSI_NALU -{ -public: - H264_PACSI_NALU() : - NALlength(5), - type(30), - X(0), - Y(0), -// T(0), - A(0), - P(0), - C(0), - S(0), - E(0), - TL0picIDx(0), - IDRpicID(0), - DONC(0), - numSEINALUs(0) - { - memset(seiMessageLength, 0, sizeof(seiMessageLength)); - memset(seiMessageData, 0, sizeof(seiMessageData)); - } - ~H264_PACSI_NALU() - { - for(int i = 0; i> 8); - databuffer[curByte++] = (uint8_t)(pacsi.IDRpicID); - } - // Decoding order number - if (addDONC) // pacsi.T - { - databuffer[curByte++] = (uint8_t)(DONC >> 8); - databuffer[curByte++] = (uint8_t)(DONC); - } - - // SEI NALU - if(firstPacketInNALU) // IMPROVEMENT duplicate it to make sure it arrives... - { - // we only set this for NALU 0 to make sure we send it only once per frame - for (uint32_t i = 0; i < pacsi.numSEINALUs; i++) - { - // NALU size - databuffer[curByte++] = (uint8_t)(pacsi.seiMessageLength[i] >> 8); - databuffer[curByte++] = (uint8_t)(pacsi.seiMessageLength[i]); - - // NALU data - memcpy(databuffer + curByte, pacsi.seiMessageData[i], pacsi.seiMessageLength[i]); - curByte += pacsi.seiMessageLength[i]; - } - } - return curByte - startByte; -} - -int32_t -RTPSenderH264::SetH264RelaySequenceNumber(const uint16_t seqNum) -{ - _h264SVCRelaySequenceNumber = seqNum; - return 0; -} - -int32_t -RTPSenderH264::SetH264RelayCompleteLayer(const bool complete) -{ - _h264SVCRelayLayerComplete = complete; - return 0; -} - -/* - 12 Filler data - - The only restriction of filler data NAL units within an - access unit is that they shall not precede the first VCL - NAL unit with the same access unit. -*/ -int32_t -RTPSenderH264::SendH264FillerData(const WebRtcRTPHeader* rtpHeader, - const uint16_t bytesToSend, - const uint32_t ssrc) -{ - uint16_t fillerLength = bytesToSend - 12 - 1; - - if (fillerLength > WEBRTC_IP_PACKET_SIZE - 12 - 1) - { - return 0; - } - - if (fillerLength == 0) - { - // do not send an empty packet, will not reach JB - fillerLength = 1; - } - - // send codec valid data, H.264 has defined data which is binary 1111111 - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - - dataBuffer[0] = static_cast(0x80); // version 2 - dataBuffer[1] = rtpHeader->header.payloadType; - RtpUtility::AssignUWord16ToBuffer( - dataBuffer + 2, - _rtpSender.IncrementSequenceNumber()); // get the current - // SequenceNumber and add by 1 - // after returning - RtpUtility::AssignUWord32ToBuffer(dataBuffer + 4, - rtpHeader->header.timestamp); - RtpUtility::AssignUWord32ToBuffer(dataBuffer + 8, rtpHeader->header.ssrc); - - // set filler NALU type - dataBuffer[12] = 12; // NRI field = 0, type 12 - - // fill with 0xff - memset(dataBuffer + 12 + 1, 0xff, fillerLength); - - return _rtpSender.SendToNetwork(dataBuffer, - fillerLength, - 12 + 1); -} - -int32_t -RTPSenderH264::SendH264FillerData(const uint32_t captureTimestamp, - const uint8_t payloadType, - const uint32_t bytes - ) -{ - - const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength(); - uint16_t maxLength = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - _rtpSender.RTPHeaderLength(); - - int32_t bytesToSend=bytes; - uint16_t fillerLength=0; - - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - - while(bytesToSend>0) - { - fillerLength=maxLength; - if(fillerLength WEBRTC_IP_PACKET_SIZE - 12 - 1) - { - return 0; - } - - if (fillerLength == 0) - { - // do not send an empty packet, will not reach JB - fillerLength = 1; - } - - // send paded data - // correct seq num, time stamp and payloadtype - _rtpSender.BuildRTPheader(dataBuffer, payloadType, false,captureTimestamp, true, true); - - // set filler NALU type - dataBuffer[12] = 12; // NRI field = 0, type 12 - - // send codec valid data, H.264 has defined data which is binary 1111111 - // fill with 0xff - memset(dataBuffer + 12 + 1, 0xff, fillerLength-1); - - if( _rtpSender.SendToNetwork(dataBuffer, - fillerLength, - 12)<0) - { - - return -1;; - } - } - return 0; -} - -int32_t -RTPSenderH264::SendH264SVCRelayPacket(const WebRtcRTPHeader* rtpHeader, - const uint8_t* incomingRTPPacket, - const uint16_t incomingRTPPacketSize, - const uint32_t ssrc, - const bool higestLayer) -{ - if (rtpHeader->header.sequenceNumber != (uint16_t)(_h264SVCRelaySequenceNumber + 1)) - { - // not continous, signal loss - _rtpSender.IncrementSequenceNumber(); - } - _h264SVCRelaySequenceNumber = rtpHeader->header.sequenceNumber; - - - if (rtpHeader->header.timestamp != _h264SVCRelayTimeStamp) - { - // new frame - _h264SVCRelayLayerComplete = false; - } - - if (rtpHeader->header.timestamp == _h264SVCRelayTimeStamp && - _h264SVCRelayLayerComplete) - { - // sanity, end of layer already sent - // Could happened for fragmented packet with missing PACSI info (PACSI packet reorded and received after packet it belongs to) - // fragmented packet has no layer info set (default info 0) - return 0; - } - _h264SVCRelayTimeStamp = rtpHeader->header.timestamp; - - // re-packetize H.264-SVC packets - // we keep the timestap unchanged - // make a copy and only change the SSRC and seqNum - - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - memcpy(dataBuffer, incomingRTPPacket, incomingRTPPacketSize); - - // _sequenceNumber initiated in Init() - // _ssrc initiated in constructor - - // re-write payload type - if(_h264SVCPayloadType != -1) - { - dataBuffer[1] &= kRtpMarkerBitMask; - dataBuffer[1] += _h264SVCPayloadType; - } - - // _sequenceNumber will not work for re-ordering by NACK from original sender - // engine responsible for this - RtpUtility::AssignUWord16ToBuffer( - dataBuffer + 2, - _rtpSender.IncrementSequenceNumber()); // get the current - // SequenceNumber and add by 1 - // after returning - // RtpUtility::AssignUWord32ToBuffer(dataBuffer+8, ssrc); - - // how do we know it's the last relayed packet in a frame? - // 1) packets arrive in order, the engine manages that - // 2) highest layer that we relay - // 3) the end bit is set for the highest layer - - if(higestLayer && rtpHeader->type.Video.codecHeader.H264.relayE) - { - // set marker bit - dataBuffer[1] |= kRtpMarkerBitMask; - - // set relayed layer as complete - _h264SVCRelayLayerComplete = true; - } - return _rtpSender.SendToNetwork(dataBuffer, - incomingRTPPacketSize - rtpHeader->header.headerLength, - rtpHeader->header.headerLength); -} - -int32_t -RTPSenderH264::SendH264_STAP_A(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - bool& switchToFUA, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength) -{ - const int32_t H264_NALU_LENGTH = 2; - - uint16_t h264HeaderLength = 1; // normal header length - uint16_t maxPayloadLengthSTAP_A = _rtpSender.MaxPayloadLength() - - FECPacketOverhead() - rtpHeaderLength - - h264HeaderLength - H264_NALU_LENGTH; - - int32_t dataOffset = rtpHeaderLength + h264HeaderLength; - uint8_t NRI = 0; - uint16_t payloadBytesInPacket = 0; - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - - if (ptrH264Info->payloadSize[idxNALU] > maxPayloadLengthSTAP_A) - { - // we need to fragment NAL switch to mode FU-A - switchToFUA = true; - } else - { - // combine as many NAL units in every IP packet - do - { - if(!_h264SendPPS_SPS) - { - // don't send NALU of type 7 and 8 SPS and PPS - if(ptrH264Info->type[idxNALU] == 7 || ptrH264Info->type[idxNALU] == 8) - { - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - idxNALU++; - continue; - } - } - if(ptrH264Info->payloadSize[idxNALU] + payloadBytesInPacket <= maxPayloadLengthSTAP_A) - { - if(ptrH264Info->NRI[idxNALU] > NRI) - { - NRI = ptrH264Info->NRI[idxNALU]; - } - // put NAL size into packet - dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] >> 8); - dataOffset++; - dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] & 0xff); - dataOffset++; - // Put payload in packet - memcpy(&dataBuffer[dataOffset], &data[ptrH264Info->startCodeSize[idxNALU]], ptrH264Info->payloadSize[idxNALU]); - dataOffset += ptrH264Info->payloadSize[idxNALU]; - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - payloadBytesInPacket += (uint16_t)(ptrH264Info->payloadSize[idxNALU] + H264_NALU_LENGTH); - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - } else - { - // we don't fitt the next NALU in this packet - break; - } - idxNALU++; - }while(payloadBytesToSend); - } - - // sanity - // don't send empty packets - if (payloadBytesInPacket) - { - // add RTP header - _rtpSender.BuildRTPheader(dataBuffer, payloadType, (payloadBytesToSend==0)?true:false, captureTimeStamp); - dataBuffer[rtpHeaderLength] = 24 + NRI; // STAP-A == 24 - uint16_t payloadLength = payloadBytesInPacket + h264HeaderLength; - - if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength)) - { - return -1; - } - } - return 0; -} // end STAP-A - -// STAP-A for H.264 SVC -int32_t -RTPSenderH264::SendH264_STAP_A_PACSI(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - bool& switchToFUA, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength, - uint16_t& decodingOrderNumber) -{ - const int32_t H264_NALU_LENGTH = 2; - - uint16_t h264HeaderLength = 1; // normal header length - uint16_t maxPayloadLengthSTAP_A = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - rtpHeaderLength - h264HeaderLength - H264_NALU_LENGTH; - int32_t dataOffset = rtpHeaderLength + h264HeaderLength; - uint8_t NRI = 0; - uint16_t payloadBytesInPacket = 0; - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - bool firstNALUNotIDR = true; //delta - - // Put PACSI NAL unit into packet - int32_t lengthPACSI = 0; - uint32_t PACSI_NALlength = ptrH264Info->PACSI[idxNALU].NALlength; - if (PACSI_NALlength > maxPayloadLengthSTAP_A) - { - return -1; - } - dataBuffer[dataOffset++] = (uint8_t)(PACSI_NALlength >> 8); - dataBuffer[dataOffset++] = (uint8_t)(PACSI_NALlength & 0xff); - - // end bit will be updated later, since another NALU in this packet might be the last - int32_t lengthPASCINALU = AddH264PACSINALU(true, - false, - ptrH264Info->PACSI[idxNALU], - ptrH264Info->SVCheader[idxNALU], - decodingOrderNumber, - dataBuffer, - dataOffset); - if (lengthPASCINALU <= 0) - { - return -1; - } - decodingOrderNumber++; - - lengthPACSI = H264_NALU_LENGTH + lengthPASCINALU; - maxPayloadLengthSTAP_A -= (uint16_t)lengthPACSI; - if (ptrH264Info->payloadSize[idxNALU] > maxPayloadLengthSTAP_A) - { - // we need to fragment NAL switch to mode FU-A - switchToFUA = true; - return 0; - } - if(!ptrH264Info->SVCheader[idxNALU].idr) - { - firstNALUNotIDR = true; - } - - uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+ - (ptrH264Info->SVCheader[idxNALU].qualityID << 8) + - ptrH264Info->SVCheader[idxNALU].temporalID; - - { - // combine as many NAL units in every IP packet, with the same priorityID - // Improvement we could allow several very small MGS NALU from different layers to be sent in one packet - - do - { - if(!_h264SendPPS_SPS) - { - // Don't send NALU of type 7 and 8 SPS and PPS, - // they could be signaled outofband - if(ptrH264Info->type[idxNALU] == 7 || ptrH264Info->type[idxNALU] == 8) - { - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - idxNALU++; - continue; - } - } - // don't send NALU type 6 (SEI message) not allowed when we send it in PACSI - if(ptrH264Info->type[idxNALU] == 6) - { - // SEI NALU Don't send, not allowed when we send it in PACSI - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - idxNALU++; - continue; - } - - const uint32_t layerNALU = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+ - (ptrH264Info->SVCheader[idxNALU].qualityID << 8) + - ptrH264Info->SVCheader[idxNALU].temporalID; - - // we need to break on a new layer - if( ptrH264Info->payloadSize[idxNALU] + payloadBytesInPacket <= maxPayloadLengthSTAP_A && - layerNALU == layer) - { - if(ptrH264Info->NRI[idxNALU] > NRI) - { - NRI = ptrH264Info->NRI[idxNALU]; - } - // put NAL size into packet - dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] >> 8); - dataOffset++; - dataBuffer[dataOffset] = (uint8_t)(ptrH264Info->payloadSize[idxNALU] & 0xff); - dataOffset++; - // Put payload in packet - memcpy(&dataBuffer[dataOffset], &data[ptrH264Info->startCodeSize[idxNALU]], ptrH264Info->payloadSize[idxNALU]); - dataOffset += ptrH264Info->payloadSize[idxNALU]; - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - payloadBytesInPacket += (uint16_t)(ptrH264Info->payloadSize[idxNALU] + H264_NALU_LENGTH); - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - } else - { - // we don't fitt the next NALU in this packet or, - // it's the next layer - - // check if we should send this NALU - // based on the layer - - if(_useHighestSendLayer && layerNALU != layer) - { - // we don't send this NALU due to it's a new layer - // check if we should send the next or if this is the last - const uint8_t dependencyQualityID = (ptrH264Info->SVCheader[idxNALU].dependencyID << 4) + ptrH264Info->SVCheader[idxNALU].qualityID; - - bool highestLayer; - if(SendH264SVCLayer(frameType, - ptrH264Info->SVCheader[idxNALU].temporalID, - dependencyQualityID, - highestLayer) == false) - { - // will trigger markerbit and stop sending this frame - payloadBytesToSend = 0; - } - } - break; - } - idxNALU++; - - }while(payloadBytesToSend); - } - - // sanity, don't send empty packets - if (payloadBytesInPacket) - { - // add RTP header - _rtpSender.BuildRTPheader(dataBuffer, payloadType, (payloadBytesToSend==0)?true:false, captureTimeStamp); - - dataBuffer[rtpHeaderLength] = 24 + NRI; // STAP-A == 24 - - // NRI for PACSI - dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 1] &= 0x1f; // zero out NRI field - dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 1] |= NRI; - - if(ptrH264Info->PACSI[idxNALU-1].E) - { - // update end bit - dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 5] |= 0x01; - } - if(firstNALUNotIDR) - { - // we have to check if any of the NALU in this packet is an IDR NALU - bool setIBit = false; - for(int i = 0; i < idxNALU; i++) - { - if(ptrH264Info->SVCheader[i].idr) - { - setIBit = true; - break; - } - } - if(setIBit) - { - // update I bit - dataBuffer[rtpHeaderLength + H264_NALU_LENGTH + 2] |= 0x40; - } - } - const uint16_t payloadLength = payloadBytesInPacket + h264HeaderLength + (uint16_t)lengthPACSI; - if(-1 == SendVideoPacket(frameType, - dataBuffer, - payloadLength, - rtpHeaderLength, - layer==0)) - { - return -1; - } - } - return 0; -} // end STAP-A - -int32_t -RTPSenderH264::SendH264_FU_A(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength, - uint16_t& decodingOrderNumber, - const bool sendSVCPACSI) -{ - - // FUA for the rest of the frame - uint16_t maxPayloadLength = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - rtpHeaderLength; - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - uint32_t payloadBytesRemainingInNALU = ptrH264Info->payloadSize[idxNALU]; - - bool isBaseLayer=false; - - if(payloadBytesRemainingInNALU > maxPayloadLength) - { - // we need to fragment NALU - const uint16_t H264_FUA_LENGTH = 2; // FU-a H.264 header is 2 bytes - - if(sendSVCPACSI) - { - SendH264_SinglePACSI(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - true, - false); - - uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+ - (ptrH264Info->SVCheader[idxNALU].qualityID << 8) + - ptrH264Info->SVCheader[idxNALU].temporalID; - isBaseLayer=(layer==0); - } - - // First packet - _rtpSender.BuildRTPheader(dataBuffer,payloadType, false, captureTimeStamp); - - uint16_t maxPayloadLengthFU_A = maxPayloadLength - H264_FUA_LENGTH ; - uint8_t fuaIndc = 28 + ptrH264Info->NRI[idxNALU]; - dataBuffer[rtpHeaderLength] = fuaIndc; // FU-A indicator - dataBuffer[rtpHeaderLength+1] = (uint8_t)(ptrH264Info->type[idxNALU] + 0x80)/*start*/; // FU-A header - - memcpy(&dataBuffer[rtpHeaderLength + H264_FUA_LENGTH], &data[ptrH264Info->startCodeSize[idxNALU]+1], maxPayloadLengthFU_A); - uint16_t payloadLength = maxPayloadLengthFU_A + H264_FUA_LENGTH; - if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength, isBaseLayer)) - { - return -1; - } - - //+1 is from the type that is coded into the FU-a header - data += maxPayloadLengthFU_A + 1 + ptrH264Info->startCodeSize[idxNALU]; // inc data ptr - payloadBytesToSend -= maxPayloadLengthFU_A+1+ptrH264Info->startCodeSize[idxNALU]; - payloadBytesRemainingInNALU -= maxPayloadLengthFU_A+1; - - // all non first/last packets - while(payloadBytesRemainingInNALU > maxPayloadLengthFU_A) - { - if(sendSVCPACSI) - { - SendH264_SinglePACSI(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - false, - false); - } - - // prepare next header - _rtpSender.BuildRTPheader(dataBuffer, payloadType, false, captureTimeStamp); - - dataBuffer[rtpHeaderLength] = (uint8_t)fuaIndc; // FU-A indicator - dataBuffer[rtpHeaderLength+1] = ptrH264Info->type[idxNALU]; // FU-A header - - memcpy(&dataBuffer[rtpHeaderLength+H264_FUA_LENGTH], data, maxPayloadLengthFU_A); - payloadLength = maxPayloadLengthFU_A + H264_FUA_LENGTH; - - if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength,isBaseLayer)) - { - return -1; - } - data += maxPayloadLengthFU_A; // inc data ptr - payloadBytesToSend -= maxPayloadLengthFU_A; - payloadBytesRemainingInNALU -= maxPayloadLengthFU_A; - dataBuffer[rtpHeaderLength] = fuaIndc; // FU-A indicator - dataBuffer[rtpHeaderLength+1] = ptrH264Info->type[idxNALU]; // FU-A header - } - if(sendSVCPACSI) - { - SendH264_SinglePACSI(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - false, - true); // last packet in NALU - - if(_useHighestSendLayer && idxNALU+1 < ptrH264Info->numNALUs) - { - // not last NALU in frame - // check if it's the the next layer should not be sent - - // check if we should send the next or if this is the last - const uint8_t dependencyQualityID = (ptrH264Info->SVCheader[idxNALU+1].dependencyID << 4) + - ptrH264Info->SVCheader[idxNALU+1].qualityID; - - bool highestLayer; - if(SendH264SVCLayer(frameType, - ptrH264Info->SVCheader[idxNALU+1].temporalID, - dependencyQualityID, - highestLayer) == false) - { - // will trigger markerbit and stop sending this frame - payloadBytesToSend = payloadBytesRemainingInNALU; - } - } - } - // last packet in NALU - _rtpSender.BuildRTPheader(dataBuffer, payloadType,(payloadBytesToSend == (int32_t)payloadBytesRemainingInNALU)?true:false, captureTimeStamp); - dataBuffer[rtpHeaderLength+1] = ptrH264Info->type[idxNALU] + 0x40/*stop*/; // FU-A header - - memcpy(&dataBuffer[rtpHeaderLength+H264_FUA_LENGTH], data, payloadBytesRemainingInNALU); - payloadLength = (uint16_t)payloadBytesRemainingInNALU + H264_FUA_LENGTH; - payloadBytesToSend -= payloadBytesRemainingInNALU; - if(payloadBytesToSend != 0) - { - data += payloadBytesRemainingInNALU; // inc data ptr - } - idxNALU++; - if(-1 == SendVideoPacket(frameType, dataBuffer, payloadLength, rtpHeaderLength,isBaseLayer)) - { - return -1; - } - } else - { - // send NAL unit in singel mode - return SendH264_SingleMode(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - payloadBytesToSend, - data, - rtpHeaderLength, - sendSVCPACSI); - } - // end FU-a - return 0; -} - -int32_t -RTPSenderH264::SendH264_SingleMode(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength, - uint16_t& decodingOrderNumber, - const bool sendSVCPACSI) -{ - // no H.264 header lenght in single mode - // we use WEBRTC_IP_PACKET_SIZE instead of the configured MTU since it's better to send fragmented UDP than not to send - const uint16_t maxPayloadLength = WEBRTC_IP_PACKET_SIZE - _rtpSender.PacketOverHead() - FECPacketOverhead() - rtpHeaderLength; - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - bool isBaseLayer=false; - - if(ptrH264Info->payloadSize[idxNALU] > maxPayloadLength) - { - return -3; - } - if(!_h264SendPPS_SPS) - { - // don't send NALU of type 7 and 8 SPS and PPS - if(ptrH264Info->type[idxNALU] == 7 || ptrH264Info->type[idxNALU] == 8) - { - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - idxNALU++; - return 0; - } - } - if(sendSVCPACSI) - { - SendH264_SinglePACSI(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - true, - true); - - uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+ - (ptrH264Info->SVCheader[idxNALU].qualityID << 8) + - ptrH264Info->SVCheader[idxNALU].temporalID; - isBaseLayer=(layer==0); - } - - // Put payload in packet - memcpy(&dataBuffer[rtpHeaderLength], &data[ptrH264Info->startCodeSize[idxNALU]], ptrH264Info->payloadSize[idxNALU]); - - uint16_t payloadBytesInPacket = (uint16_t)ptrH264Info->payloadSize[idxNALU]; - payloadBytesToSend -= ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; // left to send - - // - _rtpSender.BuildRTPheader(dataBuffer,payloadType,(payloadBytesToSend ==0)?true:false, captureTimeStamp); - - dataBuffer[rtpHeaderLength] &= 0x1f; // zero out NRI field - dataBuffer[rtpHeaderLength] |= ptrH264Info->NRI[idxNALU]; // nri - if(payloadBytesToSend > 0) - { - data += ptrH264Info->payloadSize[idxNALU] + ptrH264Info->startCodeSize[idxNALU]; - } - idxNALU++; - if(-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket, rtpHeaderLength,isBaseLayer)) - { - return -1; - } - return 0; -} - -int32_t -RTPSenderH264::SendH264_SinglePACSI(const FrameType frameType, - const H264Info* ptrH264Info, - const uint16_t idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const bool firstPacketInNALU, - const bool lastPacketInNALU); -{ - // Send PACSI in single mode - uint8_t dataBuffer[WEBRTC_IP_PACKET_SIZE]; - uint16_t rtpHeaderLength = (uint16_t)_rtpSender.BuildRTPheader(dataBuffer, payloadType,false, captureTimeStamp); - int32_t dataOffset = rtpHeaderLength; - - int32_t lengthPASCINALU = AddH264PACSINALU(firstPacketInNALU, - lastPacketInNALU, - ptrH264Info->PACSI[idxNALU], - ptrH264Info->SVCheader[idxNALU], - decodingOrderNumber, - dataBuffer, - dataOffset); - - if (lengthPASCINALU <= 0) - { - return -1; - } - decodingOrderNumber++; - - uint16_t payloadBytesInPacket = (uint16_t)lengthPASCINALU; - - // Set payload header (first payload byte co-serves as the payload header) - dataBuffer[rtpHeaderLength] &= 0x1f; // zero out NRI field - dataBuffer[rtpHeaderLength] |= ptrH264Info->NRI[idxNALU]; // nri - - const uint32_t layer = (ptrH264Info->SVCheader[idxNALU].dependencyID << 16)+ - (ptrH264Info->SVCheader[idxNALU].qualityID << 8) + - ptrH264Info->SVCheader[idxNALU].temporalID; - - if (-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket, rtpHeaderLength,layer==0)) - { - return -1; - } - return 0; -} - - - - -int32_t -RTPSenderH264::SendH264SVC(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const uint8_t* payloadData, - const uint32_t payloadSize, - H264Information& h264Information, - uint16_t& decodingOrderNumber) -{ - int32_t payloadBytesToSend = payloadSize; - const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength(); - - const H264Info* ptrH264Info = NULL; - if (h264Information.GetInfo(payloadData,payloadSize, ptrH264Info) == -1) - { - return -1; - } - if(_useHighestSendLayer) - { - // we need to check if we should drop the frame - // it could be a temporal layer (aka a temporal frame) - const uint8_t dependencyQualityID = (ptrH264Info->SVCheader[0].dependencyID << 4) + ptrH264Info->SVCheader[0].qualityID; - - bool dummyHighestLayer; - if(SendH264SVCLayer(frameType, - ptrH264Info->SVCheader[0].temporalID, - dependencyQualityID, - dummyHighestLayer) == false) - { - // skip send this frame - return 0; - } - } - - uint16_t idxNALU = 0; - while (payloadBytesToSend > 0) - { - bool switchToFUA = false; - if (SendH264_STAP_A_PACSI(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - switchToFUA, - payloadBytesToSend, - payloadData, - rtpHeaderLength, - decodingOrderNumber) != 0) - { - return -1; - } - if(switchToFUA) - { - // FU_A for this NALU - if (SendH264_FU_A(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - payloadBytesToSend, - payloadData, - rtpHeaderLength, - true) != 0) - { - return -1; - } - } - } - return 0; -} - -int32_t -RTPSenderH264::SetH264PacketizationMode(const H264PacketizationMode mode) -{ - _h264Mode = mode; - return 0; -} - -int32_t -RTPSenderH264::SetH264SendModeNALU_PPS_SPS(const bool dontSend) -{ - _h264SendPPS_SPS = !dontSend; - return 0; -} - -bool -RTPSenderH264::SendH264SVCLayer(const FrameType frameType, - const uint8_t temporalID, - const uint8_t dependencyQualityID, - bool& higestLayer) -{ - uint8_t dependencyID = dependencyQualityID >> 4; - - // keyframe required to switch between dependency layers not quality and temporal - if( _highestDependencyLayer != _highestDependencyLayerOld) - { - // we want to switch dependency layer - if(frameType == kVideoFrameKey) - { - // key frame we can change layer if it's correct layer - if(_highestDependencyLayer > _highestDependencyLayerOld) - { - // we want to switch up - // does this packet belong to a new layer? - - if( dependencyID > _highestDependencyLayerOld && - dependencyID <= _highestDependencyLayer) - { - _highestDependencyLayerOld = dependencyID; - _highestDependencyQualityIDOld = _highestDependencyQualityID; - - if( dependencyID == _highestDependencyLayer && - dependencyQualityID == _highestDependencyQualityID) - { - higestLayer = true; - } - // relay - return true; - } - } - if(_highestDependencyLayer < _highestDependencyLayerOld) - { - // we want to switch down - // does this packet belong to a low layer? - if( dependencyID <= _highestDependencyLayer) - { - _highestDependencyLayerOld = dependencyID; - _highestDependencyQualityIDOld = _highestDependencyQualityID; - if( dependencyID == _highestDependencyLayer && - dependencyQualityID == _highestDependencyQualityID) - { - higestLayer = true; - } - // relay - return true; - } - } - } else - { - // Delta frame and we are waiting to switch dependency layer - if(_highestDependencyLayer > _highestDependencyLayerOld) - { - // we want to switch up to a higher dependency layer - // use old setting until we get a key-frame - - // filter based on old dependency - // we could have allowed to add a MGS layer lower than the dependency ID - // but then we can't know the highest layer relayed we assume that the user - // will add one layer at a time - if( _highestTemporalLayer < temporalID || - _highestDependencyLayerOld < dependencyID || - _highestDependencyQualityIDOld < dependencyQualityID) - { - // drop - return false; - } - // highest layer based on old - if( dependencyID == _highestDependencyLayerOld && - dependencyQualityID == _highestDependencyQualityIDOld) - { - higestLayer = true; - } - } else - { - // we want to switch down to a lower dependency layer, - // use old setting, done bellow - // drop all temporal layers while waiting for the key-frame - if(temporalID > 0) - { - // drop - return false; - } - // we can't drop a lower MGS layer since this might depend on it - // however we can drop MGS layers larger than dependecyQualityId - // with dependency from old and quality 0 - if( _highestDependencyLayerOld < dependencyID || - (_highestDependencyQualityIDOld & 0xf0) < dependencyQualityID) - { - // drop - return false; - } - if( dependencyID == _highestDependencyLayerOld && - dependencyQualityID == (_highestDependencyQualityIDOld & 0xf0)) - { - higestLayer = true; - } - } - } - } else - { - // filter based on current state - if( _highestTemporalLayer < temporalID || - _highestDependencyLayer < dependencyID || - _highestDependencyQualityID < dependencyQualityID) - { - // drop - return false; - } - if( dependencyID == _highestDependencyLayer && - dependencyQualityID == _highestDependencyQualityID) - { - higestLayer = true; - } - } - return true; -} - -int32_t -RTPSenderH264::SetHighestSendLayer(const uint8_t dependencyQualityLayer, - const uint8_t temporalLayer) -{ - const uint8_t dependencyLayer = (dependencyQualityLayer >> 4); - - if(_highestDependencyLayerOld != _highestDependencyLayer) - { - // we have not switched to the new dependency yet - } else - { - if(_highestDependencyLayer == dependencyLayer) - { - // no change of dependency - // switch now _highestDependencyQualityIDOld - _highestDependencyQualityIDOld = dependencyQualityLayer; - }else - { - // change of dependency, update _highestDependencyQualityIDOld store as old - _highestDependencyQualityIDOld = _highestDependencyQualityID; - } - } - _useHighestSendLayer = true; - _highestDependencyLayer = dependencyLayer; - _highestDependencyQualityID = dependencyQualityLayer; - _highestTemporalLayer = temporalLayer; - return 0; -} - -int32_t -RTPSenderH264::HighestSendLayer(uint8_t& dependencyQualityLayer, - uint8_t& temporalLayer) -{ - if (!_useHighestSendLayer) - { - // No information set - return -1; - } - dependencyQualityLayer = _highestDependencyQualityID; - temporalLayer = _highestTemporalLayer; - return 0; -} -/* -* H.264 -*/ -int32_t -RTPSenderH264::SendH264(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const uint8_t* payloadData, - const uint32_t payloadSize, - H264Information& h264Information) -{ - int32_t payloadBytesToSend = payloadSize; - const uint8_t* data = payloadData; - bool switchToFUA = false; - const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength(); - - const H264Info* ptrH264Info = NULL; - if (h264Information.GetInfo(payloadData,payloadSize, ptrH264Info) == -1) - { - return -1; - } - uint16_t idxNALU = 0; - uint16_t DONCdummy = 0; - - while (payloadBytesToSend > 0) - { - switch(_h264Mode) - { - case H264_NON_INTERLEAVED_MODE: - - if(!switchToFUA) - { - if(SendH264_STAP_A(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - switchToFUA, - payloadBytesToSend, - data, - rtpHeaderLength) != 0) - { - return -1; - } - } - else - { - // FUA for the rest of the frame - if(SendH264_FU_A(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - payloadBytesToSend, - data, - rtpHeaderLength, - DONCdummy) != 0) - { - return -1; - } - // try to go back to STAP_A - switchToFUA = false; - } - break; - case H264_SINGLE_NAL_MODE: - { - // modeSingleU - if(SendH264_SingleMode(frameType, - ptrH264Info, - idxNALU, - payloadType, - captureTimeStamp, - payloadBytesToSend, - data, - rtpHeaderLength, - DONCdummy) != 0) - { - return -1; - } - break; - } - case H264_INTERLEAVED_MODE: - // not supported - assert(false); - return -1; - } - } - return 0; -} -} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/H264/rtp_sender_h264.h b/webrtc/modules/rtp_rtcp/source/H264/rtp_sender_h264.h deleted file mode 100644 index ea385d4596..0000000000 --- a/webrtc/modules/rtp_rtcp/source/H264/rtp_sender_h264.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_RTP_SENDER_H264_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_RTP_SENDER_H264_H_ - -#include "webrtc/typedefs.h" -#include "ModuleRTPRTCPConfig.h" -#include "rtp_rtcp_defines.h" -#include "h264_information.h" - -#include "RTPSender.h" - -namespace webrtc { -class RTPSenderH264 -{ -public: - int32_t SendH264(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const uint8_t* payloadData, - const uint32_t payloadSize, - H264Information& h264Information); - - int32_t SendH264SVC(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const uint8_t* payloadData, - const uint32_t payloadSize, - H264Information& h264Information); - - // H.264 AVC - int32_t SetH264PacketizationMode(const H264PacketizationMode mode); - - int32_t SetH264SendModeNALU_PPS_SPS(const bool dontSend); - - // H.264 SVC - int32_t SetHighestSendLayer(const uint8_t dependencyQualityLayer, - const uint8_t temporalLayer); - - int32_t HighestSendLayer(uint8_t& dependencyQualityLayer, - uint8_t& temporalLayer); - -protected: - RTPSenderH264(RTPSenderInterface* rtpSender); - virtual ~RTPSenderH264(); - - int32_t Init(); - - virtual uint16_t FECPacketOverhead() const = 0; - virtual RtpVideoCodecTypes VideoCodecType() const = 0; - - virtual int32_t SendVideoPacket(const FrameType frameType, - const uint8_t* dataBuffer, - const uint16_t payloadLength, - const uint16_t rtpHeaderLength, - bool baseLayerVideoPacket=false) = 0; - - - bool SendH264SVCLayer(const FrameType frameType, - const uint8_t temporalID, - const uint8_t dependencyQualityID, - bool& higestLayer); - - // H.264 SVC - int32_t AddH264PACSINALU(const bool firstPacketInNALU, - const bool lastPacketInNALU, - const H264_PACSI_NALU& paci, - const H264_SVC_NALUHeader& svc, - const uint16_t DONC, - uint8_t* databuffer, - int32_t& curByte) const; - - int32_t SendH264FillerData(const WebRtcRTPHeader* rtpHeader, - const uint16_t bytesToSend, - const uint32_t ssrc); - - int32_t SendH264FillerData(const uint32_t captureTimestamp, - const uint8_t payloadType, - const uint32_t bytesToSend); - - int32_t SendH264SVCRelayPacket(const WebRtcRTPHeader* rtpHeader, - const uint8_t* incomingRTPPacket, - const uint16_t incomingRTPPacketSize, - const uint32_t ssrc, - const bool higestLayer); - - int32_t SetH264RelaySequenceNumber(const uint16_t seqNum); - - int32_t SetH264RelayCompleteLayer(const bool complete); - - // H.264 - H264PacketizationMode _h264Mode; - bool _h264SendPPS_SPS; - - // H.264-SVC - int8_t _h264SVCPayloadType; - uint16_t _h264SVCRelaySequenceNumber; - uint32_t _h264SVCRelayTimeStamp; - bool _h264SVCRelayLayerComplete; - - -private: - // H.264 - int32_t SendH264_SingleMode(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength, - const bool sendSVCPACSI=false); - - int32_t SendH264_FU_A(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength, - const bool sendSVCPACSI = false); - - int32_t SendH264_STAP_A(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - bool& switchToFUA, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLength); - - int32_t SendH264_STAP_A_PACSI(const FrameType frameType, - const H264Info* ptrH264Info, - uint16_t &idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - bool& switchToFUA, - int32_t &payloadBytesToSend, - const uint8_t*& data, - const uint16_t rtpHeaderLengh) - - int32_t SendH264_SinglePACSI(const FrameType frameType, - const H264Info* ptrH264Info, - const uint16_t idxNALU, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const bool firstPacketInNALU, - const bool lastPacketInNALU); - - bool AddH264SVCNALUHeader(const H264_SVC_NALUHeader& svc, - uint8_t* databuffer, - int32_t& curByte) const; - - RTPSenderInterface& _rtpSender; - - // relay - bool _useHighestSendLayer; - uint8_t _highestDependencyLayerOld; - uint8_t _highestDependencyQualityIDOld; - uint8_t _highestDependencyLayer; - uint8_t _highestDependencyQualityID; - uint8_t _highestTemporalLayer; - - -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_RTP_SENDER_H264_H_ diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index 5b3b77fd18..2bec052787 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -369,18 +369,6 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, // Clear any previous modules. vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_); } - // Enable this if H264 is available. - // This sets the wanted packetization mode. - // if (video_codec.plType == kVideoCodecH264) { - // if (video_codec.codecSpecific.H264.packetization == kH264SingleMode) { - // rtp_rtcp_->SetH264PacketizationMode(H264_SINGLE_NAL_MODE); - // } else { - // rtp_rtcp_->SetH264PacketizationMode(H264_NON_INTERLEAVED_MODE); - // } - // if (video_codec.codecSpecific.H264.configParametersSize > 0) { - // rtp_rtcp_->SetH264SendModeNALU_PPS_SPS(true); - // } - // } // Don't log this error, no way to check in advance if this pl_type is // registered or not...