From 174d01d9812694d201f6f3939fc7b8bf4650cfa2 Mon Sep 17 00:00:00 2001
From: dknn <yoann.blein@free.fr>
Date: Sun, 3 Jun 2012 00:41:35 +0200
Subject: Major part of a RTP description element


diff --git a/Swiften/Elements/JingleRTPDescription.h b/Swiften/Elements/JingleRTPDescription.h
new file mode 100644
index 0000000..5337aa8
--- /dev/null
+++ b/Swiften/Elements/JingleRTPDescription.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+#include <Swiften/Elements/JingleDescription.h>
+#include <Swiften/Elements/RTPPayloadType.h>
+
+namespace Swift {
+	class JingleRTPDescription : public JingleDescription {
+		public:
+			typedef boost::shared_ptr<JingleRTPDescription> ref;
+
+			enum MediaType {
+				Audio,
+				Video,
+				Unknown,
+			};
+
+		public:
+			JingleRTPDescription(MediaType mediaType = Unknown, std::string bandwidthType = "",
+					std::string bandwidthValue = "", boost::uint32_t ssrc = 0) :
+				mediaType(mediaType), bandwidthType(bandwidthType), bandwidthValue(bandwidthValue), ssrc(ssrc) {}
+
+			void setMediaType(MediaType mediaType) { this->mediaType = mediaType; }
+			MediaType getMediaType() const { return mediaType; }
+
+			void setBandwidth(const std::string& type, const std::string& value) {
+				bandwidthType = type;
+				bandwidthValue = value;
+			}
+			void getBandwidth(std::string &type, std::string& value) const {
+				type = bandwidthType;
+				value = bandwidthValue;
+			}
+
+			void setSSRC(boost::uint32_t ssrc) { this->ssrc = ssrc; }
+			boost::uint32_t getSSRC() const { return ssrc; }
+
+			void addPayloadType(const RTPPayloadType& offer) { payloadTypes.push_back(offer); }
+			const std::vector<RTPPayloadType>& getPayloadTypes() const { return payloadTypes; }
+
+		private:
+			MediaType mediaType;
+			std::string bandwidthType;
+			std::string bandwidthValue;
+			boost::uint32_t ssrc;
+			std::vector<RTPPayloadType> payloadTypes;
+	};
+}
diff --git a/Swiften/Elements/RTPPayloadType.h b/Swiften/Elements/RTPPayloadType.h
index 4e737ee..b06b29d 100644
--- a/Swiften/Elements/RTPPayloadType.h
+++ b/Swiften/Elements/RTPPayloadType.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Yoann Blein
+ * Copyright (c) 2012 Yoann Blein
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
diff --git a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
index bddf96a..56fe109 100644
--- a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
+++ b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Yoann Blein
+ * Copyright (c) 2012 Yoann Blein
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
diff --git a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
index 6d566d6..8dee938 100644
--- a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
+++ b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Yoann Blein
+ * Copyright (c) 2012 Yoann Blein
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 53ce39f..f95ef45 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -205,6 +205,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp",
 			"Serializer/PayloadSerializers/WhiteboardSerializer.cpp",
 			"Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp",			
+			"Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.cpp",
 			"Serializer/PresenceSerializer.cpp",
 			"Serializer/StanzaSerializer.cpp",
 			"Serializer/StreamErrorSerializer.cpp",
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index b4822cd..3a423d1 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -63,6 +63,7 @@
 #include <Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h>
 #include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h>
 #include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h>
