Implement VP8 packetizer and unit tests
Implemented a new VP8 packetizer with three modes. The packetizer class needs access to the fragmentation information, which is now created in the codec wrapper and passed through the callback chain to the RTPSenderVideo::SendVP8(). A unit test for the VP8 packetizer was also implemented. It tests the three different modes. The tests could definitely be more elaborate. Review URL: http://webrtc-codereview.appspot.com/34003 git-svn-id: http://webrtc.googlecode.com/svn/trunk@48 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
8dcd789d2b
commit
d2c7bff3a1
@ -8,10 +8,6 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the implementation of the VP8 packetizer class.
|
||||
*/
|
||||
|
||||
#include "rtp_format_vp8.h"
|
||||
|
||||
#include <cassert> // assert
|
||||
@ -19,18 +15,17 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RTPFormatVP8::RTPFormatVP8(const WebRtc_UWord8* payload_data,
|
||||
const WebRtc_UWord32 payload_size,
|
||||
RtpFormatVp8::RtpFormatVp8(const WebRtc_UWord8* payload_data,
|
||||
WebRtc_UWord32 payload_size,
|
||||
const RTPFragmentationHeader* fragmentation,
|
||||
const VP8PacketizerMode mode)
|
||||
:
|
||||
payload_data_(payload_data),
|
||||
payload_size_(payload_size),
|
||||
bytes_sent_(0),
|
||||
mode_(mode),
|
||||
beginning_(true),
|
||||
first_fragment_(true),
|
||||
vp8_header_bytes_(1)
|
||||
VP8PacketizerMode mode)
|
||||
: payload_data_(payload_data),
|
||||
payload_size_(payload_size),
|
||||
payload_bytes_sent_(0),
|
||||
mode_(mode),
|
||||
beginning_(true),
|
||||
first_fragment_(true),
|
||||
vp8_header_bytes_(1)
|
||||
{
|
||||
if (fragmentation == NULL)
|
||||
{
|
||||
@ -44,23 +39,38 @@ RTPFormatVP8::RTPFormatVP8(const WebRtc_UWord8* payload_data,
|
||||
}
|
||||
}
|
||||
|
||||
bool RTPFormatVP8::NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
int* bytes_to_send)
|
||||
{
|
||||
// Convenience variables
|
||||
const int num_fragments = frag_info_.fragmentationVectorSize;
|
||||
RtpFormatVp8::RtpFormatVp8(const WebRtc_UWord8* payload_data,
|
||||
WebRtc_UWord32 payload_size)
|
||||
: payload_data_(payload_data),
|
||||
payload_size_(payload_size),
|
||||
frag_info_(),
|
||||
payload_bytes_sent_(0),
|
||||
mode_(kSloppy),
|
||||
beginning_(true),
|
||||
first_fragment_(true),
|
||||
vp8_header_bytes_(1)
|
||||
{}
|
||||
|
||||
int RtpFormatVp8::GetFragIdx()
|
||||
{
|
||||
// Which fragment are we in?
|
||||
int frag_ix = 0;
|
||||
while ((frag_ix + 1 < num_fragments) &&
|
||||
(bytes_sent_ >= frag_info_.fragmentationOffset[frag_ix + 1]))
|
||||
while ((frag_ix + 1 < frag_info_.fragmentationVectorSize) &&
|
||||
(payload_bytes_sent_ >= frag_info_.fragmentationOffset[frag_ix + 1]))
|
||||
{
|
||||
++frag_ix;
|
||||
}
|
||||
return frag_ix;
|
||||
}
|
||||
|
||||
// How much data to send in this packet?
|
||||
int send_bytes = 0;
|
||||
bool last_fragment = false;
|
||||
int RtpFormatVp8::NextPacket(int max_payload_len, WebRtc_UWord8* buffer,
|
||||
int* bytes_to_send, bool* last_packet)
|
||||
{
|
||||
// Convenience variables
|
||||
const int num_fragments = frag_info_.fragmentationVectorSize;
|
||||
int frag_ix = GetFragIdx(); //TODO (hlundin): Store frag_ix as a member?
|
||||
int send_bytes = 0; // How much data to send in this packet.
|
||||
bool end_of_fragment = false;
|
||||
|
||||
switch (mode_)
|
||||
{
|
||||
@ -75,16 +85,17 @@ bool RTPFormatVP8::NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
{
|
||||
// Pack as many whole partitions we can into this packet;
|
||||
// don't fragment.
|
||||
while (send_bytes + vp8_header_bytes_
|
||||
while ((frag_ix < num_fragments) &&
|
||||
(send_bytes + vp8_header_bytes_
|
||||
+ frag_info_.fragmentationLength[frag_ix]
|
||||
<= max_payload_len)
|
||||
<= max_payload_len))
|
||||
{
|
||||
send_bytes += frag_info_.fragmentationLength[frag_ix];
|
||||
++frag_ix;
|
||||
}
|
||||
|
||||
// This packet ends on a complete fragment.
|
||||
last_fragment = true;
|
||||
end_of_fragment = true;
|
||||
break; // Jump out of case statement.
|
||||
}
|
||||
}
|
||||
@ -99,7 +110,7 @@ bool RTPFormatVP8::NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
{
|
||||
// Find out how much is left to send in the current partition.
|
||||
const int remaining_bytes = frag_info_.fragmentationOffset[frag_ix]
|
||||
- bytes_sent_ + frag_info_.fragmentationLength[frag_ix];
|
||||
- payload_bytes_sent_ + frag_info_.fragmentationLength[frag_ix];
|
||||
assert(remaining_bytes > 0);
|
||||
assert(remaining_bytes <= frag_info_.fragmentationLength[frag_ix]);
|
||||
|
||||
@ -112,7 +123,7 @@ bool RTPFormatVP8::NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
{
|
||||
// last packet from this partition
|
||||
send_bytes = remaining_bytes;
|
||||
last_fragment = true;
|
||||
end_of_fragment = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -120,17 +131,17 @@ bool RTPFormatVP8::NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
case kSloppy:
|
||||
{
|
||||
// Send a full packet, or what is left of the payload.
|
||||
const int remaining_bytes = payload_size_ - bytes_sent_;
|
||||
const int remaining_bytes = payload_size_ - payload_bytes_sent_;
|
||||
|
||||
if (remaining_bytes + vp8_header_bytes_ > max_payload_len)
|
||||
{
|
||||
send_bytes = max_payload_len - vp8_header_bytes_;
|
||||
last_fragment = false;
|
||||
end_of_fragment = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_bytes = remaining_bytes;
|
||||
last_fragment = true;
|
||||
end_of_fragment = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -138,20 +149,23 @@ bool RTPFormatVP8::NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
default:
|
||||
// Should not end up here
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Write the payload header and the payload to buffer.
|
||||
*bytes_to_send = WriteHeaderAndPayload(send_bytes, last_fragment, buffer);
|
||||
*bytes_to_send = WriteHeaderAndPayload(send_bytes, end_of_fragment, buffer);
|
||||
if (*bytes_to_send < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Anything left to send?
|
||||
if (bytes_sent_ < payload_size_)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
*last_packet = payload_bytes_sent_ >= payload_size_;
|
||||
assert(!*last_packet || (payload_bytes_sent_ == payload_size_));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RTPFormatVP8::WriteHeaderAndPayload(const int send_bytes,
|
||||
const bool last_fragment,
|
||||
int RtpFormatVp8::WriteHeaderAndPayload(int send_bytes,
|
||||
bool end_of_fragment,
|
||||
WebRtc_UWord8* buffer)
|
||||
{
|
||||
// Write the VP8 payload header.
|
||||
@ -160,25 +174,34 @@ int RTPFormatVP8::WriteHeaderAndPayload(const int send_bytes,
|
||||
// | RSV |I|N|FI |B|
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
|
||||
if (send_bytes < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (payload_bytes_sent_ + send_bytes > payload_size_)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// PictureID always present in first packet
|
||||
const int pictureid_present = beginning_;
|
||||
const int picture_id_present = beginning_;
|
||||
// TODO(hlundin): must pipe this info from VP8 encoder
|
||||
const int nonref_frame = 0;
|
||||
const int kNonrefFrame = 0;
|
||||
|
||||
buffer[0] = 0 | (pictureid_present << 4) // I
|
||||
| (nonref_frame << 3) // N
|
||||
| (!first_fragment_ << 2) | (!last_fragment << 1) // FI
|
||||
| (beginning_);
|
||||
buffer[0] = 0;
|
||||
if (picture_id_present) buffer[0] |= (0x01 << 4); // I
|
||||
if (kNonrefFrame) buffer[0] |= (0x01 << 3); // N
|
||||
if (!first_fragment_) buffer[0] |= (0x01 << 2); // FI
|
||||
if (!end_of_fragment) buffer[0] |= (0x01 << 1); // FI
|
||||
if (beginning_) buffer[0] |= 0x01; // B
|
||||
|
||||
// Copy the payload.
|
||||
assert(bytes_sent_ + send_bytes <= payload_size_);
|
||||
memcpy(&buffer[vp8_header_bytes_], &payload_data_[bytes_sent_], send_bytes);
|
||||
memcpy(&buffer[vp8_header_bytes_], &payload_data_[payload_bytes_sent_],
|
||||
send_bytes);
|
||||
|
||||
// Update state variables.
|
||||
beginning_ = false; // next packet cannot be first packet in frame
|
||||
// next packet starts new fragment if this ended one
|
||||
first_fragment_ = last_fragment;
|
||||
bytes_sent_ += send_bytes;
|
||||
first_fragment_ = end_of_fragment;
|
||||
payload_bytes_sent_ += send_bytes;
|
||||
|
||||
// Return total length of written data.
|
||||
return send_bytes + vp8_header_bytes_;
|
||||
|
@ -10,78 +10,16 @@
|
||||
|
||||
/*
|
||||
* This file contains the declaration of the VP8 packetizer class.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_RTP_FORMAT_VP8_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_RTP_FORMAT_VP8_H_
|
||||
|
||||
#include "module_common_types.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
|
||||
// VP8 packetization modes.
|
||||
enum VP8PacketizerMode
|
||||
{
|
||||
kStrict = 0, // split partitions if too large; never aggregate partitions
|
||||
kAggregate, // split partitions if too large; aggregate partitions/fragments
|
||||
kSloppy, // split entire payload without considering partition boundaries
|
||||
};
|
||||
|
||||
// Packetizer for VP8.
|
||||
class RTPFormatVP8
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
// Initialize with payload from encoder and fragmentation info.
|
||||
// If fragmentation info is NULL, mode will be forced to kSloppy.
|
||||
RTPFormatVP8(const WebRtc_UWord8* payload_data,
|
||||
const WebRtc_UWord32 payload_size,
|
||||
const RTPFragmentationHeader* fragmentation,
|
||||
const VP8PacketizerMode mode = kStrict);
|
||||
|
||||
// Get the next payload with VP8 payload header.
|
||||
// max_payload_len limits the sum length of payload and VP8 payload header.
|
||||
// buffer is a pointer to where the output will be written.
|
||||
// bytes_to_send is an output variable that will contain number of bytes
|
||||
// written to buffer.
|
||||
bool NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
int* bytes_to_send);
|
||||
|
||||
private:
|
||||
// Write the payload header and copy the payload to the buffer.
|
||||
// Will copy send_bytes bytes from the current position on the payload data.
|
||||
// last_fragment indicates that this packet ends with the last byte of a
|
||||
// partition.
|
||||
int WriteHeaderAndPayload(const int send_bytes, const bool last_fragment,
|
||||
WebRtc_UWord8* buffer);
|
||||
|
||||
const WebRtc_UWord8* payload_data_;
|
||||
const WebRtc_UWord32 payload_size_;
|
||||
RTPFragmentationHeader frag_info_;
|
||||
int bytes_sent_;
|
||||
VP8PacketizerMode mode_;
|
||||
bool beginning_; // first partition in this frame
|
||||
bool first_fragment_; // first fragment of a partition
|
||||
const int vp8_header_bytes_; // length of VP8 payload header
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* WEBRTC_MODULES_RTP_RTCP_RTP_FORMAT_VP8_H_ */
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
* A packetizer object is created for each encoded video frame. The
|
||||
* constructor is called with the payload data and size,
|
||||
* together with the fragmentation information and a packetizer mode
|
||||
* of choice. Alternatively, if no fragmentation info is available, the
|
||||
* second constructor can be used with only payload data and size; in that
|
||||
* case the mode kSloppy is used.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the declaration of the VP8 packetizer class.
|
||||
* After creating the packetizer, the method NextPacket is called
|
||||
* repeatedly to get all packets for the frame. The method returns
|
||||
* false as long as there are more packets left to fetch.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_RTP_FORMAT_VP8_H_
|
||||
@ -93,46 +31,54 @@ private:
|
||||
namespace webrtc
|
||||
{
|
||||
|
||||
// VP8 packetization modes.
|
||||
enum VP8PacketizerMode
|
||||
{
|
||||
kStrict = 0, // split partitions if too large; never aggregate partitions
|
||||
kAggregate, // split partitions if too large; aggregate partitions/fragments
|
||||
kAggregate, // split partitions if too large; aggregate whole partitions
|
||||
kSloppy, // split entire payload without considering partition boundaries
|
||||
};
|
||||
|
||||
// Packetizer for VP8.
|
||||
class RTPFormatVP8
|
||||
class RtpFormatVp8
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
// Initialize with payload from encoder and fragmentation info.
|
||||
// If fragmentation info is NULL, mode will be forced to kSloppy.
|
||||
RTPFormatVP8(const WebRtc_UWord8* payload_data,
|
||||
const WebRtc_UWord32 payload_size,
|
||||
// The payload_data must be exactly one encoded VP8 frame.
|
||||
RtpFormatVp8(const WebRtc_UWord8* payload_data,
|
||||
WebRtc_UWord32 payload_size,
|
||||
const RTPFragmentationHeader* fragmentation,
|
||||
const VP8PacketizerMode mode = kStrict);
|
||||
VP8PacketizerMode mode);
|
||||
|
||||
// Initialize without fragmentation info. Mode kSloppy will be used.
|
||||
// The payload_data must be exactly one encoded VP8 frame.
|
||||
RtpFormatVp8(const WebRtc_UWord8* payload_data,
|
||||
WebRtc_UWord32 payload_size);
|
||||
|
||||
// Get the next payload with VP8 payload header.
|
||||
// max_payload_len limits the sum length of payload and VP8 payload header.
|
||||
// buffer is a pointer to where the output will be written.
|
||||
// bytes_to_send is an output variable that will contain number of bytes
|
||||
// written to buffer.
|
||||
bool NextPacket(const int max_payload_len, WebRtc_UWord8* buffer,
|
||||
int* bytes_to_send);
|
||||
// Returns true for the last packet of the frame, false otherwise (i.e.,
|
||||
// call the function again to get the next packet).
|
||||
int NextPacket(int max_payload_len, WebRtc_UWord8* buffer,
|
||||
int* bytes_to_send, bool* last_packet);
|
||||
|
||||
private:
|
||||
// Determine from which fragment the next byte to send will be taken.
|
||||
int GetFragIdx();
|
||||
|
||||
// Write the payload header and copy the payload to the buffer.
|
||||
// Will copy send_bytes bytes from the current position on the payload data.
|
||||
// last_fragment indicates that this packet ends with the last byte of a
|
||||
// partition.
|
||||
int WriteHeaderAndPayload(const int send_bytes, const bool last_fragment,
|
||||
int WriteHeaderAndPayload(int send_bytes, bool end_of_fragment,
|
||||
WebRtc_UWord8* buffer);
|
||||
|
||||
const WebRtc_UWord8* payload_data_;
|
||||
const WebRtc_UWord32 payload_size_;
|
||||
RTPFragmentationHeader frag_info_;
|
||||
int bytes_sent_;
|
||||
int payload_bytes_sent_;
|
||||
VP8PacketizerMode mode_;
|
||||
bool beginning_; // first partition in this frame
|
||||
bool first_fragment_; // first fragment of a partition
|
||||
|
@ -1106,14 +1106,17 @@ RTPSenderVideo::SendVP8(const FrameType frameType,
|
||||
WebRtc_UWord16 maxPayloadLengthVP8 = _rtpSender.MaxPayloadLength()
|
||||
- FECPacketOverhead() - rtpHeaderLength;
|
||||
|
||||
RTPFormatVP8 packetizer(data, payloadBytesToSend, fragmentation, kStrict);
|
||||
RtpFormatVp8 packetizer(data, payloadBytesToSend, fragmentation, kStrict);
|
||||
|
||||
bool last = false;
|
||||
while (!last)
|
||||
{
|
||||
// Write VP8 Payload Descriptor and VP8 payload.
|
||||
last = packetizer.NextPacket(maxPayloadLengthVP8,
|
||||
&dataBuffer[rtpHeaderLength], &payloadBytesInPacket);
|
||||
if (packetizer.NextPacket(maxPayloadLengthVP8,
|
||||
&dataBuffer[rtpHeaderLength], &payloadBytesInPacket, &last) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Write RTP header.
|
||||
// Set marker bit true if this is the last packet in frame.
|
||||
|
@ -18,65 +18,13 @@
|
||||
'../../source/rtp_rtcp.gyp:rtp_rtcp',
|
||||
'../../../../../testing/gtest.gyp:gtest',
|
||||
'../../../../../testing/gtest.gyp:gtest_main',
|
||||
# '../../../signal_processing_library/main/source/spl.gyp:spl',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../source',
|
||||
],
|
||||
# 'direct_dependent_settings': {
|
||||
# 'include_dirs': [
|
||||
# '../interface',
|
||||
# ],
|
||||
# },
|
||||
'sources': [
|
||||
'unit_test.h',
|
||||
'unit_test.cc',
|
||||
'../../source/rtp_format_vp8.h',
|
||||
'../../source/rtp_format_vp8.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:2
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=2 shiftwidth=2:
|
||||
# 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.
|
||||
|
||||
{
|
||||
'includes': [
|
||||
'../../../../common_settings.gypi', # Common settings
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'test_rtp_format_vp8',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'../../source/rtp_rtcp.gyp:rtp_rtcp',
|
||||
'../../../../../testing/gtest.gyp:gtest',
|
||||
'../../../../../testing/gtest.gyp:gtest_main',
|
||||
# '../../../signal_processing_library/main/source/spl.gyp:spl',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../source',
|
||||
],
|
||||
# 'direct_dependent_settings': {
|
||||
# 'include_dirs': [
|
||||
# '../interface',
|
||||
# ],
|
||||
# },
|
||||
'sources': [
|
||||
'unit_test.h',
|
||||
'unit_test.cc',
|
||||
'../../source/rtp_format_vp8.h',
|
||||
'../../source/rtp_format_vp8.cc',
|
||||
],
|
||||
},
|
||||
|
@ -13,19 +13,30 @@
|
||||
* This file includes unit tests for the VP8 packetizer.
|
||||
*/
|
||||
|
||||
#include "unit_test.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "rtp_format_vp8.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
RTPFormatVP8Test::RTPFormatVP8Test()
|
||||
{
|
||||
}
|
||||
using webrtc::RTPFragmentationHeader;
|
||||
using webrtc::RtpFormatVp8;
|
||||
|
||||
void RTPFormatVP8Test::SetUp() {
|
||||
payload_data = new WebRtc_UWord8[30];
|
||||
payload_size = 30;
|
||||
for (int i = 0; i < payload_size; i++)
|
||||
const WebRtc_UWord32 kPayloadSize = 30;
|
||||
|
||||
class RtpFormatVp8Test : public ::testing::Test {
|
||||
protected:
|
||||
RtpFormatVp8Test() {};
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
WebRtc_UWord8* payload_data;
|
||||
RTPFragmentationHeader* fragmentation;
|
||||
};
|
||||
|
||||
void RtpFormatVp8Test::SetUp() {
|
||||
payload_data = new WebRtc_UWord8[kPayloadSize];
|
||||
for (int i = 0; i < kPayloadSize; i++)
|
||||
{
|
||||
payload_data[i] = i / 10; // integer division
|
||||
}
|
||||
@ -39,7 +50,7 @@ void RTPFormatVP8Test::SetUp() {
|
||||
fragmentation->fragmentationOffset[2] = 20;
|
||||
}
|
||||
|
||||
void RTPFormatVP8Test::TearDown() {
|
||||
void RtpFormatVp8Test::TearDown() {
|
||||
delete [] payload_data;
|
||||
delete fragmentation;
|
||||
}
|
||||
@ -57,15 +68,18 @@ void RTPFormatVP8Test::TearDown() {
|
||||
|
||||
#define EXPECT_BIT_B_EQ(x,a) EXPECT_EQ((((x)&0x01) > 0), (a > 0))
|
||||
|
||||
TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
TEST_F(RtpFormatVp8Test, TestStrictMode)
|
||||
{
|
||||
WebRtc_UWord8 buffer[20];
|
||||
int send_bytes = 0;
|
||||
bool last;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, fragmentation, kStrict);
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data, kPayloadSize,
|
||||
fragmentation, webrtc::kStrict);
|
||||
|
||||
// get first packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(8, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(8, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,8);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
@ -78,7 +92,8 @@ TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
}
|
||||
|
||||
// get second packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(8, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(8, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,4); // 3 remaining from partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -92,7 +107,8 @@ TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
|
||||
// Second partition
|
||||
// Get first (and only) packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(20, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(20, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,11);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -106,7 +122,8 @@ TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
|
||||
// Third partition
|
||||
// Get first packet (of three)
|
||||
EXPECT_FALSE(packetizer.NextPacket(5, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(5, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,5);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -119,7 +136,8 @@ TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
}
|
||||
|
||||
// Get second packet (of three)
|
||||
EXPECT_FALSE(packetizer.NextPacket(5, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(5, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,5);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -132,7 +150,8 @@ TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
}
|
||||
|
||||
// Get third and last packet
|
||||
EXPECT_TRUE(packetizer.NextPacket(5, buffer, &send_bytes)); // last packet in frame
|
||||
EXPECT_EQ(0, packetizer.NextPacket(5, buffer, &send_bytes, &last));
|
||||
EXPECT_TRUE(last); // last packet in frame
|
||||
EXPECT_EQ(send_bytes,3); // 2 bytes payload left, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -146,72 +165,78 @@ TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
|
||||
}
|
||||
|
||||
TEST_F(RTPFormatVP8Test, TestAggregateMode)
|
||||
TEST_F(RtpFormatVp8Test, TestAggregateMode)
|
||||
{
|
||||
WebRtc_UWord8 buffer[30];
|
||||
WebRtc_UWord8 buffer[kPayloadSize];
|
||||
int send_bytes = 0;
|
||||
bool last;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, fragmentation,
|
||||
kAggregate);
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data, kPayloadSize,
|
||||
fragmentation, webrtc::kAggregate);
|
||||
|
||||
// get first packet
|
||||
// first two partitions aggregated
|
||||
EXPECT_FALSE(packetizer.NextPacket(25, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,21); // Two 10-byte partitions and 1 byte header
|
||||
// first half of first partition
|
||||
EXPECT_EQ(0, packetizer.NextPacket(6, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,6); // First 5 from first partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x00);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 1);
|
||||
for (int i = 1; i < 11; i++)
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
for (int i = 11; i < 21; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
|
||||
// get second packet
|
||||
// first half of last partition
|
||||
EXPECT_FALSE(packetizer.NextPacket(6, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,6); // First 5 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
// get third packet
|
||||
// second half of last partition
|
||||
EXPECT_TRUE(packetizer.NextPacket(6, buffer, &send_bytes)); // last packet
|
||||
EXPECT_EQ(send_bytes,6); // Last 5 from last partition, 1 header
|
||||
// second half of first partition
|
||||
EXPECT_EQ(0, packetizer.NextPacket(10, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,6); // Last 5 from first partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x02);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
|
||||
// get third packet
|
||||
// last two partitions aggregated
|
||||
EXPECT_EQ(0, packetizer.NextPacket(25, buffer, &send_bytes, &last));
|
||||
EXPECT_TRUE(last); // last packet
|
||||
EXPECT_EQ(send_bytes,21); // Two 10-byte partitions and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x00);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 11; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
for (int i = 11; i < 21; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_F(RTPFormatVP8Test, TestSloppyMode)
|
||||
TEST_F(RtpFormatVp8Test, TestSloppyMode)
|
||||
{
|
||||
WebRtc_UWord8 buffer[30];
|
||||
WebRtc_UWord8 buffer[kPayloadSize];
|
||||
int send_bytes = 0;
|
||||
bool last;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, fragmentation,
|
||||
kSloppy);
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data, kPayloadSize,
|
||||
fragmentation, webrtc::kSloppy);
|
||||
|
||||
// get first packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
@ -225,7 +250,8 @@ TEST_F(RTPFormatVP8Test, TestSloppyMode)
|
||||
|
||||
// get second packet
|
||||
// fragments of first and second partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (2+6) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -243,7 +269,8 @@ TEST_F(RTPFormatVP8Test, TestSloppyMode)
|
||||
|
||||
// get third packet
|
||||
// fragments of second and third partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (4+4) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -261,7 +288,8 @@ TEST_F(RTPFormatVP8Test, TestSloppyMode)
|
||||
|
||||
// get fourth packet
|
||||
// second half of last partition
|
||||
EXPECT_TRUE(packetizer.NextPacket(9, buffer, &send_bytes)); // last packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_TRUE(last); // last packet
|
||||
EXPECT_EQ(send_bytes,7); // Last 6 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -276,16 +304,18 @@ TEST_F(RTPFormatVP8Test, TestSloppyMode)
|
||||
}
|
||||
|
||||
// Verify that sloppy mode is forced if fragmentation info is missing.
|
||||
TEST_F(RTPFormatVP8Test, TestSloppyModeFallback)
|
||||
TEST_F(RtpFormatVp8Test, TestSloppyModeFallback)
|
||||
{
|
||||
WebRtc_UWord8 buffer[30];
|
||||
WebRtc_UWord8 buffer[kPayloadSize];
|
||||
int send_bytes = 0;
|
||||
bool last;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, NULL /*fragmentation*/,
|
||||
kStrict); // should be changed to kSlopy
|
||||
RtpFormatVp8 packetizer = RtpFormatVp8(payload_data, kPayloadSize,
|
||||
NULL /*fragInfo*/, webrtc::kStrict); // should be changed to kSloppy
|
||||
|
||||
// get first packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
@ -299,7 +329,8 @@ TEST_F(RTPFormatVP8Test, TestSloppyModeFallback)
|
||||
|
||||
// get second packet
|
||||
// fragments of first and second partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (2+6) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -317,7 +348,8 @@ TEST_F(RTPFormatVP8Test, TestSloppyModeFallback)
|
||||
|
||||
// get third packet
|
||||
// fragments of second and third partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_FALSE(last);
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (4+4) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -335,7 +367,8 @@ TEST_F(RTPFormatVP8Test, TestSloppyModeFallback)
|
||||
|
||||
// get fourth packet
|
||||
// second half of last partition
|
||||
EXPECT_TRUE(packetizer.NextPacket(9, buffer, &send_bytes)); // last packet
|
||||
EXPECT_EQ(0, packetizer.NextPacket(9, buffer, &send_bytes, &last));
|
||||
EXPECT_TRUE(last); // last packet
|
||||
EXPECT_EQ(send_bytes,7); // Last 6 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
@ -355,362 +388,4 @@ int main(int argc, char** argv) {
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file includes unit tests for the VP8 packetizer.
|
||||
*/
|
||||
|
||||
#include "unit_test.h"
|
||||
#include "rtp_format_vp8.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RTPFormatVP8Test::RTPFormatVP8Test()
|
||||
{
|
||||
}
|
||||
|
||||
void RTPFormatVP8Test::SetUp() {
|
||||
payload_data = new WebRtc_UWord8[30];
|
||||
payload_size = 30;
|
||||
for (int i = 0; i < payload_size; i++)
|
||||
{
|
||||
payload_data[i] = i / 10; // integer division
|
||||
}
|
||||
fragmentation = new RTPFragmentationHeader;
|
||||
fragmentation->VerifyAndAllocateFragmentationHeader(3);
|
||||
fragmentation->fragmentationLength[0] = 10;
|
||||
fragmentation->fragmentationLength[1] = 10;
|
||||
fragmentation->fragmentationLength[2] = 10;
|
||||
fragmentation->fragmentationOffset[0] = 0;
|
||||
fragmentation->fragmentationOffset[1] = 10;
|
||||
fragmentation->fragmentationOffset[2] = 20;
|
||||
}
|
||||
|
||||
void RTPFormatVP8Test::TearDown() {
|
||||
delete [] payload_data;
|
||||
delete fragmentation;
|
||||
}
|
||||
|
||||
#define EXPECT_BIT_EQ(x,n,a) EXPECT_EQ((((x)>>n)&0x1), a)
|
||||
|
||||
#define EXPECT_RSV_ZERO(x) EXPECT_EQ(((x)&0xE0), 0)
|
||||
|
||||
//#define EXPECT_BIT_I_EQ(x,a) EXPECT_EQ((((x)&0x10) > 0), (a > 0))
|
||||
#define EXPECT_BIT_I_EQ(x,a) EXPECT_BIT_EQ(x, 4, a)
|
||||
|
||||
#define EXPECT_BIT_N_EQ(x,a) EXPECT_EQ((((x)&0x08) > 0), (a > 0))
|
||||
|
||||
#define EXPECT_FI_EQ(x,a) EXPECT_EQ((((x)&0x06) >> 1), a)
|
||||
|
||||
#define EXPECT_BIT_B_EQ(x,a) EXPECT_EQ((((x)&0x01) > 0), (a > 0))
|
||||
|
||||
TEST_F(RTPFormatVP8Test, TestStrictMode)
|
||||
{
|
||||
WebRtc_UWord8 buffer[20];
|
||||
int send_bytes = 0;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, fragmentation, kStrict);
|
||||
|
||||
// get first packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(8, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,8);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 1);
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
|
||||
// get second packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(8, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,4); // 3 remaining from partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x02);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
|
||||
// Second partition
|
||||
// Get first (and only) packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(20, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,11);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x00);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 11; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
|
||||
// Third partition
|
||||
// Get first packet (of three)
|
||||
EXPECT_FALSE(packetizer.NextPacket(5, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,5);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01); // first fragment
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 5; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
// Get second packet (of three)
|
||||
EXPECT_FALSE(packetizer.NextPacket(5, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,5);
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x03); // middle fragment
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 5; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
// Get third and last packet
|
||||
EXPECT_TRUE(packetizer.NextPacket(5, buffer, &send_bytes)); // last packet in frame
|
||||
EXPECT_EQ(send_bytes,3); // 2 bytes payload left, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x02); // last fragment
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_F(RTPFormatVP8Test, TestAggregateMode)
|
||||
{
|
||||
WebRtc_UWord8 buffer[30];
|
||||
int send_bytes = 0;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, fragmentation,
|
||||
kAggregate);
|
||||
|
||||
// get first packet
|
||||
// first two partitions aggregated
|
||||
EXPECT_FALSE(packetizer.NextPacket(25, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,21); // Two 10-byte partitions and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x00);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 1);
|
||||
for (int i = 1; i < 11; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
for (int i = 11; i < 21; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
|
||||
// get second packet
|
||||
// first half of last partition
|
||||
EXPECT_FALSE(packetizer.NextPacket(6, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,6); // First 5 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
// get third packet
|
||||
// second half of last partition
|
||||
EXPECT_TRUE(packetizer.NextPacket(6, buffer, &send_bytes)); // last packet
|
||||
EXPECT_EQ(send_bytes,6); // Last 5 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x02);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_F(RTPFormatVP8Test, TestSloppyMode)
|
||||
{
|
||||
WebRtc_UWord8 buffer[30];
|
||||
int send_bytes = 0;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, fragmentation,
|
||||
kSloppy);
|
||||
|
||||
// get first packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 1);
|
||||
for (int i = 1; i < 9; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
|
||||
// get second packet
|
||||
// fragments of first and second partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (2+6) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x03);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
for (int i = 3; i < 9; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
|
||||
// get third packet
|
||||
// fragments of second and third partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (4+4) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x03);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i <= 4; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
for (int i = 5; i < 9; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
// get fourth packet
|
||||
// second half of last partition
|
||||
EXPECT_TRUE(packetizer.NextPacket(9, buffer, &send_bytes)); // last packet
|
||||
EXPECT_EQ(send_bytes,7); // Last 6 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x02);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 5; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Verify that sloppy mode is forced if fragmentation info is missing.
|
||||
TEST_F(RTPFormatVP8Test, TestSloppyModeFallback)
|
||||
{
|
||||
WebRtc_UWord8 buffer[30];
|
||||
int send_bytes = 0;
|
||||
|
||||
RTPFormatVP8 packetizer = RTPFormatVP8(payload_data, payload_size, NULL /*fragmentation*/,
|
||||
kStrict); // should be changed to kSlopy
|
||||
|
||||
// get first packet
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 1);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x01);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 1);
|
||||
for (int i = 1; i < 9; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
|
||||
// get second packet
|
||||
// fragments of first and second partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (2+6) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x03);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 0);
|
||||
}
|
||||
for (int i = 3; i < 9; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
|
||||
// get third packet
|
||||
// fragments of second and third partitions
|
||||
EXPECT_FALSE(packetizer.NextPacket(9, buffer, &send_bytes));
|
||||
EXPECT_EQ(send_bytes,9); // 8 bytes (4+4) payload and 1 byte header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x03);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i <= 4; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 1);
|
||||
}
|
||||
for (int i = 5; i < 9; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
// get fourth packet
|
||||
// second half of last partition
|
||||
EXPECT_TRUE(packetizer.NextPacket(9, buffer, &send_bytes)); // last packet
|
||||
EXPECT_EQ(send_bytes,7); // Last 6 from last partition, 1 header
|
||||
EXPECT_RSV_ZERO(buffer[0]);
|
||||
EXPECT_BIT_I_EQ(buffer[0], 0);
|
||||
EXPECT_BIT_N_EQ(buffer[0], 0);
|
||||
EXPECT_FI_EQ(buffer[0], 0x02);
|
||||
EXPECT_BIT_B_EQ(buffer[0], 0);
|
||||
for (int i = 1; i < 5; i++)
|
||||
{
|
||||
EXPECT_EQ(buffer[i], 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
@ -1,78 +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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This header file includes declaration for unit tests for the VP8 packetizer.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_RTP_FORMAT_VP8_UNIT_TEST_H_
|
||||
#define WEBRTC_RTP_FORMAT_VP8_UNIT_TEST_H_
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RTPFragmentationHeader;
|
||||
|
||||
class RTPFormatVP8Test : public ::testing::Test {
|
||||
protected:
|
||||
RTPFormatVP8Test();
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
WebRtc_UWord8* payload_data;
|
||||
WebRtc_UWord32 payload_size;
|
||||
RTPFragmentationHeader* fragmentation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // WEBRTC_RTP_FORMAT_VP8_UNIT_TEST_H_
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This header file includes declaration for unit tests for the VP8 packetizer.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_RTP_FORMAT_VP8_UNIT_TEST_H_
|
||||
#define WEBRTC_RTP_FORMAT_VP8_UNIT_TEST_H_
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RTPFragmentationHeader;
|
||||
|
||||
class RTPFormatVP8Test : public ::testing::Test {
|
||||
protected:
|
||||
RTPFormatVP8Test();
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
WebRtc_UWord8* payload_data;
|
||||
WebRtc_UWord32 payload_size;
|
||||
RTPFragmentationHeader* fragmentation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // WEBRTC_RTP_FORMAT_VP8_UNIT_TEST_H_
|
Loading…
Reference in New Issue
Block a user