~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/session/phone/mediamessages.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2010, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice,
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
/*
 
29
 * Documentation is in mediamessages.h.
 
30
 */
 
31
 
 
32
#include "talk/session/phone/mediamessages.h"
 
33
 
 
34
#include "talk/base/logging.h"
 
35
#include "talk/base/stringencode.h"
 
36
#include "talk/p2p/base/constants.h"
 
37
#include "talk/p2p/base/parsing.h"
 
38
#include "talk/session/phone/mediasessionclient.h"
 
39
#include "talk/session/phone/streamparams.h"
 
40
#include "talk/xmllite/xmlelement.h"
 
41
 
 
42
namespace cricket {
 
43
 
 
44
namespace {
 
45
 
 
46
// NOTE: There is no check here for duplicate streams, so check before
 
47
// adding.
 
48
void AddStream(std::vector<StreamParams>* streams, const StreamParams& stream) {
 
49
  streams->push_back(stream);
 
50
}
 
51
 
 
52
bool ParseSsrc(const std::string& string, uint32* ssrc) {
 
53
  return talk_base::FromString(string, ssrc);
 
54
}
 
55
 
 
56
bool ParseSsrc(const buzz::XmlElement* element, uint32* ssrc) {
 
57
  if (element == NULL) {
 
58
    return false;
 
59
  }
 
60
  return ParseSsrc(element->BodyText(), ssrc);
 
61
}
 
62
 
 
63
// Builds a <view> element according to the following spec:
 
64
// goto/jinglemuc
 
65
buzz::XmlElement* CreateViewElem(const std::string& name,
 
66
                                 const std::string& type) {
 
67
  buzz::XmlElement* view_elem =
 
68
      new buzz::XmlElement(QN_JINGLE_DRAFT_VIEW, true);
 
69
  view_elem->AddAttr(QN_NAME, name);
 
70
  view_elem->SetAttr(QN_TYPE, type);
 
71
  return view_elem;
 
72
}
 
73
 
 
74
buzz::XmlElement* CreateVideoViewElem(const std::string& content_name,
 
75
                                      const std::string& type) {
 
76
  return CreateViewElem(content_name, type);
 
77
}
 
78
 
 
79
buzz::XmlElement* CreateNoneVideoViewElem(const std::string& content_name) {
 
80
  return CreateVideoViewElem(content_name, STR_JINGLE_DRAFT_VIEW_TYPE_NONE);
 
81
}
 
82
 
 
83
buzz::XmlElement* CreateStaticVideoViewElem(const std::string& content_name,
 
84
                                            const StaticVideoView& view) {
 
85
  buzz::XmlElement* view_elem =
 
86
      CreateVideoViewElem(content_name, STR_JINGLE_DRAFT_VIEW_TYPE_STATIC);
 
87
  AddXmlAttr(view_elem, QN_SSRC, view.ssrc);
 
88
 
 
89
  buzz::XmlElement* params_elem = new buzz::XmlElement(QN_JINGLE_DRAFT_PARAMS);
 
90
  AddXmlAttr(params_elem, QN_WIDTH, view.width);
 
91
  AddXmlAttr(params_elem, QN_HEIGHT, view.height);
 
92
  AddXmlAttr(params_elem, QN_FRAMERATE, view.framerate);
 
93
  AddXmlAttr(params_elem, QN_PREFERENCE, view.preference);
 
94
  view_elem->AddElement(params_elem);
 
95
 
 
96
  return view_elem;
 
97
}
 
98
 
 
99
}  //  namespace
 
100
 
 
101
bool MediaStreams::GetAudioStreamByNickAndName(
 
102
    const std::string& nick, const std::string& name, StreamParams* stream) {
 
103
  return GetStreamByNickAndName(audio_, nick, name, stream);
 
104
}
 
105
 
 
106
bool MediaStreams::GetVideoStreamByNickAndName(
 
107
    const std::string& nick, const std::string& name, StreamParams* stream) {
 
108
  return GetStreamByNickAndName(video_, nick, name, stream);
 
109
}
 
110
 
 
111
bool MediaStreams::GetDataStreamByNickAndName(
 
112
    const std::string& nick, const std::string& name, StreamParams* stream) {
 
113
  return GetStreamByNickAndName(data_, nick, name, stream);
 
114
}
 
115
 
 
116
void MediaStreams::CopyFrom(const MediaStreams& streams) {
 
117
  audio_ = streams.audio_;
 
118
  video_ = streams.video_;
 
119
  data_ = streams.data_;
 
120
}
 
121
 
 
122
bool MediaStreams::GetAudioStreamBySsrc(uint32 ssrc, StreamParams* stream) {
 
123
  return GetStreamBySsrc(audio_, ssrc, stream);
 
124
}
 
125
 
 
126
bool MediaStreams::GetVideoStreamBySsrc(uint32 ssrc, StreamParams* stream) {
 
127
  return GetStreamBySsrc(video_, ssrc, stream);
 
128
}
 
129
 
 
130
bool MediaStreams::GetDataStreamBySsrc(uint32 ssrc, StreamParams* stream) {
 
131
  return GetStreamBySsrc(data_, ssrc, stream);
 
132
}
 
133
 
 
134
void MediaStreams::AddAudioStream(const StreamParams& stream) {
 
135
  AddStream(&audio_, stream);
 
136
}
 
137
 
 
138
void MediaStreams::AddVideoStream(const StreamParams& stream) {
 
139
  AddStream(&video_, stream);
 
140
}
 
141
 
 
142
void MediaStreams::AddDataStream(const StreamParams& stream) {
 
143
  AddStream(&data_, stream);
 
144
}
 
145
 
 
146
void MediaStreams::RemoveAudioStreamByNickAndName(
 
147
    const std::string& nick, const std::string& name) {
 
148
  RemoveStreamByNickAndName(&audio_, nick, name);
 
149
}
 
150
 
 
151
void MediaStreams::RemoveVideoStreamByNickAndName(
 
152
    const std::string& nick, const std::string& name) {
 
153
  RemoveStreamByNickAndName(&video_, nick, name);
 
154
}
 
155
 
 
156
void MediaStreams::RemoveDataStreamByNickAndName(
 
157
    const std::string& nick, const std::string& name) {
 
158
  RemoveStreamByNickAndName(&data_, nick, name);
 
159
}
 
160
 
 
161
bool IsJingleViewRequest(const buzz::XmlElement* action_elem) {
 
162
  return action_elem->FirstNamed(QN_JINGLE_DRAFT_VIEW) != NULL;
 
163
}
 
164
 
 
165
bool ParseStaticVideoView(const buzz::XmlElement* view_elem,
 
166
                          StaticVideoView* view,
 
167
                          ParseError* error) {
 
168
  if (!ParseSsrc(view_elem->Attr(QN_SSRC), &(view->ssrc))) {
 
169
    return BadParse("Invalid or missing view ssrc.", error);
 
170
  }
 
171
 
 
172
  const buzz::XmlElement* params_elem =
 
173
      view_elem->FirstNamed(QN_JINGLE_DRAFT_PARAMS);
 
174
  if (params_elem) {
 
175
    view->width = GetXmlAttr(params_elem, QN_WIDTH, 0);
 
176
    view->height = GetXmlAttr(params_elem, QN_HEIGHT, 0);
 
177
    view->framerate = GetXmlAttr(params_elem, QN_FRAMERATE, 0);
 
178
    view->preference = GetXmlAttr(params_elem, QN_PREFERENCE, 0);
 
179
  } else {
 
180
    return BadParse("Missing view params.", error);
 
181
  }
 
182
 
 
183
  return true;
 
184
}
 
185
 
 
186
bool ParseJingleViewRequest(const buzz::XmlElement* action_elem,
 
187
                            ViewRequest* view_request,
 
188
                            ParseError* error) {
 
189
  for (const buzz::XmlElement* view_elem =
 
190
           action_elem->FirstNamed(QN_JINGLE_DRAFT_VIEW);
 
191
       view_elem != NULL;
 
192
       view_elem = view_elem->NextNamed(QN_JINGLE_DRAFT_VIEW)) {
 
193
    std::string type = view_elem->Attr(QN_TYPE);
 
194
    if (STR_JINGLE_DRAFT_VIEW_TYPE_NONE == type) {
 
195
      view_request->static_video_views.clear();
 
196
      return true;
 
197
    } else if (STR_JINGLE_DRAFT_VIEW_TYPE_STATIC == type) {
 
198
      StaticVideoView static_video_view(0, 0, 0, 0);
 
199
      if (!ParseStaticVideoView(view_elem, &static_video_view, error)) {
 
200
        return false;
 
201
      }
 
202
      view_request->static_video_views.push_back(static_video_view);
 
203
    } else {
 
204
      LOG(LS_INFO) << "Ingnoring unknown view type: " << type;
 
205
    }
 
206
  }
 
207
  return true;
 
208
}
 
209
 
 
210
bool WriteJingleViewRequest(const std::string& content_name,
 
211
                            const ViewRequest& request,
 
212
                            XmlElements* elems,
 
213
                            WriteError* error) {
 
214
  if (request.static_video_views.empty()) {
 
215
    elems->push_back(CreateNoneVideoViewElem(content_name));
 
216
  } else {
 
217
    for (StaticVideoViews::const_iterator view =
 
218
             request.static_video_views.begin();
 
219
         view != request.static_video_views.end(); ++view) {
 
220
      elems->push_back(CreateStaticVideoViewElem(content_name, *view));
 
221
    }
 
222
  }
 
223
  return true;
 
224
}
 
225
 
 
226
bool ParseSsrcAsLegacyStream(const buzz::XmlElement* desc_elem,
 
227
                             std::vector<StreamParams>* streams,
 
228
                             ParseError* error) {
 
229
  const std::string ssrc_str = desc_elem->Attr(QN_SSRC);
 
230
  if (!ssrc_str.empty()) {
 
231
    uint32 ssrc;
 
232
    if (!ParseSsrc(ssrc_str, &ssrc)) {
 
233
      return BadParse("Missing or invalid ssrc.", error);
 
234
    }
 
235
 
 
236
    streams->push_back(StreamParams::CreateLegacy(ssrc));
 
237
  }
 
238
  return true;
 
239
}
 
240
 
 
241
bool ParseSsrcs(const buzz::XmlElement* parent_elem,
 
242
                std::vector<uint32>* ssrcs,
 
243
                ParseError* error) {
 
244
  for (const buzz::XmlElement* ssrc_elem =
 
245
           parent_elem->FirstNamed(QN_JINGLE_DRAFT_SSRC);
 
246
       ssrc_elem != NULL;
 
247
       ssrc_elem = ssrc_elem->NextNamed(QN_JINGLE_DRAFT_SSRC)) {
 
248
    uint32 ssrc;
 
249
    if (!ParseSsrc(ssrc_elem->BodyText(), &ssrc)) {
 
250
      return BadParse("Missing or invalid ssrc.", error);
 
251
    }
 
252
 
 
253
    ssrcs->push_back(ssrc);
 
254
  }
 
255
  return true;
 
256
}
 
257
 
 
258
bool ParseSsrcGroups(const buzz::XmlElement* parent_elem,
 
259
                     std::vector<SsrcGroup>* ssrc_groups,
 
260
                     ParseError* error) {
 
261
  for (const buzz::XmlElement* group_elem =
 
262
           parent_elem->FirstNamed(QN_JINGLE_DRAFT_SSRC_GROUP);
 
263
       group_elem != NULL;
 
264
       group_elem = group_elem->NextNamed(QN_JINGLE_DRAFT_SSRC_GROUP)) {
 
265
    std::string semantics = group_elem->Attr(QN_SEMANTICS);
 
266
    std::vector<uint32> ssrcs;
 
267
    if (!ParseSsrcs(group_elem, &ssrcs, error)) {
 
268
      return false;
 
269
    }
 
270
    ssrc_groups->push_back(SsrcGroup(semantics, ssrcs));
 
271
  }
 
272
  return true;
 
273
}
 
274
 
 
275
bool ParseJingleStream(const buzz::XmlElement* stream_elem,
 
276
                       std::vector<StreamParams>* streams,
 
277
                       ParseError* error) {
 
278
  StreamParams stream;
 
279
  stream.nick = stream_elem->Attr(QN_NICK);
 
280
  stream.name = stream_elem->Attr(QN_NAME);
 
281
  stream.type = stream_elem->Attr(QN_TYPE);
 
282
  stream.display = stream_elem->Attr(QN_DISPLAY);
 
283
  stream.cname = stream_elem->Attr(QN_CNAME);
 
284
  if (!ParseSsrcs(stream_elem, &(stream.ssrcs), error)) {
 
285
    return false;
 
286
  }
 
287
  std::vector<SsrcGroup> ssrc_groups;
 
288
  if (!ParseSsrcGroups(stream_elem, &(stream.ssrc_groups), error)) {
 
289
    return false;
 
290
  }
 
291
  streams->push_back(stream);
 
292
  return true;
 
293
}
 
294
 
 
295
bool HasJingleStreams(const buzz::XmlElement* desc_elem) {
 
296
  const buzz::XmlElement* streams_elem =
 
297
      desc_elem->FirstNamed(QN_JINGLE_DRAFT_STREAMS);
 
298
  return (streams_elem != NULL);
 
299
}
 
300
 
 
301
bool ParseJingleStreams(const buzz::XmlElement* desc_elem,
 
302
                        std::vector<StreamParams>* streams,
 
303
                        ParseError* error) {
 
304
  const buzz::XmlElement* streams_elem =
 
305
      desc_elem->FirstNamed(QN_JINGLE_DRAFT_STREAMS);
 
306
  if (streams_elem == NULL) {
 
307
    return BadParse("Missing streams element.", error);
 
308
  }
 
309
  for (const buzz::XmlElement* stream_elem =
 
310
           streams_elem->FirstNamed(QN_JINGLE_DRAFT_STREAM);
 
311
       stream_elem != NULL;
 
312
       stream_elem = stream_elem->NextNamed(QN_JINGLE_DRAFT_STREAM)) {
 
313
    if (!ParseJingleStream(stream_elem, streams, error)) {
 
314
      return false;
 
315
    }
 
316
  }
 
317
  return true;
 
318
}
 
319
 
 
320
void WriteSsrcs(const std::vector<uint32>& ssrcs,
 
321
                buzz::XmlElement* parent_elem) {
 
322
  for (std::vector<uint32>::const_iterator ssrc = ssrcs.begin();
 
323
       ssrc != ssrcs.end(); ++ssrc) {
 
324
    buzz::XmlElement* ssrc_elem =
 
325
        new buzz::XmlElement(QN_JINGLE_DRAFT_SSRC, false);
 
326
    SetXmlBody(ssrc_elem, *ssrc);
 
327
 
 
328
    parent_elem->AddElement(ssrc_elem);
 
329
  }
 
330
}
 
331
 
 
332
void WriteSsrcGroups(const std::vector<SsrcGroup>& groups,
 
333
                     buzz::XmlElement* parent_elem) {
 
334
  for (std::vector<SsrcGroup>::const_iterator group = groups.begin();
 
335
       group != groups.end(); ++group) {
 
336
    buzz::XmlElement* group_elem =
 
337
        new buzz::XmlElement(QN_JINGLE_DRAFT_SSRC_GROUP, false);
 
338
    AddXmlAttrIfNonEmpty(group_elem, QN_SEMANTICS, group->semantics);
 
339
    WriteSsrcs(group->ssrcs, group_elem);
 
340
 
 
341
    parent_elem->AddElement(group_elem);
 
342
  }
 
343
}
 
344
 
 
345
void WriteJingleStream(const StreamParams& stream,
 
346
                       buzz::XmlElement* parent_elem) {
 
347
  buzz::XmlElement* stream_elem =
 
348
      new buzz::XmlElement(QN_JINGLE_DRAFT_STREAM, false);
 
349
  AddXmlAttrIfNonEmpty(stream_elem, QN_NICK, stream.nick);
 
350
  AddXmlAttrIfNonEmpty(stream_elem, QN_NAME, stream.name);
 
351
  AddXmlAttrIfNonEmpty(stream_elem, QN_TYPE, stream.type);
 
352
  AddXmlAttrIfNonEmpty(stream_elem, QN_DISPLAY, stream.display);
 
353
  AddXmlAttrIfNonEmpty(stream_elem, QN_CNAME, stream.cname);
 
354
  WriteSsrcs(stream.ssrcs, stream_elem);
 
355
  WriteSsrcGroups(stream.ssrc_groups, stream_elem);
 
356
 
 
357
  parent_elem->AddElement(stream_elem);
 
358
}
 
359
 
 
360
void WriteJingleStreams(const std::vector<StreamParams>& streams,
 
361
                        buzz::XmlElement* parent_elem) {
 
362
  buzz::XmlElement* streams_elem =
 
363
      new buzz::XmlElement(QN_JINGLE_DRAFT_STREAMS, true);
 
364
  for (std::vector<StreamParams>::const_iterator stream = streams.begin();
 
365
       stream != streams.end(); ++stream) {
 
366
    WriteJingleStream(*stream, streams_elem);
 
367
  }
 
368
 
 
369
  parent_elem->AddElement(streams_elem);
 
370
}
 
371
 
 
372
}  // namespace cricket