+#include <Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h>
 
 namespace Swift {
 
@@ -122,6 +123,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
 	serializers_.push_back(new S5BProxyRequestSerializer());
 	serializers_.push_back(new DeliveryReceiptSerializer());
 	serializers_.push_back(new DeliveryReceiptRequestSerializer());
+	serializers_.push_back(new JingleRTPDescriptionSerializer());
 	
 	foreach(PayloadSerializer* serializer, serializers_) {
 		addSerializer(serializer);
diff --git a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp
index 48da742..c36d574 100644
--- a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Tobias Markmann
+ * Copyright (c) 2012 Tobias Markmann, Yoann Blein
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
@@ -16,6 +16,7 @@
 #include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
 #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h>
+#include <Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h>
 
 #include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h>
 #include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h>
@@ -34,12 +35,16 @@ std::string JingleContentPayloadSerializer::serializePayload(boost::shared_ptr<J
 	
 	if (!payload->getDescriptions().empty()) {
 		// JingleFileTransferDescription
-		JingleFileTransferDescriptionSerializer ftSerializer;
 		JingleFileTransferDescription::ref filetransfer;
+		JingleRTPDescription::ref rtp;
 		
 		foreach(JingleDescription::ref desc, payload->getDescriptions()) {
 			if ((filetransfer = boost::dynamic_pointer_cast<JingleFileTransferDescription>(desc))) {
+				JingleFileTransferDescriptionSerializer ftSerializer;
 				payloadXML.addNode(boost::make_shared<XMLRawTextNode>(ftSerializer.serializePayload(filetransfer)));
+			} else if ((rtp = boost::dynamic_pointer_cast<JingleRTPDescription>(desc))) {
+				JingleRTPDescriptionSerializer rtpSerializer;
+				payloadXML.addNode(boost::make_shared<XMLRawTextNode>(rtpSerializer.serializePayload(rtp)));
 			}
 		}
 	}
diff --git a/Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.cpp
new file mode 100644
index 0000000..475142b
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Serializer/XML/XMLElement.h>
+#include <Swiften/Serializer/XML/XMLRawTextNode.h>
+#include <Swiften/Serializer/XML/XMLTextNode.h>
+
+#include <Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h>
+
+namespace Swift {
+
+JingleRTPDescriptionSerializer::JingleRTPDescriptionSerializer() {
+}
+
+std::string JingleRTPDescriptionSerializer::serializePayload(boost::shared_ptr<JingleRTPDescription> payload) const {
+	XMLElement description("description", "urn:xmpp:jingle:apps:rtp:1");
+	description.setAttribute("media", mediaTypeToString(payload->getMediaType()));
+	if (payload->getSSRC()) {
+		description.setAttribute("ssrc", boost::lexical_cast<std::string>(payload->getSSRC()));
+	}
+
+	if (!payload->getPayloadTypes().empty()) {
+		RTPPayloadTypeSerializer payloadTypeSerializer;
+		foreach(RTPPayloadType payloadType, payload->getPayloadTypes()) {
+			description.addNode(boost::make_shared<XMLRawTextNode>(payloadTypeSerializer.serialize(boost::make_shared<RTPPayloadType>(payloadType))));
+		}
+	}
+
+	std::string type, value;
+	payload->getBandwidth(type, value);
+	if (!type.empty()) {
+		XMLElement::ref bandwidth = boost::make_shared<XMLElement>("bandwidth");
+		bandwidth->setAttribute("type", type);
+		bandwidth->addNode(XMLTextNode::create(value));
+		description.addNode(bandwidth);
+	}
+
+	return description.serialize();
+}
+
+std::string JingleRTPDescriptionSerializer::mediaTypeToString(JingleRTPDescription::MediaType mediaType) const {
+	switch (mediaType) {
+		case JingleRTPDescription::Audio:
+			return "audio";
+		case JingleRTPDescription::Video:
+			return "video";
+		case JingleRTPDescription::Unknown:
+		default:
+			std::cerr << "Serializing unknown media type." << std::endl;
+			return "";
+	}
+	assert(false);
+	return "";
+}
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h
new file mode 100644
index 0000000..3d23d85
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+
+#pragma once
+
+#include <Swiften/Serializer/GenericPayloadSerializer.h>
+#include <Swiften/Elements/JingleRTPDescription.h>
+
+
+
+namespace Swift {
+	class PayloadSerializerCollection;
+	class XMLElement;
+
+	class JingleRTPDescriptionSerializer : public GenericPayloadSerializer<JingleRTPDescription> {
+		public:
+			JingleRTPDescriptionSerializer();
+
+			virtual std::string serializePayload(boost::shared_ptr<JingleRTPDescription>)  const;
+
+		private:
+			std::string mediaTypeToString(JingleRTPDescription::MediaType mediaType) const;
+	};
+}
diff --git a/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp
index db21146..4ddd1ec 100644
--- a/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Yoann Blein
+ * Copyright (c) 2012 Yoann Blein
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
diff --git a/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h
index dda40ea..cc0a5b5 100644
--- a/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h
+++ b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Yoann Blein
+ * Copyright (c) 2012 Yoann Blein
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
index b773fd7..bce9259 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
@@ -15,6 +15,7 @@
 #include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h>
 #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
 #include <Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h>
+#include <Swiften/Serializer/PayloadSerializers/JingleRTPDescriptionSerializer.h>
 #include <Swiften/Elements/JingleFileTransferDescription.h>
 #include <Swiften/Elements/StreamInitiationFileInfo.h>
 #include <Swiften/Elements/JingleIBBTransportPayload.h>
@@ -23,6 +24,7 @@
 #include <Swiften/Elements/JinglePayload.h>
 #include <Swiften/Elements/JingleFileTransferReceived.h>
 #include <Swiften/Elements/RTPPayloadType.h>
+#include <Swiften/Elements/JingleRTPDescription.h>
 #include <Swiften/Base/DateTime.h>
 
 using namespace Swift;
@@ -51,6 +53,9 @@ class JingleSerializersTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testSerialize_RTPPayloadType_Simple);
 		CPPUNIT_TEST(testSerialize_RTPPayloadType_WithSub);
 
+		CPPUNIT_TEST(testSerialize_Xep0167_Example1);
+		CPPUNIT_TEST(testSerialize_Xep0167_Example48);
+
 		CPPUNIT_TEST_SUITE_END();
 		
 		 boost::shared_ptr<JinglePayloadSerializer> createTestling() {
@@ -565,6 +570,93 @@ class JingleSerializersTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(payloadType));
 		}
 
+		// http://xmpp.org/extensions/xep-0167.html#example-1
+		void testSerialize_Xep0167_Example1() {
+			std::string expected =
+				"<jingle action=\"session-initiate\""
+						" initiator=\"romeo@montague.lit/orchard\""
+						" sid=\"a73sjjvkla37jfea\""
+						" xmlns=\"urn:xmpp:jingle:1\">"
+					"<content creator=\"initiator\" name=\"voice\">"
+						"<description media=\"audio\" xmlns=\"urn:xmpp:jingle:apps:rtp:1\">"
+							"<payload-type clockrate=\"16000\" id=\"96\" name=\"speex\"/>"
+							"<payload-type clockrate=\"8000\" id=\"97\" name=\"speex\"/>"
+							"<payload-type id=\"18\" name=\"G729\"/>"
+							"<payload-type id=\"0\" name=\"PCMU\"/>"
+							"<payload-type channels=\"2\" clockrate=\"16000\" id=\"103\" name=\"L16\"/>"
+							"<payload-type clockrate=\"8000\" id=\"98\" name=\"x-ISAC\"/>"
+						"</description>"
+						//"<transport [...] >"
+					"</content>"
+				"</jingle>";
+
+			JinglePayload::ref payload = boost::make_shared<JinglePayload>();
+			payload->setAction(JinglePayload::SessionInitiate);
+			payload->setInitiator(JID("romeo@montague.lit/orchard"));
+			payload->setSessionID("a73sjjvkla37jfea");
+
+			JingleRTPDescription::ref desc = boost::make_shared<JingleRTPDescription>(JingleRTPDescription::Audio);
+			desc->addPayloadType(RTPPayloadType(96, "speex", 16000));
+			desc->addPayloadType(RTPPayloadType(97, "speex", 8000));
+			desc->addPayloadType(RTPPayloadType(18, "G729"));
+			desc->addPayloadType(RTPPayloadType(0, "PCMU"));
+			desc->addPayloadType(RTPPayloadType(103, "L16", 16000, 2));
+			desc->addPayloadType(RTPPayloadType(98, "x-ISAC", 8000));
+
+			JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>();
+			content->setCreator(JingleContentPayload::InitiatorCreator);
+			content->setName("voice");
+			content->addDescription(desc);
+
+			payload->addPayload(content);
+
+			CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload));
+		}
+
+		// http://xmpp.org/extensions/xep-0167.html#example-48
+		void testSerialize_Xep0167_Example48() {
+			std::string expected =
+				"<jingle action=\"content-accept\""
+						" initiator=\"romeo@montague.lit/orchard\""
+						" sid=\"a73sjjvkla37jfea\""
+						" xmlns=\"urn:xmpp:jingle:1\">"
+					"<content creator=\"initiator\" name=\"webcam\">"
+						"<description media=\"video\" xmlns=\"urn:xmpp:jingle:apps:rtp:1\">"
+							"<payload-type clockrate=\"90000\" id=\"98\" name=\"theora\">"
+								"<parameter name=\"height\" value=\"600\"/>"
+								//"<parameter name=\"width\" value=\"800\"/>"
+								//"<parameter name=\"delivery-method\" value=\"inline\"/>"
+								//"<parameter name=\"configuration\" value=\"somebase16string\"/>"
+								"<parameter name=\"sampling\" value=\"YCbCr-4:2:2\"/>"
+							"</payload-type>"
+							"<bandwidth type=\"AS\">128</bandwidth>"
+						"</description>"
+						//"<transport xmlns=\"urn:xmpp:jingle:transports:ice-udp:0\"/>"
+					"</content>"
+				"</jingle>";
+
+			JinglePayload::ref payload = boost::make_shared<JinglePayload>();
+			payload->setAction(JinglePayload::ContentAccept);
+			payload->setInitiator(JID("romeo@montague.lit/orchard"));
+			payload->setSessionID("a73sjjvkla37jfea");
+
+			JingleRTPDescription::ref desc = boost::make_shared<JingleRTPDescription>(JingleRTPDescription::Video);
+			RTPPayloadType payloadType(98, "theora", 90000);
+			payloadType.addParameter("height", "600");
+			payloadType.addParameter("sampling", "YCbCr-4:2:2");
+			desc->addPayloadType(payloadType);
+			desc->setBandwidth("AS", "128");
+
+			JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>();
+			content->setCreator(JingleContentPayload::InitiatorCreator);
+			content->setName("webcam");
+			content->addDescription(desc);
+
+			payload->addPayload(content);
+
+			CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload));
+		}
+
 	private:
 		FullPayloadSerializerCollection collection;
 };
-- 
cgit v0.10.2-6-g49f6