Adding operator== and != methods for CodecInst and VideoCodec structures.

R=juberti@google.com, mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/10099005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5746 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mallinath@webrtc.org 2014-03-21 00:41:28 +00:00
parent 9c2bd2b288
commit 0209e565de
4 changed files with 404 additions and 50 deletions

View File

@ -12,7 +12,7 @@
#define WEBRTC_COMMON_TYPES_H_
#include <stddef.h>
#include <string.h>
#include <vector>
#include "webrtc/typedefs.h"
@ -37,7 +37,7 @@
#define RTP_PAYLOAD_NAME_SIZE 32
#if defined(WEBRTC_WIN)
#if defined(WEBRTC_WIN) || defined(WIN32)
// Compares two strings without regard to case.
#define STR_CASE_CMP(s1, s2) ::_stricmp(s1, s2)
// Compares characters of two strings without regard to case.
@ -272,14 +272,26 @@ class FrameCountObserver {
// ==================================================================
// Each codec supported can be described by this structure.
struct CodecInst
{
int pltype;
char plname[RTP_PAYLOAD_NAME_SIZE];
int plfreq;
int pacsize;
int channels;
int rate; // bits/sec unlike {start,min,max}Bitrate elsewhere in this file!
struct CodecInst {
int pltype;
char plname[RTP_PAYLOAD_NAME_SIZE];
int plfreq;
int pacsize;
int channels;
int rate; // bits/sec unlike {start,min,max}Bitrate elsewhere in this file!
bool operator==(const CodecInst& other) const {
return pltype == other.pltype &&
(STR_CASE_CMP(plname, other.plname) == 0) &&
plfreq == other.plfreq &&
pacsize == other.pacsize &&
channels == other.channels &&
rate == other.rate;
}
bool operator!=(const CodecInst& other) const {
return !(*this == other);
}
};
// RTP
@ -541,18 +553,34 @@ enum VP8ResilienceMode {
};
// VP8 specific
struct VideoCodecVP8
{
bool pictureLossIndicationOn;
bool feedbackModeOn;
VideoCodecComplexity complexity;
VP8ResilienceMode resilience;
unsigned char numberOfTemporalLayers;
bool denoisingOn;
bool errorConcealmentOn;
bool automaticResizeOn;
bool frameDroppingOn;
int keyFrameInterval;
struct VideoCodecVP8 {
bool pictureLossIndicationOn;
bool feedbackModeOn;
VideoCodecComplexity complexity;
VP8ResilienceMode resilience;
unsigned char numberOfTemporalLayers;
bool denoisingOn;
bool errorConcealmentOn;
bool automaticResizeOn;
bool frameDroppingOn;
int keyFrameInterval;
bool operator==(const VideoCodecVP8& other) const {
return pictureLossIndicationOn == other.pictureLossIndicationOn &&
feedbackModeOn == other.feedbackModeOn &&
complexity == other.complexity &&
resilience == other.resilience &&
numberOfTemporalLayers == other.numberOfTemporalLayers &&
denoisingOn == other.denoisingOn &&
errorConcealmentOn == other.errorConcealmentOn &&
automaticResizeOn == other.automaticResizeOn &&
frameDroppingOn == other.frameDroppingOn &&
keyFrameInterval == other.keyFrameInterval;
}
bool operator!=(const VideoCodecVP8& other) const {
return !(*this == other);
}
};
// Video codec types
@ -574,15 +602,28 @@ union VideoCodecUnion
// Simulcast is when the same stream is encoded multiple times with different
// settings such as resolution.
struct SimulcastStream
{
unsigned short width;
unsigned short height;
unsigned char numberOfTemporalLayers;
unsigned int maxBitrate; // kilobits/sec.
unsigned int targetBitrate; // kilobits/sec.
unsigned int minBitrate; // kilobits/sec.
unsigned int qpMax; // minimum quality
struct SimulcastStream {
unsigned short width;
unsigned short height;
unsigned char numberOfTemporalLayers;
unsigned int maxBitrate; // kilobits/sec.
unsigned int targetBitrate; // kilobits/sec.
unsigned int minBitrate; // kilobits/sec.
unsigned int qpMax; // minimum quality
bool operator==(const SimulcastStream& other) const {
return width == other.width &&
height == other.height &&
numberOfTemporalLayers == other.numberOfTemporalLayers &&
maxBitrate == other.maxBitrate &&
targetBitrate == other.targetBitrate &&
minBitrate == other.minBitrate &&
qpMax == other.qpMax;
}
bool operator!=(const SimulcastStream& other) const {
return !(*this == other);
}
};
enum VideoCodecMode {
@ -591,31 +632,63 @@ enum VideoCodecMode {
};
// Common video codec properties
struct VideoCodec
{
VideoCodecType codecType;
char plName[kPayloadNameSize];
unsigned char plType;
struct VideoCodec {
VideoCodecType codecType;
char plName[kPayloadNameSize];
unsigned char plType;
unsigned short width;
unsigned short height;
unsigned short width;
unsigned short height;
unsigned int startBitrate; // kilobits/sec.
unsigned int maxBitrate; // kilobits/sec.
unsigned int minBitrate; // kilobits/sec.
unsigned char maxFramerate;
unsigned int startBitrate; // kilobits/sec.
unsigned int maxBitrate; // kilobits/sec.
unsigned int minBitrate; // kilobits/sec.
unsigned char maxFramerate;
VideoCodecUnion codecSpecific;
VideoCodecUnion codecSpecific;
unsigned int qpMax;
unsigned char numberOfSimulcastStreams;
SimulcastStream simulcastStream[kMaxSimulcastStreams];
unsigned int qpMax;
unsigned char numberOfSimulcastStreams;
SimulcastStream simulcastStream[kMaxSimulcastStreams];
VideoCodecMode mode;
VideoCodecMode mode;
// When using an external encoder/decoder this allows to pass
// extra options without requiring webrtc to be aware of them.
Config* extra_options;
// When using an external encoder/decoder this allows to pass
// extra options without requiring webrtc to be aware of them.
Config* extra_options;
};
// TODO(mallinath) - Remove this and push these two methods inside VideoCodec.
// This is done to handle operator== defined in fakewebrtcvideoengine.h
// This modification allows us to commit this CL directly and not with libjingle
// push.
struct VideoCodecDerived : public VideoCodec {
bool operator==(const VideoCodec& other) const {
bool ret = codecType == other.codecType &&
(STR_CASE_CMP(plName, other.plName) == 0) &&
plType == other.plType &&
width == other.width &&
height == other.height &&
startBitrate == other.startBitrate &&
maxBitrate == other.maxBitrate &&
minBitrate == other.minBitrate &&
maxFramerate == other.maxFramerate &&
qpMax == other.qpMax &&
numberOfSimulcastStreams == other.numberOfSimulcastStreams &&
mode == other.mode;
if (ret && codecType == kVideoCodecVP8) {
ret &= (codecSpecific.VP8 == other.codecSpecific.VP8);
}
for (unsigned char i = 0; i < other.numberOfSimulcastStreams && ret; ++i) {
ret &= (simulcastStream[i] == other.simulcastStream[i]);
}
return ret;
}
bool operator!=(const VideoCodec& other) const {
return !(*this == other);
}
};
// Bandwidth over-use detector options. These are used to drive

View File

@ -131,6 +131,7 @@
'encoder_state_feedback_unittest.cc',
'overuse_frame_detector_unittest.cc',
'stream_synchronization_unittest.cc',
'vie_codec_unittest.cc',
'vie_remb_unittest.cc',
],
'conditions': [

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2014 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 "testing/gtest/include/gtest/gtest.h"
#include "webrtc/common_types.h"
namespace webrtc {
// Builds VP8 codec with 0 simulcast streams.
void BuildVP8Codec(webrtc::VideoCodec* video_codec) {
video_codec->codecType = kVideoCodecVP8;
strncpy(video_codec->plName, "VP8", 4);
video_codec->plType = 100;
video_codec->width = 1280;
video_codec->height = 720;
video_codec->startBitrate = 1000; // kbps
video_codec->maxBitrate = 2000; // kbps
video_codec->minBitrate = 1000; // kbps
video_codec->maxFramerate = 30;
video_codec->qpMax = 50;
video_codec->numberOfSimulcastStreams = 0;
video_codec->mode = kRealtimeVideo;
// Set VP8 codec specific info.
video_codec->codecSpecific.VP8.pictureLossIndicationOn = true;
video_codec->codecSpecific.VP8.feedbackModeOn = true;
video_codec->codecSpecific.VP8.complexity = kComplexityNormal;
video_codec->codecSpecific.VP8.resilience = kResilienceOff;
video_codec->codecSpecific.VP8.numberOfTemporalLayers = 0;
video_codec->codecSpecific.VP8.denoisingOn = true;
video_codec->codecSpecific.VP8.errorConcealmentOn = true;
video_codec->codecSpecific.VP8.automaticResizeOn = true;
video_codec->codecSpecific.VP8.frameDroppingOn = true;
video_codec->codecSpecific.VP8.keyFrameInterval = 200;
}
void SetSimulcastSettings(webrtc::VideoCodec* video_codec) {
// Simulcast settings.
video_codec->numberOfSimulcastStreams = 1;
video_codec->simulcastStream[0].width = 320;
video_codec->simulcastStream[0].height = 180;
video_codec->simulcastStream[0].numberOfTemporalLayers = 0;
video_codec->simulcastStream[0].maxBitrate = 100;
video_codec->simulcastStream[0].targetBitrate = 100;
video_codec->simulcastStream[0].minBitrate = 0;
video_codec->simulcastStream[0].qpMax = video_codec->qpMax;
}
// This test compares two VideoCodecInst objects except codec specific and
// simulcast streams.
TEST(ViECodecTest, TestCompareCodecs) {
VideoCodecDerived codec1, codec2;
memset(&codec1, 0, sizeof(VideoCodec));
memset(&codec2, 0, sizeof(VideoCodec));
BuildVP8Codec(&codec1);
BuildVP8Codec(&codec2);
EXPECT_TRUE(codec1 == codec2);
EXPECT_FALSE(codec1 != codec2);
// plname is case insensitive.
strncpy(codec2.plName, "vp8", 4);
EXPECT_TRUE(codec1 == codec2);
codec2.codecType = kVideoCodecUnknown;
EXPECT_FALSE(codec1 == codec2);
// Modify pltype.
BuildVP8Codec(&codec2);
codec2.plType = 101;
EXPECT_FALSE(codec1 == codec2);
// Modifing height and width.
BuildVP8Codec(&codec2);
codec2.width = 640;
codec2.height = 480;
EXPECT_FALSE(codec1 == codec2);
// Modify framerate, default value is 30.
BuildVP8Codec(&codec2);
codec2.maxFramerate = 15;
EXPECT_FALSE(codec1 == codec2);
// Modifying startBitrate, default value is 1000 kbps.
BuildVP8Codec(&codec2);
codec2.startBitrate = 2000;
EXPECT_FALSE(codec1 == codec2);
// maxBitrate
BuildVP8Codec(&codec2);
codec2.startBitrate = 3000;
EXPECT_FALSE(codec1 == codec2);
// minBirate
BuildVP8Codec(&codec2);
codec2.startBitrate = 500;
EXPECT_FALSE(codec1 == codec2);
// Modify qpMax.
BuildVP8Codec(&codec2);
codec2.qpMax = 100;
EXPECT_FALSE(codec1 == codec2);
// Modify mode
BuildVP8Codec(&codec2);
codec2.mode = kScreensharing;
EXPECT_FALSE(codec1 == codec2);
}
// Test VP8 specific comparision.
TEST(ViECodecTest, TestCompareVP8CodecSpecific) {
VideoCodecDerived codec1, codec2;
memset(&codec1, 0, sizeof(VideoCodec));
memset(&codec2, 0, sizeof(VideoCodec));
BuildVP8Codec(&codec1);
BuildVP8Codec(&codec2);
EXPECT_TRUE(codec1 == codec2);
// pictureLossIndicationOn
codec2.codecSpecific.VP8.pictureLossIndicationOn = false;
EXPECT_FALSE(codec1 == codec2);
// feedbackModeOn
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.feedbackModeOn = false;
EXPECT_FALSE(codec1 == codec2);
// complexity
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.complexity = kComplexityHigh;
EXPECT_FALSE(codec1 == codec2);
// resilience
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.resilience = kResilientStream;
EXPECT_FALSE(codec1 == codec2);
// numberOfTemporalLayers
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.numberOfTemporalLayers = 2;
EXPECT_FALSE(codec1 == codec2);
// denoisingOn
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.denoisingOn = false;
EXPECT_FALSE(codec1 == codec2);
// errorConcealmentOn
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.errorConcealmentOn = false;
EXPECT_FALSE(codec1 == codec2);
// pictureLossIndicationOn
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.automaticResizeOn = false;
EXPECT_FALSE(codec1 == codec2);
// frameDroppingOn
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.frameDroppingOn = false;
EXPECT_FALSE(codec1 == codec2);
// keyFrameInterval
BuildVP8Codec(&codec2);
codec2.codecSpecific.VP8.keyFrameInterval = 100;
EXPECT_FALSE(codec1 == codec2);
}
// This test compares simulcast stream information in VideoCodec.
TEST(ViECodecTest, TestCompareSimulcastStreams) {
VideoCodecDerived codec1, codec2;
memset(&codec1, 0, sizeof(VideoCodec));
memset(&codec2, 0, sizeof(VideoCodec));
BuildVP8Codec(&codec1);
BuildVP8Codec(&codec2);
// Set simulacast settings.
SetSimulcastSettings(&codec1);
SetSimulcastSettings(&codec2);
EXPECT_TRUE(codec1 == codec2);
// Modify number of streams.
codec2.numberOfSimulcastStreams = 2;
EXPECT_FALSE(codec1 == codec2);
// Resetting steram count.
codec2.numberOfSimulcastStreams = 1;
// Modify height and width in codec2.
codec2.simulcastStream[0].width = 640;
codec2.simulcastStream[0].height = 480;
EXPECT_FALSE(codec1 == codec2);
// numberOfTemporalLayers
SetSimulcastSettings(&codec2);
codec2.simulcastStream[0].numberOfTemporalLayers = 2;
EXPECT_FALSE(codec1 == codec2);
// maxBitrate
SetSimulcastSettings(&codec2);
codec2.simulcastStream[0].maxBitrate = 1000;
EXPECT_FALSE(codec1 == codec2);
// targetBitrate
SetSimulcastSettings(&codec2);
codec2.simulcastStream[0].targetBitrate = 1000;
EXPECT_FALSE(codec1 == codec2);
// minBitrate
SetSimulcastSettings(&codec2);
codec2.simulcastStream[0].minBitrate = 50;
EXPECT_FALSE(codec1 == codec2);
// qpMax
SetSimulcastSettings(&codec2);
codec2.simulcastStream[0].qpMax = 100;
EXPECT_FALSE(codec1 == codec2);
}
} // namespace webrtc

View File

@ -169,6 +169,56 @@ TEST_F(VoECodecTest, DISABLED_ON_ANDROID(DualStreamRemoveSecondaryCodec)) {
EXPECT_EQ(-1, voe_codec_->GetSecondarySendCodec(channel_, my_codec));
}
TEST(VoECodecInst, TestCompareCodecInstances) {
CodecInst codec1, codec2;
memset(&codec1, 0, sizeof(CodecInst));
memset(&codec2, 0, sizeof(CodecInst));
codec1.pltype = 101;
strncpy(codec1.plname, "isac", 4);
codec1.plfreq = 8000;
codec1.pacsize = 110;
codec1.channels = 1;
codec1.rate = 8000;
memcpy(&codec2, &codec1, sizeof(CodecInst));
// Compare two codecs now.
EXPECT_TRUE(codec1 == codec2);
EXPECT_FALSE(codec1 != codec2);
// Changing pltype.
codec2.pltype = 102;
EXPECT_FALSE(codec1 == codec2);
EXPECT_TRUE(codec1 != codec2);
// Reset to codec2 to codec1 state.
memcpy(&codec2, &codec1, sizeof(CodecInst));
// payload name should be case insensitive.
strncpy(codec2.plname, "ISAC", 4);
EXPECT_TRUE(codec1 == codec2);
// Test modifying the |plfreq|
codec2.plfreq = 16000;
EXPECT_FALSE(codec1 == codec2);
// Reset to codec2 to codec1 state.
memcpy(&codec2, &codec1, sizeof(CodecInst));
// Test modifying the |pacsize|.
codec2.pacsize = 440;
EXPECT_FALSE(codec1 == codec2);
// Reset to codec2 to codec1 state.
memcpy(&codec2, &codec1, sizeof(CodecInst));
// Test modifying the |channels|.
codec2.channels = 2;
EXPECT_FALSE(codec1 == codec2);
// Reset to codec2 to codec1 state.
memcpy(&codec2, &codec1, sizeof(CodecInst));
// Test modifying the |rate|.
codec2.rate = 0;
EXPECT_FALSE(codec1 == codec2);
}
} // namespace
} // namespace voe
} // namespace webrtc