Commit 1d3ebe19 authored by Tristan Matthews's avatar Tristan Matthews
Browse files

* #13814: video: add codec-specifc "parameters" handling

parent 417f6d8f
......@@ -40,6 +40,10 @@
#include <algorithm>
#ifdef SFL_VIDEO
#include "video/libav_utils.h"
#endif
using std::string;
using std::map;
using std::vector;
......@@ -424,7 +428,7 @@ string Sdp::getLineFromSession(const pjmedia_sdp_session *sess, const string &ke
return "";
}
string Sdp::getActiveIncomingVideoDescription() const
string Sdp::getIncomingVideoDescription() const
{
stringstream ss;
ss << "v=0" << std::endl;
......@@ -471,10 +475,10 @@ string Sdp::getActiveIncomingVideoDescription() const
return ss.str();
}
std::string Sdp::getActiveOutgoingVideoCodec() const
std::string Sdp::getOutgoingVideoCodec() const
{
string str("a=rtpmap:");
str += getActiveOutgoingVideoPayload();
str += getOutgoingVideoPayload();
string vCodecLine(getLineFromSession(activeRemoteSession_, str));
char codec_buf[32];
codec_buf[0] = '\0';
......@@ -482,20 +486,33 @@ std::string Sdp::getActiveOutgoingVideoCodec() const
return string(codec_buf);
}
std::string Sdp::getActiveOutgoingVideoBitrate(const std::string &codec) const
{
for (vector<map<string, string> >::const_iterator i = video_codec_list_.begin(); i != video_codec_list_.end(); ++i) {
map<string, string>::const_iterator name = i->find("name");
if (name != i->end() and (codec == name->second)) {
map<string, string>::const_iterator bitrate = i->find("bitrate");
if (bitrate != i->end())
return bitrate->second;
namespace {
vector<map<string, string> >::const_iterator
findCodecInList(const vector<map<string, string> > &codecs, const string &codec)
{
for (vector<map<string, string> >::const_iterator i = codecs.begin(); i != codecs.end(); ++i) {
map<string, string>::const_iterator name = i->find("name");
if (name != i->end() and (codec == name->second))
return i;
}
return codecs.end();
}
}
std::string
Sdp::getOutgoingVideoField(const std::string &codec, const char *key) const
{
const vector<map<string, string> >::const_iterator i = findCodecInList(video_codec_list_, codec);
if (i != video_codec_list_.end()) {
map<string, string>::const_iterator field = i->find(key);
if (field != i->end())
return field->second;
}
return "0";
return "";
}
std::string Sdp::getActiveOutgoingVideoPayload() const
std::string
Sdp::getOutgoingVideoPayload() const
{
string videoLine(getLineFromSession(activeRemoteSession_, "m=video"));
int payload_num;
......@@ -539,7 +556,7 @@ namespace {
ERROR("Session is NULL when looking for \"%s\" attribute", type);
return -1;
}
int i = 0;
size_t i = 0;
while (i < session->media_count and pj_stricmp2(&session->media[i]->desc.media, type) != 0)
++i;
......@@ -616,3 +633,24 @@ void Sdp::getRemoteSdpCryptoFromOffer(const pjmedia_sdp_session* remote_sdp, Cry
}
}
}
bool Sdp::getOutgoingVideoSettings(map<string, string> &args) const
{
#ifdef SFL_VIDEO
string codec(getOutgoingVideoCodec());
if (not codec.empty()) {
const string encoder(libav_utils::encodersMap()[codec]);
if (encoder.empty()) {
DEBUG("Couldn't find encoder for \"%s\"\n", codec.c_str());
return false;
} else {
args["codec"] = encoder;
args["bitrate"] = getOutgoingVideoField(codec, "bitrate");
args["parameters"] = getOutgoingVideoField(codec, "parameters");
args["payload_type"] = getOutgoingVideoPayload();
}
return true;
}
#endif
return false;
}
......@@ -113,10 +113,7 @@ class Sdp {
* Returns a string version of the negotiated SDP fields which pertain
* to video.
*/
std::string getActiveIncomingVideoDescription() const;
std::string getActiveOutgoingVideoCodec() const;
std::string getActiveOutgoingVideoBitrate(const std::string &codec) const;
std::string getActiveOutgoingVideoPayload() const;
std::string getIncomingVideoDescription() const;
/*
* On building an invite outside a dialog, build the local offer and create the
......@@ -242,12 +239,18 @@ class Sdp {
std::string getAudioCodecName() const;
std::string getSessionVideoCodec() const;
sfl::AudioCodec* getSessionAudioMedia() const;
// Sets @param settings with appropriate values and returns true if
// we are sending video, false otherwise
bool getOutgoingVideoSettings(std::map<std::string, std::string> &settings) const;
private:
NON_COPYABLE(Sdp);
friend class SDPTest;
std::string getLineFromSession(const pjmedia_sdp_session *sess, const std::string &keyword) const;
std::string getOutgoingVideoCodec() const;
std::string getOutgoingVideoField(const std::string &codec, const char *key) const;
std::string getOutgoingVideoPayload() const;
/**
* The pool to allocate memory, ownership to SipCall
......
......@@ -36,7 +36,6 @@
#include "video_receive_thread.h"
#include "sip/sdp.h"
#include "sip/sipvoiplink.h"
#include "libav_utils.h"
#include "manager.h"
#include "logger.h"
......@@ -52,7 +51,7 @@ VideoRtpSession::VideoRtpSession(const string &callID, const map<string, string>
void VideoRtpSession::updateSDP(const Sdp &sdp)
{
string desc(sdp.getActiveIncomingVideoDescription());
string desc(sdp.getIncomingVideoDescription());
// if port has changed
if (desc != rxArgs_["receiving_sdp"]) {
rxArgs_["receiving_sdp"] = desc;
......@@ -84,21 +83,8 @@ void VideoRtpSession::updateSDP(const Sdp &sdp)
receiving_ = false;
}
string codec(sdp.getActiveOutgoingVideoCodec());
if (not codec.empty()) {
const string encoder(libav_utils::encodersMap()[codec]);
if (encoder.empty()) {
DEBUG("Couldn't find encoder for \"%s\"\n", codec.c_str());
sending_ = false;
} else {
txArgs_["codec"] = encoder;
txArgs_["bitrate"] = sdp.getActiveOutgoingVideoBitrate(codec);
}
} else {
sending_ = false;
}
txArgs_["payload_type"] = sdp.getActiveOutgoingVideoPayload();;
if (sending_)
sending_ = sdp.getOutgoingVideoSettings(txArgs_);
}
void VideoRtpSession::updateDestination(const string &destination,
......
......@@ -62,6 +62,7 @@ enum {
COLUMN_CODEC_ACTIVE,
COLUMN_CODEC_NAME,
COLUMN_CODEC_BITRATE,
COLUMN_CODEC_PARAMETERS,
CODEC_COLUMN_COUNT
};
......@@ -164,12 +165,14 @@ preferences_dialog_fill_codec_list(account_t *acc)
GtkTreeIter iter;
gtk_list_store_append(codecStore, &iter);
const gchar *bitrate = g_hash_table_lookup(c, "bitrate");
const gchar *parameters = g_hash_table_lookup(c, "parameters");
const gboolean is_active = !g_strcmp0(g_hash_table_lookup(c, "enabled"), "true");
const gchar *name = g_hash_table_lookup(c, "name");
gtk_list_store_set(codecStore, &iter, COLUMN_CODEC_ACTIVE,
is_active, COLUMN_CODEC_NAME, name,
COLUMN_CODEC_BITRATE, bitrate, -1);
COLUMN_CODEC_BITRATE, bitrate,
COLUMN_CODEC_PARAMETERS, parameters, -1);
}
}
g_ptr_array_free(vcodecs, TRUE);
......@@ -198,6 +201,12 @@ video_codec_set_bitrate(GHashTable *codec, const gchar *bitrate)
g_hash_table_replace(codec, g_strdup("bitrate"), g_strdup(bitrate));
}
static void
video_codec_set_parameters(GHashTable *codec, const gchar *parameters)
{
g_hash_table_replace(codec, g_strdup("parameters"), g_strdup(parameters));
}
static GHashTable *
video_codec_list_get_by_name(GPtrArray *vcodecs, const gchar *name)
{
......@@ -403,6 +412,46 @@ bitrate_edited_cb(GtkCellRenderer *renderer UNUSED, gchar *path, gchar *new_text
}
static void
parameters_edited_cb(GtkCellRenderer *renderer UNUSED, gchar *path, gchar *new_text, gpointer data)
{
account_t *acc = (account_t*) data;
if (!acc) {
ERROR("No account selected");
return;
}
if (strlen(new_text) == 0)
return;
// Get path of edited codec
GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(codecTreeView));
GtkTreeIter iter;
gtk_tree_model_get_iter(model, &iter, tree_path);
gtk_tree_path_free(tree_path);
gchar *name = NULL;
gtk_tree_model_get(model, &iter, COLUMN_CODEC_NAME, &name, -1);
GPtrArray *vcodecs = dbus_get_video_codecs(acc->accountID);
if (!vcodecs)
return;
gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_CODEC_PARAMETERS, new_text, -1);
GHashTable *codec = video_codec_list_get_by_name(vcodecs, name);
if (codec) {
DEBUG("Setting new parameters \"%s\" for %s", new_text, name);
video_codec_set_parameters(codec, new_text);
dbus_set_video_codecs(acc->accountID, vcodecs);
} else {
ERROR("Could not find codec %s", name);
}
g_ptr_array_free(vcodecs, TRUE);
}
GtkWidget *
videocodecs_box(account_t *acc)
{
......@@ -453,6 +502,13 @@ videocodecs_box(account_t *acc)
treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Bitrate (kbps)"), renderer, "text", COLUMN_CODEC_BITRATE, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(codecTreeView), treeViewColumn);
/* Parameters column */
renderer = gtk_cell_renderer_text_new();
g_object_set(renderer, "editable", TRUE, NULL);
g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(parameters_edited_cb), acc);
treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Parameters"), renderer, "text", COLUMN_CODEC_PARAMETERS, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(codecTreeView), treeViewColumn);
gtk_container_add(GTK_CONTAINER(scrolledWindow), codecTreeView);
// Create button box
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment