Updating to VP8 RTP spec rev -02
Updating the VP8 packetizer class (RtpFormatVp8) and VP8 parser (in class RTPPayloadParser) to follow the -02 revision of the spec. See http://tools.ietf.org/html/draft-ietf-payload-vp8-02. Updating the unit tests, too. Finally, updating the tests to follow the recommendations from the test team; specifically including the test code in the webrtc namespace, and omitting the main function at the end of each test file. Review URL: http://webrtc-codereview.appspot.com/296003 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1013 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
517dcb71f2
commit
6f2c0168f0
@ -46,6 +46,7 @@ struct RTPVideoHeaderH263
|
||||
enum {kNoPictureId = -1};
|
||||
enum {kNoTl0PicIdx = -1};
|
||||
enum {kNoTemporalIdx = -1};
|
||||
enum {kNoKeyIdx = -1};
|
||||
enum {kNoSimulcastIdx = 0};
|
||||
|
||||
struct RTPVideoHeaderVP8
|
||||
@ -56,6 +57,7 @@ struct RTPVideoHeaderVP8
|
||||
pictureId = kNoPictureId;
|
||||
tl0PicIdx = kNoTl0PicIdx;
|
||||
temporalIdx = kNoTemporalIdx;
|
||||
keyIdx = kNoKeyIdx;
|
||||
partitionId = 0;
|
||||
beginningOfPartition = false;
|
||||
frameWidth = 0;
|
||||
@ -68,6 +70,7 @@ struct RTPVideoHeaderVP8
|
||||
WebRtc_Word16 tl0PicIdx; // TL0PIC_IDX, 8 bits;
|
||||
// kNoTl0PicIdx means no value provided.
|
||||
WebRtc_Word8 temporalIdx; // Temporal layer index, or kNoTemporalIdx.
|
||||
int keyIdx; // 5 bits; kNoKeyIdx means not used.
|
||||
int partitionId; // VP8 partition ID
|
||||
bool beginningOfPartition; // True if this packet is the first
|
||||
// in a VP8 partition. Otherwise false
|
||||
|
@ -178,13 +178,13 @@ int RtpFormatVp8::WriteHeaderAndPayload(int payload_bytes,
|
||||
// +-+-+-+-+-+-+-+-+-+
|
||||
// |X| |N|S| PART_ID |
|
||||
// +-+-+-+-+-+-+-+-+-+
|
||||
// X: |I|L|T| | (mandatory if any of the below are used)
|
||||
// X: |I|L|T|K| | (mandatory if any of the below are used)
|
||||
// +-+-+-+-+-+-+-+-+-+
|
||||
// I: |PictureID (8/16b)| (optional)
|
||||
// +-+-+-+-+-+-+-+-+-+
|
||||
// L: | TL0PIC_IDX | (optional)
|
||||
// +-+-+-+-+-+-+-+-+-+
|
||||
// T: | TID | | (optional)
|
||||
// T/K: | TID | KEYIDX | (optional)
|
||||
// +-+-+-+-+-+-+-+-+-+
|
||||
|
||||
assert(payload_bytes > 0);
|
||||
@ -235,9 +235,9 @@ const
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (TIDFieldPresent())
|
||||
if (TIDFieldPresent() || KeyIdxFieldPresent())
|
||||
{
|
||||
if (WriteTIDFields(x_field, buffer, buffer_length,
|
||||
if (WriteTIDAndKeyIdxFields(x_field, buffer, buffer_length,
|
||||
&extension_length) < 0)
|
||||
{
|
||||
return -1;
|
||||
@ -299,7 +299,7 @@ int RtpFormatVp8::WriteTl0PicIdxFields(WebRtc_UWord8* x_field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RtpFormatVp8::WriteTIDFields(WebRtc_UWord8* x_field,
|
||||
int RtpFormatVp8::WriteTIDAndKeyIdxFields(WebRtc_UWord8* x_field,
|
||||
WebRtc_UWord8* buffer,
|
||||
int buffer_length,
|
||||
int* extension_length) const
|
||||
@ -309,9 +309,19 @@ int RtpFormatVp8::WriteTIDFields(WebRtc_UWord8* x_field,
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
WebRtc_UWord8* data_field =
|
||||
&buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length];
|
||||
*data_field = 0;
|
||||
if (TIDFieldPresent())
|
||||
{
|
||||
*x_field |= kTBit;
|
||||
buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length]
|
||||
= hdr_info_.temporalIdx << 5;
|
||||
*data_field |= hdr_info_.temporalIdx << 5;
|
||||
}
|
||||
if (KeyIdxFieldPresent())
|
||||
{
|
||||
*x_field |= kKBit;
|
||||
*data_field |= (hdr_info_.keyIdx & kKeyIdxField);
|
||||
}
|
||||
++*extension_length;
|
||||
return 0;
|
||||
}
|
||||
@ -320,7 +330,7 @@ int RtpFormatVp8::PayloadDescriptorExtraLength() const
|
||||
{
|
||||
int length_bytes = PictureIdLength();
|
||||
if (TL0PicIdxFieldPresent()) ++length_bytes;
|
||||
if (TIDFieldPresent()) ++length_bytes;
|
||||
if (TIDFieldPresent() || KeyIdxFieldPresent()) ++length_bytes;
|
||||
if (length_bytes > 0) ++length_bytes; // Include the extension field.
|
||||
return length_bytes;
|
||||
}
|
||||
@ -340,7 +350,8 @@ int RtpFormatVp8::PictureIdLength() const
|
||||
|
||||
bool RtpFormatVp8::XFieldPresent() const
|
||||
{
|
||||
return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent());
|
||||
return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent()
|
||||
|| KeyIdxFieldPresent());
|
||||
}
|
||||
|
||||
bool RtpFormatVp8::TIDFieldPresent() const
|
||||
@ -348,6 +359,11 @@ bool RtpFormatVp8::TIDFieldPresent() const
|
||||
return (hdr_info_.temporalIdx != kNoTemporalIdx);
|
||||
}
|
||||
|
||||
bool RtpFormatVp8::KeyIdxFieldPresent() const
|
||||
{
|
||||
return (hdr_info_.keyIdx != kNoKeyIdx);
|
||||
}
|
||||
|
||||
bool RtpFormatVp8::TL0PicIdxFieldPresent() const
|
||||
{
|
||||
return (hdr_info_.tl0PicIdx != kNoTl0PicIdx);
|
||||
|
@ -84,9 +84,11 @@ private:
|
||||
static const int kNBit = 0x20;
|
||||
static const int kSBit = 0x10;
|
||||
static const int kPartIdField = 0x0F;
|
||||
static const int kKeyIdxField = 0x1F;
|
||||
static const int kIBit = 0x80;
|
||||
static const int kLBit = 0x40;
|
||||
static const int kTBit = 0x20;
|
||||
static const int kKBit = 0x10;
|
||||
|
||||
// Calculate size of next chunk to send. Returns 0 if none can be sent.
|
||||
int CalcNextSize(int max_payload_len, int remaining_bytes,
|
||||
@ -115,9 +117,10 @@ private:
|
||||
int WriteTl0PicIdxFields(WebRtc_UWord8* x_field, WebRtc_UWord8* buffer,
|
||||
int buffer_length, int* extension_length) const;
|
||||
|
||||
// Set the T bit in the x_field, and write TID to the appropriate
|
||||
// position in buffer. The function returns 0 on success, -1 otherwise.
|
||||
int WriteTIDFields(WebRtc_UWord8* x_field, WebRtc_UWord8* buffer,
|
||||
// Set the T and K bits in the x_field, and write TID and KeyIdx to the
|
||||
// appropriate position in buffer. The function returns 0 on success,
|
||||
// -1 otherwise.
|
||||
int WriteTIDAndKeyIdxFields(WebRtc_UWord8* x_field, WebRtc_UWord8* buffer,
|
||||
int buffer_length, int* extension_length) const;
|
||||
|
||||
// Write the PictureID from codec_specific_info_ to buffer. One or two
|
||||
@ -136,6 +139,7 @@ private:
|
||||
// Check whether each of the optional fields will be included in the header.
|
||||
bool XFieldPresent() const;
|
||||
bool TIDFieldPresent() const;
|
||||
bool KeyIdxFieldPresent() const;
|
||||
bool TL0PicIdxFieldPresent() const;
|
||||
bool PictureIdPresent() const { return (PictureIdLength() > 0); }
|
||||
|
||||
|
@ -18,11 +18,7 @@
|
||||
#include "typedefs.h"
|
||||
#include "rtp_format_vp8.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using webrtc::RTPFragmentationHeader;
|
||||
using webrtc::RtpFormatVp8;
|
||||
using webrtc::RTPVideoHeaderVP8;
|
||||
namespace webrtc {
|
||||
|
||||
const int kPayloadSize = 30;
|
||||
const int kBufferSize = kPayloadSize + 6; // Add space for payload descriptor.
|
||||
@ -35,7 +31,7 @@ class RtpFormatVp8Test : public ::testing::Test {
|
||||
void CheckHeader(bool first_in_frame, bool frag_start, int part_id);
|
||||
void CheckPictureID();
|
||||
void CheckTl0PicIdx();
|
||||
void CheckTID();
|
||||
void CheckTIDAndKeyIdx();
|
||||
void CheckPayload(int payload_end);
|
||||
void CheckLast(bool last) const;
|
||||
void CheckPacket(int send_bytes, int expect_bytes, bool last,
|
||||
@ -66,10 +62,11 @@ void RtpFormatVp8Test::SetUp() {
|
||||
fragmentation_->fragmentationOffset[1] = 10;
|
||||
fragmentation_->fragmentationOffset[2] = 20;
|
||||
|
||||
hdr_info_.pictureId = webrtc::kNoPictureId;
|
||||
hdr_info_.pictureId = kNoPictureId;
|
||||
hdr_info_.nonReference = false;
|
||||
hdr_info_.temporalIdx = webrtc::kNoTemporalIdx;
|
||||
hdr_info_.tl0PicIdx = webrtc::kNoTl0PicIdx;
|
||||
hdr_info_.temporalIdx = kNoTemporalIdx;
|
||||
hdr_info_.tl0PicIdx = kNoTl0PicIdx;
|
||||
hdr_info_.keyIdx = kNoKeyIdx;
|
||||
}
|
||||
|
||||
void RtpFormatVp8Test::TearDown() {
|
||||
@ -96,7 +93,11 @@ void RtpFormatVp8Test::TearDown() {
|
||||
|
||||
#define EXPECT_BIT_T_EQ(x,a) EXPECT_BIT_EQ(x, 5, a)
|
||||
|
||||
#define EXPECT_TID_EQ(x,a) EXPECT_EQ((((x)&0xE0) >> 5), a)
|
||||
#define EXPECT_BIT_K_EQ(x,a) EXPECT_BIT_EQ(x, 4, a)
|
||||
|
||||
#define EXPECT_TID_EQ(x,a) EXPECT_EQ((((x) & 0xE0) >> 5), a)
|
||||
|
||||
#define EXPECT_KEYIDX_EQ(x,a) EXPECT_EQ(((x) & 0x1F), a)
|
||||
|
||||
void RtpFormatVp8Test::CheckHeader(bool first_in_frame, bool frag_start,
|
||||
int part_id)
|
||||
@ -105,15 +106,16 @@ void RtpFormatVp8Test::CheckHeader(bool first_in_frame, bool frag_start,
|
||||
EXPECT_BIT_EQ(buffer_[0], 6, 0); // check reserved bit
|
||||
|
||||
|
||||
if (hdr_info_.pictureId != webrtc::kNoPictureId ||
|
||||
hdr_info_.temporalIdx != webrtc::kNoTemporalIdx ||
|
||||
hdr_info_.tl0PicIdx != webrtc::kNoTl0PicIdx)
|
||||
if (hdr_info_.pictureId != kNoPictureId ||
|
||||
hdr_info_.temporalIdx != kNoTemporalIdx ||
|
||||
hdr_info_.tl0PicIdx != kNoTl0PicIdx ||
|
||||
hdr_info_.keyIdx != kNoKeyIdx)
|
||||
{
|
||||
EXPECT_BIT_X_EQ(buffer_[0], 1);
|
||||
++payload_start_;
|
||||
CheckPictureID();
|
||||
CheckTl0PicIdx();
|
||||
CheckTID();
|
||||
CheckTIDAndKeyIdx();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -137,7 +139,7 @@ void RtpFormatVp8Test::CheckHeader(bool first_in_frame, bool frag_start,
|
||||
|
||||
void RtpFormatVp8Test::CheckPictureID()
|
||||
{
|
||||
if (hdr_info_.pictureId != webrtc::kNoPictureId)
|
||||
if (hdr_info_.pictureId != kNoPictureId)
|
||||
{
|
||||
EXPECT_BIT_I_EQ(buffer_[1], 1);
|
||||
if (hdr_info_.pictureId > 0x7F)
|
||||
@ -165,7 +167,7 @@ void RtpFormatVp8Test::CheckPictureID()
|
||||
|
||||
void RtpFormatVp8Test::CheckTl0PicIdx()
|
||||
{
|
||||
if (hdr_info_.tl0PicIdx != webrtc::kNoTl0PicIdx)
|
||||
if (hdr_info_.tl0PicIdx != kNoTl0PicIdx)
|
||||
{
|
||||
EXPECT_BIT_L_EQ(buffer_[1], 1);
|
||||
EXPECT_EQ(buffer_[payload_start_], hdr_info_.tl0PicIdx);
|
||||
@ -177,19 +179,36 @@ void RtpFormatVp8Test::CheckTl0PicIdx()
|
||||
}
|
||||
}
|
||||
|
||||
void RtpFormatVp8Test::CheckTID()
|
||||
void RtpFormatVp8Test::CheckTIDAndKeyIdx()
|
||||
{
|
||||
if (hdr_info_.temporalIdx != webrtc::kNoTemporalIdx)
|
||||
if (hdr_info_.temporalIdx == kNoTemporalIdx &&
|
||||
hdr_info_.keyIdx == kNoKeyIdx)
|
||||
{
|
||||
EXPECT_BIT_T_EQ(buffer_[1], 0);
|
||||
EXPECT_BIT_K_EQ(buffer_[1], 0);
|
||||
return;
|
||||
}
|
||||
if (hdr_info_.temporalIdx != kNoTemporalIdx)
|
||||
{
|
||||
EXPECT_BIT_T_EQ(buffer_[1], 1);
|
||||
EXPECT_TID_EQ(buffer_[payload_start_], hdr_info_.temporalIdx);
|
||||
EXPECT_EQ(buffer_[payload_start_] & 0x1F, 0);
|
||||
++payload_start_;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_BIT_T_EQ(buffer_[1], 0);
|
||||
EXPECT_TID_EQ(buffer_[payload_start_], 0);
|
||||
}
|
||||
if (hdr_info_.keyIdx != kNoKeyIdx)
|
||||
{
|
||||
EXPECT_BIT_K_EQ(buffer_[1], 1);
|
||||
EXPECT_KEYIDX_EQ(buffer_[payload_start_], hdr_info_.keyIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_BIT_K_EQ(buffer_[1], 0);
|
||||
EXPECT_KEYIDX_EQ(buffer_[payload_start_], 0);
|
||||
}
|
||||
++payload_start_;
|
||||
}
|
||||
|
||||
void RtpFormatVp8Test::CheckPayload(int payload_end)
|
||||
@ -232,7 +251,7 @@ TEST_F(RtpFormatVp8Test, TestStrictMode)
|
||||
|
||||
hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
|
||||
hdr_info_, *fragmentation_, webrtc::kStrict);
|
||||
hdr_info_, *fragmentation_, kStrict);
|
||||
|
||||
// get first packet, expect balanced size ~= same as second packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(13, buffer_, &send_bytes, &last));
|
||||
@ -289,7 +308,7 @@ TEST_F(RtpFormatVp8Test, TestAggregateMode)
|
||||
|
||||
hdr_info_.pictureId = 20; // <= 0x7F should produce 1-byte PictureID
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
|
||||
hdr_info_, *fragmentation_, webrtc::kAggregate);
|
||||
hdr_info_, *fragmentation_, kAggregate);
|
||||
|
||||
// get first packet
|
||||
// first part of first partition (balanced fragments are expected)
|
||||
@ -328,9 +347,9 @@ TEST_F(RtpFormatVp8Test, TestSloppyMode)
|
||||
bool last;
|
||||
bool first_in_frame = true;
|
||||
|
||||
hdr_info_.pictureId = webrtc::kNoPictureId; // no PictureID
|
||||
hdr_info_.pictureId = kNoPictureId; // no PictureID
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
|
||||
hdr_info_, *fragmentation_, webrtc::kSloppy);
|
||||
hdr_info_, *fragmentation_, kSloppy);
|
||||
|
||||
// get first packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer_, &send_bytes, &last));
|
||||
@ -431,7 +450,7 @@ TEST_F(RtpFormatVp8Test, TestTl0PicIdxAndTID) {
|
||||
hdr_info_.tl0PicIdx = 117;
|
||||
hdr_info_.temporalIdx = 2;
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
|
||||
hdr_info_, *fragmentation_, webrtc::kAggregate);
|
||||
hdr_info_, *fragmentation_, kAggregate);
|
||||
|
||||
// get first and only packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes,
|
||||
@ -442,10 +461,41 @@ TEST_F(RtpFormatVp8Test, TestTl0PicIdxAndTID) {
|
||||
/* frag_start */ true);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
// Verify KeyIdx field
|
||||
TEST_F(RtpFormatVp8Test, TestKeyIdx) {
|
||||
int send_bytes = 0;
|
||||
bool last;
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
hdr_info_.keyIdx = 17;
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
|
||||
hdr_info_, *fragmentation_, kAggregate);
|
||||
|
||||
// get first and only packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes,
|
||||
&last));
|
||||
bool first_in_frame = true;
|
||||
CheckPacket(send_bytes, kPayloadSize + 3, last,
|
||||
first_in_frame,
|
||||
/* frag_start */ true);
|
||||
}
|
||||
|
||||
// Verify TID field and KeyIdx field in combination
|
||||
TEST_F(RtpFormatVp8Test, TestTIDAndKeyIdx) {
|
||||
int send_bytes = 0;
|
||||
bool last;
|
||||
|
||||
hdr_info_.temporalIdx = 1;
|
||||
hdr_info_.keyIdx = 5;
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
|
||||
hdr_info_, *fragmentation_, kAggregate);
|
||||
|
||||
// get first and only packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes,
|
||||
&last));
|
||||
bool first_in_frame = true;
|
||||
CheckPacket(send_bytes, kPayloadSize + 3, last,
|
||||
first_in_frame,
|
||||
/* frag_start */ true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -812,13 +812,13 @@ ModuleRTPUtility::RTPPayloadParser::ParseMPEG4(
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |X|R|N|S|PartID | (REQUIRED)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// X: |I|L|T| RSV-A | (OPTIONAL)
|
||||
// X: |I|L|T|K| RSV | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// I: | PictureID | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// L: | TL0PICIDX | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// T: | TID | RSV-B | (OPTIONAL)
|
||||
// T/K: | TID | KEYIDX | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Payload header (considered part of the actual payload, sent to decoder)
|
||||
@ -912,6 +912,7 @@ int ModuleRTPUtility::RTPPayloadParser::ParseVP8Extension(
|
||||
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++;
|
||||
@ -934,9 +935,9 @@ int ModuleRTPUtility::RTPPayloadParser::ParseVP8Extension(
|
||||
}
|
||||
}
|
||||
|
||||
if (vp8->hasTID)
|
||||
if (vp8->hasTID || vp8->hasKeyIdx)
|
||||
{
|
||||
if (ParseVP8TID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0)
|
||||
if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -982,14 +983,21 @@ ModuleRTPUtility::RTPPayloadParser::ParseVP8Tl0PicIdx(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModuleRTPUtility::RTPPayloadParser::ParseVP8TID(
|
||||
int ModuleRTPUtility::RTPPayloadParser::ParseVP8TIDAndKeyIdx(
|
||||
RTPPayloadVP8 *vp8,
|
||||
const WebRtc_UWord8 **dataPtr,
|
||||
int *dataLength,
|
||||
int *parsedBytes) const
|
||||
{
|
||||
if (*dataLength <= 0) return -1;
|
||||
if (vp8->hasTID)
|
||||
{
|
||||
vp8->tID = ((**dataPtr >> 5) & 0x07);
|
||||
}
|
||||
if (vp8->hasKeyIdx)
|
||||
{
|
||||
vp8->keyIdx = (**dataPtr & 0x1F);
|
||||
}
|
||||
(*dataPtr)++;
|
||||
(*parsedBytes)++;
|
||||
(*dataLength)--;
|
||||
|
@ -145,9 +145,11 @@ namespace ModuleRTPUtility
|
||||
bool hasPictureID;
|
||||
bool hasTl0PicIdx;
|
||||
bool hasTID;
|
||||
bool hasKeyIdx;
|
||||
int pictureID;
|
||||
int tl0PicIdx;
|
||||
int tID;
|
||||
int keyIdx;
|
||||
int frameWidth;
|
||||
int frameHeight;
|
||||
|
||||
@ -208,7 +210,7 @@ namespace ModuleRTPUtility
|
||||
int *dataLength,
|
||||
int *parsedBytes) const;
|
||||
|
||||
int ParseVP8TID(RTPPayloadVP8 *vp8,
|
||||
int ParseVP8TIDAndKeyIdx(RTPPayloadVP8 *vp8,
|
||||
const WebRtc_UWord8 **dataPtr,
|
||||
int *dataLength,
|
||||
int *parsedBytes) const;
|
||||
|
@ -19,25 +19,24 @@
|
||||
#include "rtp_utility.h"
|
||||
#include "rtp_format_vp8.h"
|
||||
|
||||
namespace {
|
||||
namespace webrtc {
|
||||
|
||||
using webrtc::ModuleRTPUtility::RTPPayloadParser;
|
||||
using webrtc::ModuleRTPUtility::RTPPayload;
|
||||
using webrtc::ModuleRTPUtility::RTPPayloadVP8;
|
||||
using webrtc::RtpVideoCodecTypes;
|
||||
using ModuleRTPUtility::RTPPayloadParser;
|
||||
using ModuleRTPUtility::RTPPayload;
|
||||
using ModuleRTPUtility::RTPPayloadVP8;
|
||||
|
||||
// Payload descriptor
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |X|R|N|S|PartID | (REQUIRED)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// X: |I|L|T| RSV-A | (OPTIONAL)
|
||||
// X: |I|L|T|K| RSV | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// I: | PictureID | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// L: | TL0PICIDX | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// T: | TID | RSV-B | (OPTIONAL)
|
||||
// T/K: | TID | KEYIDX | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Payload header
|
||||
@ -65,11 +64,13 @@ void VerifyBasicHeader(const RTPPayloadVP8 &header, bool N, bool S, int PartID)
|
||||
EXPECT_EQ(PartID, header.partitionID);
|
||||
}
|
||||
|
||||
void VerifyExtensions(const RTPPayloadVP8 &header, bool I, bool L, bool T)
|
||||
void VerifyExtensions(const RTPPayloadVP8 &header,
|
||||
bool I, bool L, bool T, bool K)
|
||||
{
|
||||
EXPECT_EQ(I, header.hasPictureID);
|
||||
EXPECT_EQ(L, header.hasTl0PicIdx);
|
||||
EXPECT_EQ(T, header.hasTID);
|
||||
EXPECT_EQ(K, header.hasKeyIdx);
|
||||
}
|
||||
|
||||
TEST(ParseVP8Test, BasicHeader) {
|
||||
@ -77,16 +78,16 @@ TEST(ParseVP8Test, BasicHeader) {
|
||||
payload[0] = 0x14; // binary 0001 0100; S = 1, PartID = 4
|
||||
payload[1] = 0x01; // P frame
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, payload, 4, 0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 4, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(webrtc::ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(webrtc::kRtpVp8Video, parsedPacket.type);
|
||||
EXPECT_EQ(ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 1 /*S*/, 4 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 0 /*T*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 0 /*T*/, 0 /*K*/);
|
||||
|
||||
EXPECT_EQ(payload + 1, parsedPacket.info.VP8.data);
|
||||
EXPECT_EQ(4 - 1, parsedPacket.info.VP8.dataLength);
|
||||
@ -98,16 +99,16 @@ TEST(ParseVP8Test, PictureID) {
|
||||
payload[1] = 0x80;
|
||||
payload[2] = 17;
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, payload, 10, 0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 10, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(webrtc::ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(webrtc::kRtpVp8Video, parsedPacket.type);
|
||||
EXPECT_EQ(ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 1 /*N*/, 0 /*S*/, 0 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 0 /*L*/, 0 /*T*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 0 /*L*/, 0 /*T*/, 0 /*K*/);
|
||||
|
||||
EXPECT_EQ(17, parsedPacket.info.VP8.pictureID);
|
||||
|
||||
@ -118,12 +119,12 @@ TEST(ParseVP8Test, PictureID) {
|
||||
// Re-use payload, but change to long PictureID
|
||||
payload[2] = 0x80 | 17;
|
||||
payload[3] = 17;
|
||||
RTPPayloadParser rtpPayloadParser2(webrtc::kRtpVp8Video, payload, 10, 0);
|
||||
RTPPayloadParser rtpPayloadParser2(kRtpVp8Video, payload, 10, 0);
|
||||
|
||||
ASSERT_TRUE(rtpPayloadParser2.Parse(parsedPacket));
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 1 /*N*/, 0 /*S*/, 0 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 0 /*L*/, 0 /*T*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 0 /*L*/, 0 /*T*/, 0 /*K*/);
|
||||
|
||||
EXPECT_EQ((17<<8) + 17, parsedPacket.info.VP8.pictureID);
|
||||
|
||||
@ -137,16 +138,16 @@ TEST(ParseVP8Test, Tl0PicIdx) {
|
||||
payload[1] = 0x40;
|
||||
payload[2] = 17;
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, payload, 13, 0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 13, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(webrtc::ModuleRTPUtility::kIFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(webrtc::kRtpVp8Video, parsedPacket.type);
|
||||
EXPECT_EQ(ModuleRTPUtility::kIFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 1 /*S*/, 0 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 1 /*L*/, 0 /*T*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 1 /*L*/, 0 /*T*/, 0 /*K*/);
|
||||
|
||||
EXPECT_EQ(17, parsedPacket.info.VP8.tl0PicIdx);
|
||||
|
||||
@ -160,16 +161,16 @@ TEST(ParseVP8Test, TID) {
|
||||
payload[1] = 0x20;
|
||||
payload[2] = 0x40;
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, payload, 10, 0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 10, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(webrtc::ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(webrtc::kRtpVp8Video, parsedPacket.type);
|
||||
EXPECT_EQ(ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 0 /*S*/, 8 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 1 /*T*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 1 /*T*/, 0 /*K*/);
|
||||
|
||||
EXPECT_EQ(2, parsedPacket.info.VP8.tID);
|
||||
|
||||
@ -177,29 +178,53 @@ TEST(ParseVP8Test, TID) {
|
||||
EXPECT_EQ(10 - 3, parsedPacket.info.VP8.dataLength);
|
||||
}
|
||||
|
||||
TEST(ParseVP8Test, KeyIdx) {
|
||||
WebRtc_UWord8 payload[10] = {0};
|
||||
payload[0] = 0x88;
|
||||
payload[1] = 0x10; // K = 1
|
||||
payload[2] = 0x11; // KEYIDX = 17 decimal
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 10, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 0 /*S*/, 8 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 0 /*T*/, 1 /*K*/);
|
||||
|
||||
EXPECT_EQ(17, parsedPacket.info.VP8.keyIdx);
|
||||
|
||||
EXPECT_EQ(payload + 3, parsedPacket.info.VP8.data);
|
||||
EXPECT_EQ(10 - 3, parsedPacket.info.VP8.dataLength);
|
||||
}
|
||||
|
||||
TEST(ParseVP8Test, MultipleExtensions) {
|
||||
WebRtc_UWord8 payload[10] = {0};
|
||||
payload[0] = 0x88;
|
||||
payload[1] = 0x80 | 0x40 | 0x20;
|
||||
payload[1] = 0x80 | 0x40 | 0x20 | 0x10;
|
||||
payload[2] = 0x80 | 17; // PictureID, high 7 bits
|
||||
payload[3] = 17; // PictureID, low 8 bits
|
||||
payload[4] = 42; // Tl0PicIdx
|
||||
payload[5] = 0x40; // TID
|
||||
payload[5] = 0x40 | 0x11; // TID + KEYIDX
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, payload, 10, 0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 10, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(webrtc::ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(webrtc::kRtpVp8Video, parsedPacket.type);
|
||||
EXPECT_EQ(ModuleRTPUtility::kPFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 0 /*S*/, 8 /*PartID*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 1 /*L*/, 1 /*T*/);
|
||||
VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 1 /*L*/, 1 /*T*/, 1 /*K*/);
|
||||
|
||||
EXPECT_EQ((17<<8) + 17, parsedPacket.info.VP8.pictureID);
|
||||
EXPECT_EQ(42, parsedPacket.info.VP8.tl0PicIdx);
|
||||
EXPECT_EQ(2, parsedPacket.info.VP8.tID);
|
||||
EXPECT_EQ(17, parsedPacket.info.VP8.keyIdx);
|
||||
|
||||
EXPECT_EQ(payload + 6, parsedPacket.info.VP8.data);
|
||||
EXPECT_EQ(10 - 6, parsedPacket.info.VP8.dataLength);
|
||||
@ -208,19 +233,16 @@ TEST(ParseVP8Test, MultipleExtensions) {
|
||||
TEST(ParseVP8Test, TooShortHeader) {
|
||||
WebRtc_UWord8 payload[4] = {0};
|
||||
payload[0] = 0x88;
|
||||
payload[1] = 0x80 | 0x40 | 0x20; // All extensions are enabled
|
||||
payload[1] = 0x80 | 0x40 | 0x20 | 0x10; // All extensions are enabled
|
||||
payload[2] = 0x80 | 17; //... but only 2 bytes PictureID is provided
|
||||
payload[3] = 17; // PictureID, low 8 bits
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, payload, 4, 0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, payload, 4, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
EXPECT_FALSE(rtpPayloadParser.Parse(parsedPacket));
|
||||
}
|
||||
|
||||
using webrtc::RtpFormatVp8;
|
||||
using webrtc::RTPVideoHeaderVP8;
|
||||
|
||||
TEST(ParseVP8Test, TestWithPacketizer) {
|
||||
WebRtc_UWord8 payload[10] = {0};
|
||||
WebRtc_UWord8 packet[20] = {0};
|
||||
@ -228,21 +250,21 @@ TEST(ParseVP8Test, TestWithPacketizer) {
|
||||
inputHeader.nonReference = true;
|
||||
inputHeader.pictureId = 300;
|
||||
inputHeader.temporalIdx = 1;
|
||||
inputHeader.tl0PicIdx = -1; // disable
|
||||
inputHeader.tl0PicIdx = kNoTl0PicIdx; // disable
|
||||
inputHeader.keyIdx = 31;
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload, 10, inputHeader);
|
||||
bool last;
|
||||
int send_bytes;
|
||||
ASSERT_EQ(0, packetizer.NextPacket(20, packet, &send_bytes, &last));
|
||||
ASSERT_TRUE(last);
|
||||
|
||||
RTPPayloadParser rtpPayloadParser(webrtc::kRtpVp8Video, packet, send_bytes,
|
||||
0);
|
||||
RTPPayloadParser rtpPayloadParser(kRtpVp8Video, packet, send_bytes, 0);
|
||||
|
||||
RTPPayload parsedPacket;
|
||||
ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
|
||||
|
||||
EXPECT_EQ(webrtc::ModuleRTPUtility::kIFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(webrtc::kRtpVp8Video, parsedPacket.type);
|
||||
EXPECT_EQ(ModuleRTPUtility::kIFrame, parsedPacket.frameType);
|
||||
EXPECT_EQ(kRtpVp8Video, parsedPacket.type);
|
||||
|
||||
VerifyBasicHeader(parsedPacket.info.VP8,
|
||||
inputHeader.nonReference /*N*/,
|
||||
@ -251,19 +273,15 @@ TEST(ParseVP8Test, TestWithPacketizer) {
|
||||
VerifyExtensions(parsedPacket.info.VP8,
|
||||
1 /*I*/,
|
||||
0 /*L*/,
|
||||
1 /*T*/);
|
||||
1 /*T*/,
|
||||
1 /*K*/);
|
||||
|
||||
EXPECT_EQ(inputHeader.pictureId, parsedPacket.info.VP8.pictureID);
|
||||
EXPECT_EQ(inputHeader.temporalIdx, parsedPacket.info.VP8.tID);
|
||||
EXPECT_EQ(inputHeader.keyIdx, parsedPacket.info.VP8.keyIdx);
|
||||
|
||||
EXPECT_EQ(packet + 5, parsedPacket.info.VP8.data);
|
||||
EXPECT_EQ(send_bytes - 5, parsedPacket.info.VP8.dataLength);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user