Remove the old H264 code now that a new H.264 packetizer has been implemented.
R=pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/15109004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6847 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
9d74f7ce8c
commit
59a2f9f584
@ -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 <string.h>
|
||||
|
||||
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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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 <string.h>
|
||||
#include "h264_information.h"
|
||||
|
||||
//#define DEBUG_SEI_MESSAGE 1
|
||||
|
||||
#ifdef DEBUG_SEI_MESSAGE
|
||||
#include "bitstream_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
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
|
@ -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<KMaxNumberOfSEINALUs; i++)
|
||||
{
|
||||
if(seiMessageData[i])
|
||||
{
|
||||
delete [] seiMessageData[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t NALlength;
|
||||
const uint8_t type;
|
||||
uint8_t X;
|
||||
uint8_t Y;
|
||||
// uint8_t T;
|
||||
uint8_t A;
|
||||
uint8_t P;
|
||||
uint8_t C;
|
||||
uint8_t S;
|
||||
uint8_t E;
|
||||
uint8_t TL0picIDx;
|
||||
uint16_t IDRpicID;
|
||||
uint16_t DONC;
|
||||
uint32_t numSEINALUs;
|
||||
uint32_t seiMessageLength[KMaxNumberOfSEINALUs]; // we allow KMaxNumberOfSEINALUs SEI messages
|
||||
uint8_t* seiMessageData[KMaxNumberOfSEINALUs];
|
||||
};
|
||||
|
||||
struct H264Info
|
||||
{
|
||||
H264Info()
|
||||
:
|
||||
numNALUs(0),
|
||||
numLayers(0)
|
||||
{
|
||||
memset(startCodeSize, 0, sizeof(startCodeSize));
|
||||
memset(payloadSize, 0, sizeof(payloadSize));
|
||||
memset(NRI, 0, sizeof(NRI));
|
||||
memset(type, 0, sizeof(type));
|
||||
memset(accLayerSize, 0, sizeof(accLayerSize));
|
||||
}
|
||||
uint16_t numNALUs;
|
||||
uint8_t numLayers;
|
||||
uint8_t startCodeSize[KMaxNumberOfNALUs];
|
||||
uint32_t payloadSize[KMaxNumberOfNALUs];
|
||||
uint8_t NRI[KMaxNumberOfNALUs];
|
||||
uint8_t type[KMaxNumberOfNALUs];
|
||||
H264_SVC_NALUHeader SVCheader[KMaxNumberOfNALUs];
|
||||
H264_PACSI_NALU PACSI[KMaxNumberOfNALUs];
|
||||
int32_t accLayerSize[KMaxNumberOfLayers];
|
||||
};
|
||||
|
||||
|
||||
class H264Information : public VideoCodecInformation
|
||||
{
|
||||
public:
|
||||
H264Information(const bool SVC);
|
||||
~H264Information();
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
virtual RtpVideoCodecTypes Type();
|
||||
|
||||
virtual int32_t GetInfo(const uint8_t* ptrEncodedBuffer, const uint32_t length, const H264Info*& ptrInfo);
|
||||
|
||||
|
||||
protected:
|
||||
bool HasInfo(const uint32_t length);
|
||||
int32_t FindInfo(const uint8_t* ptrEncodedBuffer, const uint32_t length);
|
||||
|
||||
void GetNRI();
|
||||
int32_t FindNALU();
|
||||
int32_t FindNALUStartCodeSize();
|
||||
int32_t FindNALUType();
|
||||
|
||||
int32_t ParseSVCNALUHeader();
|
||||
|
||||
void SetLayerSEBit(int32_t foundLast);
|
||||
int32_t SetLayerLengths();
|
||||
|
||||
private:
|
||||
const bool _SVC;
|
||||
const uint8_t* _ptrData;
|
||||
uint32_t _length;
|
||||
uint32_t _parsedLength;
|
||||
uint32_t _remLength;
|
||||
H264Info _info;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_H264_INFORMATION_H_
|
File diff suppressed because it is too large
Load Diff
@ -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_
|
@ -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...
|
||||
|
Loading…
x
Reference in New Issue
Block a user