return 1 << exp;
}
-void RTPPayload::SetType(RtpVideoCodecTypes videoType) {
- type = videoType;
-
- switch (type) {
- case kRtpVideoGeneric:
- break;
- case kRtpVideoVp8: {
- info.VP8.nonReferenceFrame = false;
- info.VP8.beginningOfPartition = false;
- info.VP8.partitionID = 0;
- info.VP8.hasPictureID = false;
- info.VP8.hasTl0PicIdx = false;
- info.VP8.hasTID = false;
- info.VP8.hasKeyIdx = false;
- info.VP8.pictureID = -1;
- info.VP8.tl0PicIdx = -1;
- info.VP8.tID = -1;
- info.VP8.layerSync = false;
- info.VP8.frameWidth = 0;
- info.VP8.frameHeight = 0;
- break;
- }
- default:
- break;
- }
-}
-
RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
const size_t rtpDataLength)
: _ptrRTPDataBegin(rtpData),
}
return num_zero_bytes;
}
-
-RTPPayloadParser::RTPPayloadParser(const RtpVideoCodecTypes videoType,
- const uint8_t* payloadData,
- uint16_t payloadDataLength)
- : _dataPtr(payloadData),
- _dataLength(payloadDataLength),
- _videoType(videoType) {}
-
-RTPPayloadParser::~RTPPayloadParser() {
-}
-
-bool RTPPayloadParser::Parse(RTPPayload& parsedPacket) const {
- parsedPacket.SetType(_videoType);
-
- switch (_videoType) {
- case kRtpVideoGeneric:
- return ParseGeneric(parsedPacket);
- case kRtpVideoVp8:
- return ParseVP8(parsedPacket);
- default:
- return false;
- }
-}
-
-bool RTPPayloadParser::ParseGeneric(RTPPayload& /*parsedPacket*/) const {
- return false;
-}
-
-//
-// VP8 format:
-//
-// Payload descriptor
-// 0 1 2 3 4 5 6 7
-// +-+-+-+-+-+-+-+-+
-// |X|R|N|S|PartID | (REQUIRED)
-// +-+-+-+-+-+-+-+-+
-// X: |I|L|T|K| RSV | (OPTIONAL)
-// +-+-+-+-+-+-+-+-+
-// I: | PictureID | (OPTIONAL)
-// +-+-+-+-+-+-+-+-+
-// L: | TL0PICIDX | (OPTIONAL)
-// +-+-+-+-+-+-+-+-+
-// T/K: |TID:Y| KEYIDX | (OPTIONAL)
-// +-+-+-+-+-+-+-+-+
-//
-// Payload header (considered part of the actual payload, sent to decoder)
-// 0 1 2 3 4 5 6 7
-// +-+-+-+-+-+-+-+-+
-// |Size0|H| VER |P|
-// +-+-+-+-+-+-+-+-+
-// | ... |
-// + +
-
-bool RTPPayloadParser::ParseVP8(RTPPayload& parsedPacket) const {
- RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
- const uint8_t* dataPtr = _dataPtr;
- int dataLength = _dataLength;
-
- // Parse mandatory first byte of payload descriptor
- bool extension = (*dataPtr & 0x80) ? true : false; // X bit
- vp8->nonReferenceFrame = (*dataPtr & 0x20) ? true : false; // N bit
- vp8->beginningOfPartition = (*dataPtr & 0x10) ? true : false; // S bit
- vp8->partitionID = (*dataPtr & 0x0F); // PartID field
-
- if (vp8->partitionID > 8) {
- // Weak check for corrupt data: PartID MUST NOT be larger than 8.
- return false;
- }
-
- // Advance dataPtr and decrease remaining payload size
- dataPtr++;
- dataLength--;
-
- if (extension) {
- const int parsedBytes = ParseVP8Extension(vp8, dataPtr, dataLength);
- if (parsedBytes < 0) return false;
- dataPtr += parsedBytes;
- dataLength -= parsedBytes;
- }
-
- if (dataLength <= 0) {
- LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
- return false;
- }
-
- // Read P bit from payload header (only at beginning of first partition)
- if (dataLength > 0 && vp8->beginningOfPartition && vp8->partitionID == 0) {
- parsedPacket.frameType = (*dataPtr & 0x01) ? kPFrame : kIFrame;
- } else {
- parsedPacket.frameType = kPFrame;
- }
- if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) {
- return false;
- }
- parsedPacket.info.VP8.data = dataPtr;
- parsedPacket.info.VP8.dataLength = dataLength;
- return true;
-}
-
-int RTPPayloadParser::ParseVP8FrameSize(RTPPayload& parsedPacket,
- const uint8_t* dataPtr,
- int dataLength) const {
- if (parsedPacket.frameType != kIFrame) {
- // Included in payload header for I-frames.
- return 0;
- }
- if (dataLength < 10) {
- // For an I-frame we should always have the uncompressed VP8 header
- // in the beginning of the partition.
- return -1;
- }
- RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
- vp8->frameWidth = ((dataPtr[7] << 8) + dataPtr[6]) & 0x3FFF;
- vp8->frameHeight = ((dataPtr[9] << 8) + dataPtr[8]) & 0x3FFF;
- return 0;
-}
-
-int RTPPayloadParser::ParseVP8Extension(RTPPayloadVP8* vp8,
- const uint8_t* dataPtr,
- int dataLength) const {
- int parsedBytes = 0;
- if (dataLength <= 0) return -1;
- // Optional X field is present
- vp8->hasPictureID = (*dataPtr & 0x80) ? true : false; // I bit
- vp8->hasTl0PicIdx = (*dataPtr & 0x40) ? true : false; // L bit
- vp8->hasTID = (*dataPtr & 0x20) ? true : false; // T bit
- vp8->hasKeyIdx = (*dataPtr & 0x10) ? true : false; // K bit
-
- // Advance dataPtr and decrease remaining payload size
- dataPtr++;
- parsedBytes++;
- dataLength--;
-
- if (vp8->hasPictureID) {
- if (ParseVP8PictureID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
- return -1;
- }
- }
-
- if (vp8->hasTl0PicIdx) {
- if (ParseVP8Tl0PicIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
- return -1;
- }
- }
-
- if (vp8->hasTID || vp8->hasKeyIdx) {
- if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
- return -1;
- }
- }
- return parsedBytes;
-}
-
-int RTPPayloadParser::ParseVP8PictureID(RTPPayloadVP8* vp8,
- const uint8_t** dataPtr,
- int* dataLength,
- int* parsedBytes) const {
- if (*dataLength <= 0) return -1;
- vp8->pictureID = (**dataPtr & 0x7F);
- if (**dataPtr & 0x80) {
- (*dataPtr)++;
- (*parsedBytes)++;
- if (--(*dataLength) <= 0) return -1;
- // PictureID is 15 bits
- vp8->pictureID = (vp8->pictureID << 8) +** dataPtr;
- }
- (*dataPtr)++;
- (*parsedBytes)++;
- (*dataLength)--;
- return 0;
-}
-
-int RTPPayloadParser::ParseVP8Tl0PicIdx(RTPPayloadVP8* vp8,
- const uint8_t** dataPtr,
- int* dataLength,
- int* parsedBytes) const {
- if (*dataLength <= 0) return -1;
- vp8->tl0PicIdx = **dataPtr;
- (*dataPtr)++;
- (*parsedBytes)++;
- (*dataLength)--;
- return 0;
-}
-
-int RTPPayloadParser::ParseVP8TIDAndKeyIdx(RTPPayloadVP8* vp8,
- const uint8_t** dataPtr,
- int* dataLength,
- int* parsedBytes) const {
- if (*dataLength <= 0) return -1;
- if (vp8->hasTID) {
- vp8->tID = ((**dataPtr >> 6) & 0x03);
- vp8->layerSync = (**dataPtr & 0x20) ? true : false; // Y bit
- }
- if (vp8->hasKeyIdx) {
- vp8->keyIdx = (**dataPtr & 0x1F);
- }
- (*dataPtr)++;
- (*parsedBytes)++;
- (*dataLength)--;
- return 0;
-}
-
} // namespace RtpUtility
} // namespace webrtc