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:
stefan@webrtc.org 2014-08-07 15:09:24 +00:00
parent 9d74f7ce8c
commit 59a2f9f584
9 changed files with 0 additions and 3363 deletions

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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...