[server] / trunk / server / src / ipmdevice.cxx Repository:
ViewVC logotype

Diff of /trunk/server/src/ipmdevice.cxx

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 142, Thu Apr 30 17:35:14 2009 UTC revision 634, Fri Mar 19 17:43:14 2010 UTC
# Line 1  Line 1 
1  /*  /*
2   * This file is part of the Dialogic Woomera Server project.   * This file is part of Project DiaStar Server.
3   *   *
4     * More information about this project can be found at:
5     * http://www.projectdiastar.org.
6   *   *
7   * Copyright (C) 2009 Dialogic Corporation   * Copyright (C) 2009 Dialogic Corp.
8   * All Rights Reserved   *
9     * This program is free software; you can redistribute it and/or
10     * modify it under the terms of the GNU General Public License
11     * as published by the Free Software Foundation; either version 2
12     * of the License, or (at your option) any later version.
13     *
14     * This program is distributed in the hope that it will be useful,
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     * GNU General Public License for more details.
18     *
19     * You should have received a copy of the GNU General Public License
20     * along with this program; if not, write to the Free Software
21     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22     * 02110-1301, USA.
23     * Alternatively see <http://www.gnu.org/licenses/>.
24     * Or see the LICENSE file included within the source tree.
25   *   *
26   */   */
27    
# Line 11  Line 29 
29   * \file        ipmdevice.cxx   * \file        ipmdevice.cxx
30   * \brief       Dialogic IPM device   * \brief       Dialogic IPM device
31   * \author      Antony Martin <antony.martin@dialogic.com>   * \author      Antony Martin <antony.martin@dialogic.com>
32     * \author      John Tarlton <john.tarlton@dialogic.com>
33   * \version     2-APR-2009   * \version     2-APR-2009
34   */   */
35    
36  /*------------------------------ Dependencies --------------------------------*/  /*------------------------------ Dependencies --------------------------------*/
37    
38  #include "logger.h"  #include "logger.h"
39    #include "string-util.h"
40    
41    #include "overlay.h"
42    #include "dialogicchannelmanager.h"
43    #include "mmdevice.h"
44    #include "gciptdevice.h"
45  #include "ipmdevice.h"  #include "ipmdevice.h"
46    
47  /*----------------------------------------------------------------------------*/  /*----------------------------------------------------------------------------*/
# Line 28  Line 53 
53                            DialogicChannelManager& channelMgr )                            DialogicChannelManager& channelMgr )
54          : DialogicDevice(name, channelMgr)          : DialogicDevice(name, channelMgr)
55  {  {
56          memset(&localMediaInfo_, 0, sizeof(IPM_MEDIA_INFO));          ipt_ = 0;        /* standalone mode */
57            busy_ = false;
58            overlay_ = 0;
59    
60            /* Lookup configured audio coder as the default.
61             */
62            const Coders::audio_coders_t& audioCoders = channelMgr_.getAudioCoders();
63            Coders::audio_coders_t::const_iterator i = audioCoders.begin();
64            for ( ; i != audioCoders.end(); ++i )
65            {
66                    if ( channelMgr_.getClientAudioFormat() == (*i).encoding )
67                    {
68                            localAudioCoder_ = *i;
69                            break;
70                    }
71            }
72            if ( i == audioCoders.end() )
73            {
74                     /*  Hard default: PCMU */
75    
76                    LOGWARN("IpmDevice::IpmDevice() No coder found for: "  <<
77                            channelMgr_.getClientAudioFormat() <<
78                            ", falling back to hard default PCMU");
79    
80                    localAudioCoder_.coderType = CODER_TYPE_G711ULAW64K;
81                    localAudioCoder_.coderPayloadType = 0;
82                    localAudioCoder_.coderFramesize = CODER_FRAMESIZE_20;
83                    localAudioCoder_.framesPerPkt = 1;
84                    localAudioCoder_.vadEnable = CODER_VAD_ENABLE;
85                    localAudioCoder_.redPayloadType = 0;
86            }
87    
88            /* Lookup configured video coder as the default.
89             */
90            const Coders::video_coders_t& videoCoders = channelMgr_.getVideoCoders();
91            Coders::video_coders_t::const_iterator j = videoCoders.begin();
92            for ( ; j != videoCoders.end(); ++j )
93            {
94                    if ( channelMgr_.getClientVideoFormat() == (*j).encoding )
95                    {
96                            localVideoCoder_ = *j;
97                            break;
98                    }
99            }
100            if ( j == videoCoders.end() )
101            {
102                    /* Hard default: H.263 QCIF=2 */
103    
104                    LOGWARN("IpmDevice::IpmDevice() No codee found for: "  <<
105                            channelMgr_.getClientVideoFormat() <<
106                            ", falling back to hard default H.263");
107    
108                    localVideoCoder_.coderType = CODER_TYPE_H263;
109                    localVideoCoder_.coderPayloadType = 34;
110                    localVideoCoder_.profile = VIDEO_PROFILE_0_H263;
111                    localVideoCoder_.level = VIDEO_LEVEL_10_H263;
112                    localVideoCoder_.bitRate = 384000;
113                    localVideoCoder_.samplingRate = VIDEO_SAMPLING_RATE_DEFAULT;
114    
115                    localVideoCoder_.active_fmt.imageWidth = VIDEO_IMAGE_WIDTH_176;
116                    localVideoCoder_.active_fmt.imageHeight = VIDEO_IMAGE_HEIGHT_144;
117                    localVideoCoder_.active_fmt.framesPerSec = VIDEO_FRAMESPERSEC_15;
118                    localVideoCoder_.available_fmts.push_back(localVideoCoder_.active_fmt);
119            }
120    
121            remoteAudioCoder_ = localAudioCoder_;
122            remoteVideoCoder_ = localVideoCoder_;
123    
124            dtmf_mode_ = DTMF_RFC2833;
125            rfc2833_payload_type_ = 101;  /* may be changed by sdp processing */
126    
127          /* Number of steps in the initialisation sequence, decremented by event          /* Number of steps in the initialisation sequence, decremented by event
128           * handlers. When zero state is changed to IDLE.           * handlers. When zero, state is changed to IDLE.
129           *           *
130           *  IPMEV_OPEN,           *  IPMEV_OPEN,
131           *  DMEV_GET_RX_PORT_INFO,           *  DMEV_GET_RX_PORT_INFO,
# Line 46  Line 140 
140   */   */
141  IpmDevice::~IpmDevice()  IpmDevice::~IpmDevice()
142  {  {
143            delete overlay_;
144    }
145    
146    
147    /*
148     * Process a command that was queueued because an async operation was in progress
149     * when it was initially requested.
150     */
151    void IpmDevice::processPendingCommand()
152    {
153            while ( !busy_ && !pending_.empty() )
154            {
155                    LOGDEBUG("IpmDevice::processPendingCommand()");
156                    switch( pending_.front().cmd )
157                    {
158                            case IpmCommand::START:
159                                    startMedia();
160                                    break;
161    
162                            case IpmCommand::STOP:
163                                    stop(pending_.front().operation);
164                                    break;
165    
166                            case IpmCommand::LISTEN:
167                                    listen(pending_.front().other.audio);
168                                    break;
169    
170                            case IpmCommand::UNLISTEN:
171                                    unListen();
172                                    break;
173    
174                            case IpmCommand::CONNECT:
175                                    connect(pending_.front().other.audio,
176                                            pending_.front().other.video,
177                                            pending_.front().other.transcode_audio,
178                                            pending_.front().other.transcode_video);
179                                    break;
180    
181                            case IpmCommand::DISCONNECT:
182                                    disconnect();
183                                    break;
184    
185                            case IpmCommand::ADD_OVERLAY:
186                                    addOverlay(pending_.front().overlay_info);
187                                    break;
188    
189                            case IpmCommand::REMOVE_OVERLAY:
190                                    removeOverlay();
191                                    break;
192    
193                            default:
194                                    break;
195                    }
196                    pending_.pop();
197            }
198  }  }
199    
200    
# Line 54  Line 203 
203   */   */
204  bool IpmDevice::open()  bool IpmDevice::open()
205  {  {
206          LOGDEBUG("IpmDevice::open() device: " << devName_);          LOGDEBUG("IpmDevice::open() device: " << getDeviceName());
207    
208          devHandle_ = ipm_Open(devName_.c_str(), NULL, EV_ASYNC);          devHandle_ = ipm_Open(getDeviceName().c_str(), NULL, EV_ASYNC);
209          if ( devHandle_ < 0 )          if ( devHandle_ < 0 )
210          {          {
211                  LOGERROR("ipm_Open() failed");                  LOGERROR("ipm_Open() failed");
# Line 72  Line 221 
221   */   */
222  bool IpmDevice::close()  bool IpmDevice::close()
223  {  {
224          LOGDEBUG("IpmDevice::close() device: " << devName_);          LOGDEBUG("IpmDevice::close() device: " << getDeviceName());
225    
226          if ( devHandle_ > 0 )          if ( devHandle_ > 0 )
227          {          {
# Line 92  Line 241 
241   */   */
242  bool IpmDevice::listen( DialogicDevice* other )  bool IpmDevice::listen( DialogicDevice* other )
243  {  {
244          LOGDEBUG("IpmDevice::listen() device: " << devName_ <<          if ( busy_ )
245            {
246                    pending_.push(IpmCommand(IpmCommand::LISTEN, other));
247                    return true;
248            }
249    
250            if ( other_audio_ != other )
251            {
252                    LOGDEBUG("IpmDevice::listen() device: " << getDeviceName() <<
253                   " other: " << other->getDeviceName());                   " other: " << other->getDeviceName());
254    
255          SC_TSINFO tsinfo;          SC_TSINFO tsinfo;
256          tsinfo.sc_numts = 1;          tsinfo.sc_numts = 1;
257          tsinfo.sc_tsarrayp = other->getTimeslot();                  tsinfo.sc_tsarrayp = other->getXmitTimeslotPtr();
258    
259          if ( ipm_Listen(devHandle_, &tsinfo, EV_SYNC) == -1 )                  if ( ipm_Listen(devHandle_, &tsinfo, EV_ASYNC) == -1 )
260          {          {
261                  LOGERROR("ipm_Listen() failed on device: " << devName_ <<                          LOGERROR("ipm_Listen() failed on device: " << getDeviceName() <<
262                           " " << ATDV_ERRMSGP(devHandle_));                           " " << ATDV_ERRMSGP(devHandle_));
263                  return false;                  return false;
264          }          }
265                    other_audio_ = other;
266                    busy_ = true;
267            }
268          return true;          return true;
269  }  }
270    
# Line 114  Line 274 
274   */   */
275  bool IpmDevice::unListen()  bool IpmDevice::unListen()
276  {  {
277          LOGDEBUG("IpmDevice::unListen() device: " << devName_);          if ( busy_ )
278            {
279                    pending_.push(IpmCommand(IpmCommand::UNLISTEN));
280                    return true;
281            }
282    
283            if ( other_audio_ )
284            {
285                    LOGDEBUG("IpmDevice::unListen() device: " << getDeviceName());
286    
287          if ( ipm_UnListen(devHandle_, EV_SYNC) == -1)                  if ( ipm_UnListen(devHandle_, EV_ASYNC) == -1)
288          {          {
289                  LOGERROR("ipm_UnListen() failed on device: " << devName_ <<                          LOGERROR("ipm_UnListen() failed on device: " << getDeviceName() <<
290                           " " << ATDV_ERRMSGP(devHandle_));                           " " << ATDV_ERRMSGP(devHandle_));
291                  return false;                  return false;
292          }          }
293                    other_audio_ = 0;
294                    busy_ = true;
295            }
296          return true;          return true;
297  }  }
298    
299    
300  /*  /*
301   * Search localMediaInfo_ for the requested information.   * Connect media.
302   */   */
303  void IpmDevice::getLocalMediaInfo( eIPM_MEDIA_TYPE type,  bool IpmDevice::connect( DialogicDevice* other_audio,
304                                     IpInfo& rtp_media ) const                           DialogicDevice* other_video,
305                             bool transcode_audio,
306                             bool transcode_video )
307    {
308            if ( busy_ )
309            {
310                    pending_.push(IpmCommand(IpmCommand::CONNECT,
311                                             other_audio,
312                                             other_video,
313                                             transcode_audio,
314                                             transcode_video));
315                    return true;
316            }
317    
318            if ( !other_audio_ && !other_video_ )
319            {
320                    LOGDEBUG("IpmDevice::connect() device: " << getDeviceName() <<
321                             " other_audio: " << (other_audio ? other_audio->getDeviceName() : "n/a") <<
322                             " other_video: " << (other_video ? other_video->getDeviceName() : "n/a") <<
323                             " transcode_audio: " << (transcode_audio ? "Y" : "N") <<
324                             " transcode_video: " << (transcode_video ? "Y" : "N"));
325    
326                    DM_PORT_CONNECT_INFO_LIST portConnectInfoList;
327                    memset(&portConnectInfoList, 0, sizeof(portConnectInfoList));
328                    INIT_DM_PORT_CONNECT_INFO_LIST(&portConnectInfoList);
329                    int count = 0;
330    
331                    if ( other_audio )
332                    {
333                            INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]);
334    /* XXX crashes DME if both media set to native.
335                            portConnectInfoList.port_connect_info[count].unFlags = transcode_audio ? DMFL_TRANSCODE_ON : DMFL_TRANSCODE_NATIVE;
336    */
337                            portConnectInfoList.port_connect_info[count].unFlags = DMFL_TRANSCODE_ON;
338                            portConnectInfoList.port_connect_info[count].port_info_tx = getAudioTxPortInfo();
339                            portConnectInfoList.port_connect_info[count].port_info_rx = other_audio->getAudioRxPortInfo();
340                            count++;
341                    }
342                    if ( other_video )
343                    {
344                            INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]);
345                            portConnectInfoList.port_connect_info[count].unFlags = transcode_video ? DMFL_TRANSCODE_ON : DMFL_TRANSCODE_NATIVE;
346                            portConnectInfoList.port_connect_info[count].port_info_tx = getVideoTxPortInfo();
347                            portConnectInfoList.port_connect_info[count].port_info_rx = other_video->getVideoRxPortInfo();
348                            count++;
349                    }
350                    portConnectInfoList.unCount = count;
351                    if ( dev_PortConnect(devHandle_, &portConnectInfoList, NULL) != DEV_SUCCESS )
352                    {
353                            LOGERROR("IpmDevice::connect() dev_PortConnect() failed on device: " << getDeviceName() <<
354                                     " " << ATDV_ERRMSGP(devHandle_));
355                            return false;
356                    }
357    
358                    other_audio_ = other_audio;
359                    other_video_ = other_video;
360                    busy_ = true;
361            }
362            else
363  {  {
364          for ( unsigned int i = 0; i < localMediaInfo_.unCount; i++ )                  if ( other_audio && other_audio_ && (other_audio != other_audio_) )
365          {          {
366                  if ( type == localMediaInfo_.MediaData[i].eMediaType )                          LOGERROR("IpmDevice::connect() " << getDeviceName() <<
367                                     " unable to connect audio to device: " << other_audio->getDeviceName() <<
368                                     " already connected to device: "  << other_audio_->getDeviceName());
369                    }
370                    if ( other_video && other_video_ && (other_video != other_video_) )
371                  {                  {
372                          rtp_media.setAddress(localMediaInfo_.MediaData[i].mediaInfo.PortInfo.cIPAddress);                          LOGERROR("IpmDevice::connect() " << getDeviceName() <<
373                          rtp_media.setPort(localMediaInfo_.MediaData[i].mediaInfo.PortInfo.unPortId);                                   " unable to connect video to device: " << other_video->getDeviceName() <<
374                          break;                                   " already connected to device: "  << other_video_->getDeviceName());
375                    }
376    
377            }
378            return true;
379    }
380    
381    
382    /*
383     * Disconnect media.
384     */
385    bool IpmDevice::disconnect()
386    {
387            if ( busy_ )
388            {
389                    pending_.push(IpmCommand(IpmCommand::DISCONNECT));
390                    return true;
391            }
392    
393            if ( other_audio_ || other_video_ )
394            {
395                    LOGDEBUG("IpmDevice::disconnect() device: " << getDeviceName() <<
396                             " other_audio: " << (other_audio_ ? other_audio_->getDeviceName() : "n/a") <<
397                             " other_video: " << (other_video_ ? other_video_->getDeviceName() : "n/a"));
398    
399                    DM_PORT_CONNECT_INFO_LIST portConnectInfoList;
400                    memset(&portConnectInfoList, 0, sizeof(portConnectInfoList));
401                    INIT_DM_PORT_CONNECT_INFO_LIST(&portConnectInfoList);
402                    int count = 0;
403    
404                    if ( other_audio_ )
405                    {
406                            INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]);
407                            portConnectInfoList.port_connect_info[count].port_info_tx = getAudioTxPortInfo();
408                            portConnectInfoList.port_connect_info[count].port_info_rx = other_audio_->getAudioRxPortInfo();
409                            count++;
410                    }
411                    if ( other_video_ )
412                    {
413                            INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]);
414                            portConnectInfoList.port_connect_info[count].port_info_tx = getVideoTxPortInfo();
415                            portConnectInfoList.port_connect_info[count].port_info_rx = other_video_->getVideoRxPortInfo();
416                            count++;
417                    }
418    
419                    portConnectInfoList.unCount = count;
420                    if ( dev_PortDisconnect(devHandle_, &portConnectInfoList, NULL) != DEV_SUCCESS )
421                    {
422                            LOGERROR("IpmDevice::disconnect() dev_PortDisconnect() failed on device: " << getDeviceName() <<
423                                     " " << ATDV_ERRMSGP(devHandle_));
424                            return false;
425                    }
426    
427                    other_audio_ = 0;
428                    other_video_ = 0;
429                    busy_ = true;
430            }
431            return true;
432                  }                  }
433    
434    
435    /*
436     * Get local RTP info.
437     */
438    bool IpmDevice::getLocalMediaInfo( eIPM_MEDIA_TYPE type,
439                                       IpInfo& rtp_media ) const
440    {
441            switch ( type )
442            {
443                    case MEDIATYPE_AUDIO_LOCAL_RTP_INFO:
444                            rtp_media = localRtpAudio_;
445                            break;
446    
447                    case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO:
448                            rtp_media = localRtcpAudio_;
449                            break;
450    
451                    case MEDIATYPE_VIDEO_LOCAL_RTP_INFO:
452                            rtp_media = localRtpVideo_;
453                            break;
454    
455                    case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO:
456                            rtp_media = localRtcpVideo_;
457                            break;
458    
459                    default:
460                            return false;
461          }          }
462            return true;
463  }  }
464    
465    
466  /*  /*
467   * Save the remote params.   * Save the remote params, the RTCP port is assumed to be media + 1.
468   */   */
469  void IpmDevice::setRemoteMediaInfo( eIPM_MEDIA_TYPE type,  void IpmDevice::setRemoteMediaInfo( eIPM_MEDIA_TYPE type,
470                                      const IpInfo& rtp_info )                                      const IpInfo& rtp_info )
471  {  {
472            if ( type == MEDIATYPE_AUDIO_REMOTE_RTP_INFO )
473            {
474          remoteRtpAudio_ = rtp_info;          remoteRtpAudio_ = rtp_info;
475          remoteRtcpAudio_ = rtp_info;          remoteRtcpAudio_ = rtp_info;
476          remoteRtcpAudio_.setPort(remoteRtpAudio_.getPort() + 1); // XXXXXXXXXx                  remoteRtcpAudio_.setPort(remoteRtpAudio_.getPort() + 1);
477    
478                    LOGDEBUG("IpmDevice::setRemoteMediaInfo() device: " << getDeviceName() <<
479                             " a=" << remoteRtpAudio_);
480            }
481            if ( type == MEDIATYPE_VIDEO_REMOTE_RTP_INFO )
482            {
483                    remoteRtpVideo_ = rtp_info;
484                    remoteRtcpVideo_ = rtp_info;
485                    remoteRtcpVideo_.setPort(remoteRtpVideo_.getPort() + 1);
486                    LOGDEBUG("IpmDevice::setRemoteMediaInfo() device: " << getDeviceName() <<
487                             " v=" << remoteRtpVideo_);
488            }
489    }
490    
491    
492    /*
493     * Get remote Rtp info.
494     */
495    bool IpmDevice::getRemoteMediaInfo( eIPM_MEDIA_TYPE type,
496                                        IpInfo& rtp_media ) const
497    {
498            switch ( type )
499            {
500                    case MEDIATYPE_AUDIO_REMOTE_RTP_INFO:
501                            rtp_media = remoteRtpAudio_;
502                            break;
503    
504                    case MEDIATYPE_AUDIO_REMOTE_RTCP_INFO:
505                            rtp_media = remoteRtcpAudio_;
506                            break;
507    
508                    case MEDIATYPE_VIDEO_REMOTE_RTP_INFO:
509                            rtp_media = remoteRtpVideo_;
510                            break;
511    
512                    case MEDIATYPE_VIDEO_REMOTE_RTCP_INFO:
513                            rtp_media = remoteRtcpVideo_;
514                            break;
515    
516                    default:
517                            return false;
518            }
519            return true;
520  }  }
521    
522    
# Line 163  Line 527 
527  {  {
528          if ( state_ == IPM_IDLE )          if ( state_ == IPM_IDLE )
529          {          {
530                  return false;                  return true; /* already stopped */
531            }
532    
533            if ( busy_ )
534            {
535                    pending_.push(IpmCommand(IpmCommand::STOP, operation));
536                    return true;
537          }          }
538    
539          if ( ipm_Stop(devHandle_, operation, EV_ASYNC) == -1 )          if ( ipm_Stop(devHandle_, operation, EV_ASYNC) == -1 )
540          {          {
541                  LOGERROR("ipm_Stop() on device: " << devName_ << " failed: " <<                  LOGERROR("ipm_Stop() on device: " << getDeviceName() << " failed: " <<
542                           ATDV_LASTERR(devHandle_));                           ATDV_LASTERR(devHandle_));
543                  return false;                  return false;
544          }          }
545    
546            LOGDEBUG("IpmDevice::stopMedia() stopping RTP streaming on device: " <<
547                     getDeviceName());
548    
549          state_ = IPM_STOPPING;          state_ = IPM_STOPPING;
550            busy_ = true;
551    
552          return true;          return true;
553  }  }
554    
555    
556  /*  /*
557   * Start RTP streaming to peer.   * Start RTP streaming to peer using the current settings.
558   */   */
559  bool IpmDevice::startMedia()  bool IpmDevice::startMedia()
560  {  {
561          return startMedia(remoteRtpAudio_, remoteRtcpAudio_);          return startMedia(remoteRtpAudio_,
562                              remoteRtcpAudio_,
563                              remoteRtpVideo_,
564                              remoteRtcpVideo_);
565  }  }
566    
567    
568  /*  /*
569   * Start RTP streaming using G.711 and local/remote port information.   * Start RTP streaming: audio and video.
  * Will use G.711 - choose ALaw Ulaw from woomera msg?  
  * Mu hardwired in for now.  
570   */   */
571  bool IpmDevice::startMedia( const IpInfo& remote_rtp_audio,  bool IpmDevice::startMedia( const IpInfo& remote_rtp_audio,
572                              const IpInfo& remote_rtcp_audio )                              const IpInfo& remote_rtcp_audio,
573                                const IpInfo& remote_rtp_video,
574                                const IpInfo& remote_rtcp_video )
575    {
576            if ( busy_ )
577            {
578                    pending_.push(IpmCommand(IpmCommand::START));
579                    return true;
580            }
581    
582            if ( state_ == IPM_STREAMING )
583  {  {
584          if ( state_ != IPM_IDLE )                   /* already started, ignore */
585                    LOGDEBUG("IpmDevice::startMedia() already streaming on device: " <<
586                             getDeviceName());
587                    return true;
588            }
589    
590            if ( !remote_rtp_audio.isValid() && !remote_rtp_video.isValid() )
591          {          {
592                  LOGERROR("IpmDevice::startMedia() device: " << devName_ << " is not in IDLE state");                  LOGERROR("IpmDevice::startMedia() no remote rtp media for device: " <<
593                             getDeviceName());
594                  return false;                  return false;
595          }          }
596    
597            setDtmfMode(dtmf_mode_);
598    
599          IPM_MEDIA_INFO mediaInfo;          IPM_MEDIA_INFO mediaInfo;
600          memset(&mediaInfo, 0, sizeof(IPM_MEDIA_INFO));          memset(&mediaInfo, 0, sizeof(IPM_MEDIA_INFO));
601    
602          int mediaCnt = 0; /* limit MAX_MEDIA_INFO */          int mediaCnt = 0; /* limit MAX_MEDIA_INFO */
603    
604          /* remote audio          /* local audio.
605           */           */
606          mediaInfo.MediaData[mediaCnt].eMediaType =      MEDIATYPE_AUDIO_REMOTE_CODER_INFO;          mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_LOCAL_CODER_INFO;
607          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = localAudioCoder_.coderType;
608          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_20;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = localAudioCoder_.coderFramesize;
609          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = 1;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = localAudioCoder_.framesPerPkt;
610          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_ENABLE;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = localAudioCoder_.vadEnable;
611          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 0;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = localAudioCoder_.coderPayloadType;
612          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = 0;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = localAudioCoder_.redPayloadType;
613          mediaCnt++;          mediaCnt++;
614    
615          /* local audio          /* remote audio.
616           */           */
617          mediaInfo.MediaData[mediaCnt].eMediaType =      MEDIATYPE_AUDIO_LOCAL_CODER_INFO;          mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_CODER_INFO;
618          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = remoteAudioCoder_.coderType;
619          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_20;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = remoteAudioCoder_.coderFramesize;
620          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = 1;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = remoteAudioCoder_.framesPerPkt;
621          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_ENABLE;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = remoteAudioCoder_.vadEnable;
622          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 0;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = remoteAudioCoder_.coderPayloadType;
623          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = 0;          mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = remoteAudioCoder_.redPayloadType;
624          mediaCnt++;          mediaCnt++;
625    
626          /* remote audio ports and IP addresses          /* remote audio ports and IP addresses.
627           */           */
628          mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTP_INFO;          mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTP_INFO;
629          strcpy(mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,          copy_string_to_c_array(remote_rtp_audio.getAddress(),
630                 remote_rtp_audio.getAddress().c_str());                                 mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,
631                                   IP_ADDR_SIZE);
632          mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtp_audio.getPort();          mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtp_audio.getPort();
633          mediaCnt++;          mediaCnt++;
634    
635          mediaInfo.MediaData[mediaCnt].eMediaType =      MEDIATYPE_AUDIO_REMOTE_RTCP_INFO;          mediaInfo.MediaData[mediaCnt].eMediaType =      MEDIATYPE_AUDIO_REMOTE_RTCP_INFO;
636          strcpy(mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,          copy_string_to_c_array(remote_rtcp_audio.getAddress(),
637                 remote_rtcp_audio.getAddress().c_str());                                 mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,
638                                   IP_ADDR_SIZE);
639          mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtcp_audio.getPort();          mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtcp_audio.getPort();
640          mediaCnt++;          mediaCnt++;
641    
642            if ( remote_rtp_video.isValid() )
643            {
644                    /* local video.
645                     */
646                    mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_LOCAL_CODER_INFO;
647                    INIT_IPM_VIDEO_CODER_INFO(&mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo);
648                    mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.eCoderType = localVideoCoder_.coderType;
649                    mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.unCoderPayloadType = localVideoCoder_.coderPayloadType;
650    
651                    IPM_VIDEO_CODER_INFO_EX localVideoCoderInfoEx;
652                    INIT_IPM_VIDEO_CODER_INFO_EX(&localVideoCoderInfoEx);
653                    localVideoCoderInfoEx.eProfile = localVideoCoder_.profile;
654                    localVideoCoderInfoEx.eLevel = localVideoCoder_.level;
655                    localVideoCoderInfoEx.eImageWidth = localVideoCoder_.active_fmt.imageWidth;
656                    localVideoCoderInfoEx.eImageHeight = localVideoCoder_.active_fmt.imageHeight;
657                    localVideoCoderInfoEx.eFramesPerSec = localVideoCoder_.active_fmt.framesPerSec;
658                    localVideoCoderInfoEx.unBitRate = localVideoCoder_.bitRate;
659                    localVideoCoderInfoEx.eSamplingRate = localVideoCoder_.samplingRate;
660                    localVideoCoderInfoEx.unVisualConfigSize = 0;
661                    localVideoCoderInfoEx.szVisualConfiguration = NULL;
662                    mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.pExtraCoderInfo = &localVideoCoderInfoEx;
663                    //LOGINFO("IpmDevice::startMedia() Local VideoCoderInfo: " << std::endl << mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo);
664                    mediaCnt++;
665    
666                    /* remote video.
667                     */
668                    mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_REMOTE_CODER_INFO;
669                    INIT_IPM_VIDEO_CODER_INFO(&mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo);
670                    mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.eCoderType = remoteVideoCoder_.coderType;
671                    mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.unCoderPayloadType = remoteVideoCoder_.coderPayloadType;
672    
673                    IPM_VIDEO_CODER_INFO_EX remoteVideoCoderInfoEx;
674                    INIT_IPM_VIDEO_CODER_INFO_EX(&remoteVideoCoderInfoEx);
675                    remoteVideoCoderInfoEx.eProfile = remoteVideoCoder_.profile;
676                    remoteVideoCoderInfoEx.eLevel = remoteVideoCoder_.level;
677                    remoteVideoCoderInfoEx.eImageWidth = remoteVideoCoder_.active_fmt.imageWidth;
678                    remoteVideoCoderInfoEx.eImageHeight = remoteVideoCoder_.active_fmt.imageHeight;
679                    remoteVideoCoderInfoEx.eFramesPerSec = remoteVideoCoder_.active_fmt.framesPerSec;
680                    remoteVideoCoderInfoEx.unBitRate = remoteVideoCoder_.bitRate;
681                    remoteVideoCoderInfoEx.eSamplingRate = remoteVideoCoder_.samplingRate;
682                    remoteVideoCoderInfoEx.unVisualConfigSize = 0;
683                    remoteVideoCoderInfoEx.szVisualConfiguration = NULL;
684                    mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.pExtraCoderInfo = &remoteVideoCoderInfoEx;
685                    //LOGINFO("IpmDevice::startMedia() Remote VideoCoderInfo: " << std::endl << mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo);
686                    mediaCnt++;
687    
688                    /* remote video ports and IP addresses.
689                     */
690                    mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_REMOTE_RTP_INFO;
691                    copy_string_to_c_array(remote_rtp_video.getAddress(),
692                                           mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,
693                                           IP_ADDR_SIZE);
694                    mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtp_video.getPort();
695                    mediaCnt++;
696    
697                    mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_REMOTE_RTCP_INFO;
698                    copy_string_to_c_array(remote_rtcp_video.getAddress(),
699                                           mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,
700                                           IP_ADDR_SIZE);
701                    mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtcp_video.getPort();
702                    mediaCnt++;
703            }
704    
705            /* done.
706             */
707          mediaInfo.unCount = mediaCnt;          mediaInfo.unCount = mediaCnt;
708    
709          LOGDEBUG("IpmDevice::startMedia() starting RTP streaming on device: " <<          LOGDEBUG("IpmDevice::startMedia() starting audio on device: " <<
710                   devName_ << " to: " << remote_rtp_audio);                   getDeviceName() <<
711                     " remote_rtp: " << remote_rtp_audio <<
712                     " remote_rtcp: " << remote_rtcp_audio);
713    
714            if ( remote_rtp_video.isValid() )
715            {
716                    LOGDEBUG("IpmDevice::startMedia() starting video on device: " <<
717                             getDeviceName() <<
718                             " remote_rtp: " << remote_rtp_video <<
719                             " remote_rtcp: " << remote_rtcp_video);
720            }
721    
722          if ( ipm_StartMedia(devHandle_, &mediaInfo, DATA_IP_TDM_BIDIRECTIONAL, EV_ASYNC) == -1 )          if ( ipm_StartMedia(devHandle_, &mediaInfo, DATA_IP_TDM_BIDIRECTIONAL, EV_ASYNC) == -1 )
723          {          {
724                  LOGERROR("ipm_StartMedia failed for device: " << devName_ <<                  LOGERROR("ipm_StartMedia failed for device: " << getDeviceName() <<
725                           " with error: " << ATDV_ERRMSGP(devHandle_));                           " with error: " << ATDV_ERRMSGP(devHandle_));
726                  return false;                  return false;
727          }          }
728    
729          state_ = IPM_STARTING;          state_ = IPM_STARTING;
730            busy_ = true;
731    
732            return true;
733    }
734    
735    
736    /*
737     * Add the overlay to media stream.
738     */
739    bool IpmDevice::addOverlay( OverlayInfo* overlayInfo )
740    {
741            if ( busy_ )
742            {
743                    pending_.push(IpmCommand(IpmCommand::ADD_OVERLAY, overlayInfo));
744                    return true;
745            }
746    
747            if ( !overlay_ )
748            {
749                    overlay_ = new Overlay; /* will exist until this object is deleted */
750            }
751    
752            overlay_->createOverlay(*overlayInfo);
753            delete overlayInfo;
754    
755            if ( !overlay_->addOverlay(getDeviceHandle(), eSM_OVERLAY_DIRECTION_DEVICE) )
756            {
757                    LOGERROR("IpmDevice::addOverlay() failed for device: " << getDeviceName());
758                    return false;
759            }
760            LOGDEBUG("IpmDevice::addOverlay() for device: " << getDeviceName());
761            busy_ = true;
762            return true;
763    }
764    
765    
766    /*
767     * Add the overlay to media stream.
768     */
769    bool IpmDevice::removeOverlay()
770    {
771            if ( busy_ )
772            {
773                    pending_.push(IpmCommand(IpmCommand::REMOVE_OVERLAY));
774                    return true;
775            }
776    
777            if ( !overlay_ )
778            {
779                    return false;
780            }
781    
782            if ( !overlay_->removeOverlay(getDeviceHandle()) )
783            {
784                    LOGERROR("IpmDevice::removeOverlay() failed for device: " << getDeviceName());
785                    return false;
786            }
787            LOGDEBUG("IpmDevice::removeOverlay() for device: " << getDeviceName());
788            busy_ = true;
789    
790          return true;          return true;
791  }  }
792    
# Line 274  Line 807 
807                          break;                          break;
808    
809                  case IPMEV_GET_LOCAL_MEDIA_INFO:                  case IPMEV_GET_LOCAL_MEDIA_INFO:
810                          onLocalMediaInfo((IPM_MEDIA_INFO*)metaevent.evtdatap);                          onLocalMediaInfo(static_cast<IPM_MEDIA_INFO*>(sr_getevtdatap()));
811                          break;                          break;
812    
813                  case IPMEV_STARTMEDIA:                  case IPMEV_STARTMEDIA:
# Line 285  Line 818 
818                          onStopped ();                          onStopped ();
819                          break;                          break;
820    
821                    case IPMEV_LISTEN:
822                            onListen();
823                            break;
824    
825                    case IPMEV_UNLISTEN:
826                            onUnListen();
827                            break;
828    
829                  case IPMEV_ERROR:                  case IPMEV_ERROR:
830                          onError();                          onError();
831                          break;                          break;
832    
833                    case IPMEV_TELEPHONY_EVENT:
834                            onTelephonyEvent(static_cast<IPM_TELEPHONY_INFO*>(sr_getevtdatap()));
835                            break;
836    
837                  case DMEV_GET_TX_PORT_INFO:                  case DMEV_GET_TX_PORT_INFO:
838                          onGetTxPortInfo((DM_PORT_INFO_LIST*)metaevent.evtdatap);                          onGetTxPortInfo(static_cast<DM_PORT_INFO_LIST*>(sr_getevtdatap()));
839                          break;                          break;
840    
841                  case DMEV_GET_RX_PORT_INFO:                  case DMEV_GET_RX_PORT_INFO:
842                          onGetRxPortInfo((DM_PORT_INFO_LIST*)metaevent.evtdatap);                          onGetRxPortInfo(static_cast<DM_PORT_INFO_LIST*>(sr_getevtdatap()));
843                          break;                          break;
844    
845                  case DMEV_GET_TX_PORT_INFO_FAIL:                  case DMEV_GET_TX_PORT_INFO_FAIL:
# Line 309  Line 854 
854                          onPortConnect();                          onPortConnect();
855                          break;                          break;
856    
857                  default:                  case DMEV_PORT_CONNECT_FAIL:
858                          LOGWARN("IpmDevice::processEvent() unhandled event: 0x" <<                          onPortConnectFail();
859                                  std::hex << metaevent.evttype << " for device: " << devName_);                          break;
                         return false;  
         }  
         return true;  
 }  
860    
861                    case DMEV_PORT_DISCONNECT:
862                            onPortDisconnect();
863                            break;
864    
865  /*                  case DMEV_PORT_DISCONNECT_FAIL:
866   * Handler for IPMEV_OPEN events.                          LOGERROR("IpmDevice::processEvent() DMEV_PORT_DISCONNECT_FAIL device: " << getDeviceName());
867   */                          break;
 void IpmDevice::onOpen()  
 {  
         LOGDEBUG("IpmDevice::onOpen() device: " << devName_);  
868    
869                    case SMEV_ADD_OVERLAY:
870                            onAddOverlay();
871                            break;
872    
873                    case SMEV_ADD_OVERLAY_FAIL:
874                            onAddOverlayFail();
875                            break;
876    
877                    case SMEV_REMOVE_OVERLAY:
878                            onRemoveOverlay();
879                            break;
880    
881                    case SMEV_REMOVE_OVERLAY_FAIL:
882                            onRemoveOverlayFail();
883                            break;
884    
885                    case SMEV_ERROR:
886                            LOGERROR("IpmDevice::processEvent() SMEV_ERROR device: " << getDeviceName());
887                            break;
888    
889                    default:
890                            LOGWARN("IpmDevice::processEvent() unhandled event: 0x" <<
891                                    std::hex << metaevent.evttype << " for device: " << getDeviceName());
892                            return false;
893            }
894            return true;
895    }
896    
897    
898    /*
899     * Handler for IPMEV_OPEN events.
900     */
901    void IpmDevice::onOpen()
902    {
903            LOGINFO("IpmDevice::onOpen() device: " << getDeviceName());
904    
905            other_audio_ = 0;
906            other_video_ = 0;
907    
908            /* Get and save the transmit timeslot on CTBus.
909             */
910          SC_TSINFO tsinfo;          SC_TSINFO tsinfo;
911          tsinfo.sc_numts = 1;          tsinfo.sc_numts = 1;
912          tsinfo.sc_tsarrayp = getTimeslot();          tsinfo.sc_tsarrayp = getXmitTimeslotPtr();
913          if ( ipm_GetXmitSlot(devHandle_, &tsinfo, EV_SYNC) == -1 )          if ( ipm_GetXmitSlot(devHandle_, &tsinfo, EV_SYNC) == -1 )
914          {          {
915                  LOGERROR("ipm_GetXmitSlot() failed" );                  LOGERROR("ipm_GetXmitSlot() failed" );
916          }          }
917    
918            /* Enable dtmf events.
919             */
920            eIPM_EVENT event = EVT_RFC2833;
921            if ( ipm_EnableEvents(devHandle_, &event, 1, EV_ASYNC) < 0 )
922            {
923                    LOGERROR("ipm_EnableEvent() failed on device:" << devHandle_);
924            }
925    
926            /* Request port info.
927             */
928          if ( dev_GetTransmitPortInfo(devHandle_, this) == -1 )          if ( dev_GetTransmitPortInfo(devHandle_, this) == -1 )
929          {          {
930                  LOGERROR("dev_GetTransmitPortInfo() failed");                  LOGERROR("dev_GetTransmitPortInfo() failed");
# Line 342  Line 934 
934                  LOGERROR("dev_GetReceivePortInfo() failed");                  LOGERROR("dev_GetReceivePortInfo() failed");
935          }          }
936    
937          /* Request the local media information and save it in localMediaInfo_          /* Request the local media information.
938           */           */
939          localMediaInfo_.unCount = 3;          IPM_MEDIA_INFO media_info;
940          localMediaInfo_.MediaData[0].eMediaType = MEDIATYPE_AUDIO_LOCAL_RTP_INFO;          memset(&media_info, 0, sizeof(IPM_MEDIA_INFO));
941          localMediaInfo_.MediaData[1].eMediaType = MEDIATYPE_VIDEO_LOCAL_RTP_INFO;          media_info.unCount = 2;
942          localMediaInfo_.MediaData[2].eMediaType = MEDIATYPE_NBUP_LOCAL_RTP_INFO;          media_info.MediaData[0].eMediaType = MEDIATYPE_AUDIO_LOCAL_RTP_INFO;
943            media_info.MediaData[1].eMediaType = MEDIATYPE_VIDEO_LOCAL_RTP_INFO;
944    
945          if ( ipm_GetLocalMediaInfo (devHandle_, &localMediaInfo_, EV_ASYNC) == -1 )          if ( ipm_GetLocalMediaInfo(devHandle_, &media_info, EV_ASYNC) == -1 )
946          {          {
947                  LOGERROR("ipm_GetLocalMediaInfo() failed for device: " <<                  LOGERROR("ipm_GetLocalMediaInfo() failed for device: " <<
948                           devName_ << " with error: " << ATDV_LASTERR(devHandle_));                           getDeviceName() << " with error: " << ATDV_LASTERR(devHandle_));
949          }          }
950    
951          /* update init state          /* update init state.
952           */           */
953          state_ = IPM_INITIALIZATION_START;          state_ = IPM_INITIALIZATION_START;
954          initStepsRemaining_--;          initStepsRemaining_--;
# Line 369  Line 962 
962  /*  /*
963   * Handler for DMEV_GET_TX_PORT_INFO events.   * Handler for DMEV_GET_TX_PORT_INFO events.
964   */   */
965  void IpmDevice::onGetTxPortInfo( DM_PORT_INFO_LIST* portInfo )  void IpmDevice::onGetTxPortInfo( DM_PORT_INFO_LIST* portInfoList )
966    {
967            LOGINFO("IpmDevice::onGetTxPortInfo() device: " << getDeviceName());
968    
969            txPortInfoList_ = *portInfoList;
970            LOGDEBUG(std::endl << txPortInfoList_);
971    
972            for ( unsigned int i = 0; i < txPortInfoList_.unCount; i++ )
973  {  {
974          LOGDEBUG("IpmDevice::onGetTxPortInfo() device: " << devName_);                  switch ( txPortInfoList_.port_info[i].port_media_type )
975                    {
976                            case DM_PORT_MEDIA_TYPE_AUDIO:
977                                    audioPortTxInfo_ = txPortInfoList_.port_info[i];
978                                    break;
979    
980          memcpy(&txPortInfoList_, sr_getevtdatap(), sr_getevtlen());                          case DM_PORT_MEDIA_TYPE_VIDEO:
981                                    videoPortTxInfo_ = txPortInfoList_.port_info[i];
982                                    break;
983    
984          printPortInfo(portInfo);                          default:
985                                    break;
986                    }
987            }
988    
989          initStepsRemaining_--;          initStepsRemaining_--;
990          if ( initStepsRemaining_ == 0 )          if ( initStepsRemaining_ == 0 )
# Line 388  Line 997 
997  /*  /*
998   * Handler for DMEV_GET_RX_PORT_INFO events.   * Handler for DMEV_GET_RX_PORT_INFO events.
999   */   */
1000  void IpmDevice::onGetRxPortInfo( DM_PORT_INFO_LIST* portInfo )  void IpmDevice::onGetRxPortInfo( DM_PORT_INFO_LIST* portInfoList )
1001    {
1002            LOGINFO("IpmDevice::onGetRxPortInfo() device: " << getDeviceName());
1003    
1004            rxPortInfoList_ = *portInfoList;
1005            LOGDEBUG(std::endl << rxPortInfoList_);
1006    
1007            for ( unsigned int i = 0; i < rxPortInfoList_.unCount; i++ )
1008  {  {
1009          LOGDEBUG("IpmDevice::onGetRxPortInfo() device: " << devName_);                  switch ( rxPortInfoList_.port_info[i].port_media_type )
1010                    {
1011                            case DM_PORT_MEDIA_TYPE_AUDIO:
1012                                    audioPortRxInfo_ = rxPortInfoList_.port_info[i];
1013                                    break;
1014    
1015          memcpy(&rxPortInfoList_, sr_getevtdatap(), sr_getevtlen());                          case DM_PORT_MEDIA_TYPE_VIDEO:
1016                                    videoPortRxInfo_ =  rxPortInfoList_.port_info[i];
1017                                    break;
1018    
1019          printPortInfo(portInfo);                          default:
1020                                    break;
1021                    }
1022            }
1023    
1024          initStepsRemaining_--;          initStepsRemaining_--;
1025          if ( initStepsRemaining_ == 0 )          if ( initStepsRemaining_ == 0 )
# Line 405  Line 1030 
1030    
1031    
1032  /*  /*
  * Handler for DMEV_PORT_CONNECT events.  
  */  
 void IpmDevice::onPortConnect()  
 {  
         LOGDEBUG("IpmDevice::onPortConnect() device: " << devName_);  
 }  
   
   
 /*  
1033   * Handler for DMEV_GET_TX_PORT_INFO_FAIL and DMEV_GET_RX_PORT_INFO_FAIL   * Handler for DMEV_GET_TX_PORT_INFO_FAIL and DMEV_GET_RX_PORT_INFO_FAIL
1034   * events.   * events.
1035   */   */
1036  void IpmDevice::onPortGetFail()  void IpmDevice::onPortGetFail()
1037  {  {
1038          LOGERROR("IpmDevice::onPortGetFail() device: " << devName_);          LOGERROR("IpmDevice::onPortGetFail() device: " << getDeviceName());
1039    
1040          state_ = IPM_INVALID;          state_ = IPM_INVALID;  /* ideas? */
1041  }  }
1042    
1043    
# Line 430  Line 1046 
1046   */   */
1047  void IpmDevice::onError()  void IpmDevice::onError()
1048  {  {
1049          LOGERROR("IpmDevice::onError() device: " << devName_ <<          LOGERROR("IpmDevice::onError() device: " << getDeviceName() <<
1050                   " error: " << ATDV_ERRMSGP(devHandle_));                   " error: " << ATDV_ERRMSGP(devHandle_));
1051    
1052          state_ = IPM_INVALID;          state_ = IPM_INVALID;
1053    
1054            busy_ = false;
1055            processPendingCommand();
1056    }
1057    
1058    
1059    /*
1060     * Handler for IPMEV_TELEPHONY_EVENT events.
1061     */
1062    void IpmDevice::onTelephonyEvent( IPM_TELEPHONY_INFO* info )
1063    {
1064            LOGINFO("IpmDevice::processEvent() IPMEV_TELEPHONY_EVENT device: " << getDeviceName() );
1065            const std::string dtmf = "0123456789*#";
1066    
1067            switch ( info->eTelInfoType )
1068            {
1069                    case TEL_INFOTYPE_EVENT:
1070                    {
1071                            int event_id = info->TelephonyInfo.TelEvtInfo.eTelephonyEventID;
1072                            LOGDEBUG("TelephonyEventID: 0x" << std::hex << event_id);
1073                            if ( event_id >= 0 && event_id <= 11 )
1074                            {
1075                                    channelMgr_.onDtmf(ipt_, dtmf[event_id], 100); /* fake duration */
1076                            }
1077                            break;
1078                    }
1079    
1080                    default:
1081                            break;
1082    
1083            }
1084    }
1085    
1086    
1087    /*
1088     * Handler for IPMEV_GET_LOCAL_MEDIA_INFO events.
1089     */
1090    void IpmDevice::onLocalMediaInfo( IPM_MEDIA_INFO* mediaInfo )
1091    {
1092            LOGINFO("IpmDevice::onLocalMediaInfo() device: " << getDeviceName());
1093            LOGDEBUG(std::endl << *mediaInfo);
1094    
1095            for( unsigned int i = 0; i < mediaInfo->unCount; i++ )
1096            {
1097                    switch ( mediaInfo->MediaData[i].eMediaType )
1098                    {
1099                            case MEDIATYPE_AUDIO_LOCAL_RTP_INFO:
1100                                    localRtpAudio_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress);
1101                                    localRtpAudio_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId);
1102                                    break;
1103    
1104                            case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO:
1105                                    localRtcpAudio_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress);
1106                                    localRtcpAudio_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId);
1107                                    break;
1108    
1109                            case MEDIATYPE_VIDEO_LOCAL_RTP_INFO:
1110                                    localRtpVideo_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress);
1111                                    localRtpVideo_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId);
1112                                    break;
1113    
1114                            case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO:
1115                                    localRtcpVideo_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress);
1116                                    localRtcpVideo_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId);
1117                                    break;
1118    
1119                            default:
1120                                    break;
1121                    }
1122            }
1123  }  }
1124    
1125    
1126  /*  /*
1127   * Handler for IPMEV_EVENT_ENABLED events   * Handler for IPMEV_EVENT_ENABLED events.
1128   */   */
1129  void IpmDevice::onEventEnabled()  void IpmDevice::onEventEnabled()
1130  {  {
1131          LOGDEBUG("IpmDevice::onEventEnabled() device: " << devName_);          LOGINFO("IpmDevice::onEventEnabled() device: " << getDeviceName());
1132    
1133          initStepsRemaining_--;          initStepsRemaining_--;
1134          if ( initStepsRemaining_ == 0 )          if ( initStepsRemaining_ == 0 )
# Line 457  Line 1143 
1143   */   */
1144  void IpmDevice::onStartMedia()  void IpmDevice::onStartMedia()
1145  {  {
1146          LOGDEBUG("IpmDevice::onStartMedia() device: " << devName_);          LOGINFO("IpmDevice::onStartMedia() device: " << getDeviceName());
   
1147          state_ = IPM_STREAMING;          state_ = IPM_STREAMING;
1148            if ( ipt_ )
1149            {
1150                    ipt_->sendIFrameRequest();
1151            }
1152            busy_ = false;
1153            processPendingCommand();
1154  }  }
1155    
1156    
# Line 468  Line 1159 
1159   */   */
1160  void IpmDevice::onStopped()  void IpmDevice::onStopped()
1161  {  {
1162          LOGDEBUG("IpmDevice::onStopped() device: " << devName_);          LOGINFO("IpmDevice::onStopped() device: " << getDeviceName());
   
1163          state_ = IPM_IDLE;          state_ = IPM_IDLE;
1164            busy_ = false;
1165            processPendingCommand();
1166  }  }
1167    
1168    
1169  /*  /*
1170   * Handler for IPMEV_GET_LOCAL_MEDIA_INFO events.   * Handler for IPMEV_LISTEN events.
1171   */   */
1172  void IpmDevice::onLocalMediaInfo( IPM_MEDIA_INFO* mediaInfo )  void IpmDevice::onListen()
1173  {  {
1174          LOGDEBUG("IpmDevice::onLocalMediaInfo() device: " << devName_);          LOGINFO("IpmDevice::onListen() device: " << getDeviceName());
1175            busy_ = false;
1176          memcpy(&localMediaInfo_, mediaInfo, sizeof(IPM_MEDIA_INFO));          processPendingCommand();
         printMediaInfo(&localMediaInfo_);  
1177  }  }
1178    
1179    
1180    /*
1181     * Handler for IPMEV__UNLISTEN events.
1182     */
1183    void IpmDevice::onUnListen()
1184    {
1185            LOGINFO("IpmDevice::onUnListen() device: " << getDeviceName());
1186            busy_ = false;
1187            processPendingCommand();
1188    }
1189    
1190    
1191  /*  /*
1192   * Debug aid.   * Handler for DMEV_PORT_CONNECT events.
1193   */   */
1194  void IpmDevice::printPortInfo( DM_PORT_INFO_LIST* portInfo ) const  void IpmDevice::onPortConnect()
1195  {  {
1196          std::stringstream ss;          LOGINFO("IpmDevice::onPortConnect() device: " << getDeviceName());
1197            busy_ = false;
1198            processPendingCommand();
1199    }
1200    
1201    
1202          for ( unsigned int i = 0; i < portInfo->unCount; i++ )  /*
1203     * Handler for DMEV_PORT_CONNECT_FAIL events.
1204     */
1205    void IpmDevice::onPortConnectFail()
1206          {          {
1207                  DM_PORT_INFO& info = portInfo->port_info[i];          LOGERROR("IpmDevice::onPortConnectFail() device: " << getDeviceName());
1208                  ss << "Port: " << i << " MediaType: " << info.port_media_type;          busy_ = false;
1209                  if ( info.port_media_type == DM_PORT_MEDIA_TYPE_AUDIO )          processPendingCommand();
1210    }
1211    
1212    
1213    /*
1214     * Handler for DMEV_PORT_DISCONNECT events.
1215     */
1216    void IpmDevice::onPortDisconnect()
1217                  {                  {
1218                          ss << "Audio";          LOGINFO("IpmDevice::onPortDisconnect() device: " << getDeviceName());
1219            busy_ = false;
1220            processPendingCommand();
1221                  }                  }
1222                  else if ( info.port_media_type == DM_PORT_MEDIA_TYPE_VIDEO )  
1223    
1224    /*
1225     * Handler for SMEV_ADD_OVERLAY events.
1226     */
1227    void IpmDevice::onAddOverlay()
1228    {
1229            LOGINFO("IpmDevice::onOverlayAdd() device: " << getDeviceName());
1230    
1231            if ( overlay_ )
1232                  {                  {
1233                          ss << "Video";                  void* evtContext = sr_getUserContext();
1234                    void* evtData = sr_getevtdatap();
1235                    overlay_->onOverlayAdd(evtData, evtContext);
1236            }
1237            busy_ = false;
1238            processPendingCommand();
1239                  }                  }
1240                  else if ( info.port_media_type == DM_PORT_MEDIA_TYPE_NBUP )  
1241    
1242    /*
1243     * Handler for SMEV_ADD_OVERLAY_FAIL events.
1244     */
1245    void IpmDevice::onAddOverlayFail()
1246                  {                  {
1247                          ss << "NBUP";          LOGERROR("IpmDevice::onAddOverlayFail() device: " << getDeviceName());
1248            busy_ = false;
1249            processPendingCommand();
1250                  }                  }
1251                  else  
1252    
1253    /*
1254     * Handler for SMEV_REMOVE_OVERLAY events.
1255     */
1256    void IpmDevice::onRemoveOverlay()
1257    {
1258            LOGINFO("IpmDevice::onRemoveOverlay() device: " << getDeviceName());
1259    
1260            if ( overlay_ )
1261                  {                  {
1262                          ss << info.port_media_type;                  void* evtContext = sr_getUserContext();
1263                    void* evtData = sr_getevtdatap();
1264                    overlay_->onOverlayRemove(evtData, evtContext);
1265                  }                  }
1266            busy_ = false;
1267            processPendingCommand();
1268          }          }
1269          LOGDEBUG(ss.str());  
1270    
1271    /*
1272     * Handler for SMEV_REMOVE_OVERLAY_FAIL events.
1273     */
1274    void IpmDevice::onRemoveOverlayFail()
1275    {
1276            LOGERROR("IpmDevice::onRemoveOverlayFail() device: " << getDeviceName());
1277            busy_ = false;
1278            processPendingCommand();
1279  }  }
1280    
1281    
1282  /*  /*
1283   * Debug aid   * Set the dtmf signalling mode.
1284     * XXX add support for SIP INFO (need to process message body ourselves).
1285   */   */
1286  void IpmDevice::printMediaInfo( IPM_MEDIA_INFO* mediaInfo ) const  void IpmDevice::setDtmfMode( DtmfMode dtmf_mode )
1287  {  {
1288          std::stringstream ss;          IPM_PARM_INFO parmInfo;
1289          for ( unsigned int i = 0; i < mediaInfo->unCount; i++ )  
1290            switch ( dtmf_mode )
1291          {          {
1292                  ss << "MediaType = ";                  case DTMF_RFC2833:
                 switch ( mediaInfo->MediaData[i].eMediaType )  
1293                  {                  {
1294                          case MEDIATYPE_VIDEO_LOCAL_RTP_INFO:                                  eIPM_DTMFXFERMODE value = DTMFXFERMODE_RFC2833;
1295                                  ss << "MEDIATYPE_VIDEO_LOCAL_RTP_INFO";                                  parmInfo.eParm = PARMCH_DTMFXFERMODE;
1296                                    parmInfo.pvParmValue = &value;
1297                                    LOGDEBUG("IpmDevice::setDtmfMode() using RFC2833");
1298                                    if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 )
1299                                    {
1300                                            LOGERROR("ipm_SetParm() DTMFXFERMODE_RFC2833");
1301                                    }
1302    
1303                                    parmInfo.eParm = PARMCH_RFC2833EVT_TX_PLT;
1304                                    parmInfo.pvParmValue = &rfc2833_payload_type_;
1305                                    if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 )
1306                                    {
1307                                            LOGERROR("ipm_SetParm() PARMCH_RFC2833EVT_TX_PLT " << rfc2833_payload_type_);
1308                                    }
1309    
1310                                    parmInfo.eParm = PARMCH_RFC2833EVT_RX_PLT;
1311                                    parmInfo.pvParmValue = &rfc2833_payload_type_;
1312                                    if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 )
1313                                    {
1314                                            LOGERROR("ipm_SetParm() PARMCH_RFC2833EVT_RX_PLT " << rfc2833_payload_type_);
1315                                    }
1316                            }
1317                                  break;                                  break;
1318    
1319                          case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO:                  case DTMF_INBAND:
1320                                  ss << "MEDIATYPE_VIDEO_LOCAL_RTCP_INFO";                          {
1321                                    eIPM_DTMFXFERMODE value = DTMFXFERMODE_INBAND;
1322                                    parmInfo.eParm = PARMCH_DTMFXFERMODE;
1323                                    parmInfo.pvParmValue = &value;
1324    
1325                                    LOGDEBUG("IpmDevice::setDtmfMode() using inband audio");
1326                                    if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 )
1327                                    {
1328                                            LOGERROR("ipm_SetParm() DTMFXFERMODE_INBAND");
1329                                    }
1330                            }
1331                                  break;                                  break;
1332            }
1333    }
1334    
1335                          case MEDIATYPE_AUDIO_LOCAL_RTP_INFO:  
1336                                  ss << "MEDIATYPE_AUDIO_LOCAL_RTP_INFO";  /*
1337     * Convert a minimum-picture-interval to frames-per-second.
1338     * RFC4629: fps = 30 / (1.001 * the specified value).
1339     */
1340    int IpmDevice::mpi2fps( int mpi )
1341    {
1342            int fps;
1343            switch ( mpi )
1344            {
1345                    case 1:
1346                            fps = VIDEO_FRAMESPERSEC_2997;
1347                                  break;                                  break;
1348    
1349                          case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO:                  case 2:
1350                                  ss << "MEDIATYPE_AUDIO_LOCAL_RTCP_INFO";                          fps = VIDEO_FRAMESPERSEC_15;
1351                            break;
1352    
1353                    case 3:
1354                            fps = VIDEO_FRAMESPERSEC_10;
1355                                  break;                                  break;
1356    
1357                          case MEDIATYPE_NBUP_LOCAL_RTP_INFO:                  case 5:
1358                                  ss << "MEDIATYPE_NBUP_LOCAL_RTP_INFO";                          fps = VIDEO_FRAMESPERSEC_6;
1359                                  break;                                  break;
1360    
1361                          default:                          default:
1362                                  ss << "MEDIATYPE_??? " << mediaInfo->MediaData[i].eMediaType;                          fps = VIDEO_FRAMESPERSEC_DEFAULT;
1363                            break;
1364            }
1365            return fps;
1366    }
1367    
1368    
1369    /*
1370     * Convert frames-per-second to a minimum-picture-interval.
1371     * RFC4629: fps = 30 / (1.001 * the specified value).
1372     */
1373    int IpmDevice::fps2mpi( eVIDEO_FRAMESPERSEC fps )
1374    {
1375            int mpi;
1376            switch ( fps )
1377            {
1378                    case VIDEO_FRAMESPERSEC_6:
1379                            mpi = 5;
1380                            break;
1381    
1382                    case  VIDEO_FRAMESPERSEC_10:
1383                            mpi = 3;
1384                            break;
1385    
1386                    case VIDEO_FRAMESPERSEC_2997:
1387                    case VIDEO_FRAMESPERSEC_30:
1388                            mpi = 1;
1389                            break;
1390    
1391                    default:  /* 15 fps */
1392                            mpi = 2;
1393                                  break;                                  break;
1394                  }                  }
1395                  ss << " IP = " << mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress;          return mpi;
1396                  ss << " Port = " << mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId;  }
1397                  ss << std::endl;  
1398    
1399    /*
1400     * offer sdpS contain all available codecs.
1401     */
1402    void IpmDevice::buildOfferSdp( SdpSessionDescription& sdp )
1403    {
1404            /* get here so it can be used for the origin address */
1405            IpInfo local_audio_rtp;
1406            getLocalMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, local_audio_rtp);
1407    
1408            sdp.version()->setVersion("0");
1409    
1410            sdp.origin()->setUserName("DiaStarServer");
1411            sdp.origin()->setNetworkType("IN");
1412            sdp.origin()->setAddressType("IP4");
1413            sdp.origin()->setAddress(local_audio_rtp.getAddress().c_str());
1414    
1415            /* use a common c= for all media */
1416            sdp.connection()->setNetworkType("IN");
1417            sdp.connection()->setAddressType("IP4");
1418            sdp.connection()->setAddress(local_audio_rtp.getAddress().c_str());
1419    
1420            time_t t;
1421            time(&t);
1422            std::stringstream sessionIdandVersion;
1423            sessionIdandVersion << t;
1424            sdp.origin()->setSessionId(sessionIdandVersion.str().c_str());
1425            sdp.origin()->setVersion(sessionIdandVersion.str().c_str());
1426    
1427            sdp.sessionName()->setName("DiaStarServer");
1428    
1429            SdpTimeDescription* timeDescription = sdp.timeDescriptionList()->addItem();
1430            timeDescription->time()->setStart(0);
1431            timeDescription->time()->setStop(0);
1432    
1433            /* media
1434             */
1435            SdpMediaDescriptionList* mdList = sdp.mediaDescriptionList();
1436            mdList->clear();
1437    
1438            /* m=audio
1439             */
1440            const Coders::audio_coders_t&  audioCoders = channelMgr_.getAudioCoders();
1441            if ( audioCoders.size() > 0 )
1442            {
1443                    SdpMediaDescription* audioMD = mdList->addItem();
1444                    SdpMedia* audioMedia = audioMD->media();
1445                    audioMedia->setMedia("audio");
1446                    audioMedia->setPort(local_audio_rtp.getPort());
1447                    audioMedia->setTransport("RTP/AVP");
1448                    audioMedia->setNumPorts(1);
1449    
1450                    SdpAttributeList* audioAttrList = audioMD->attributeList();
1451                    SdpAttribute* audioAttribute;
1452    
1453                    Coders::audio_coders_t::const_iterator i;
1454                    for ( i = audioCoders.begin(); i != audioCoders.end(); ++i )
1455                    {
1456                            const AudioCoderInfo& audio_coder_info = *i;
1457    
1458                            if ( audio_coder_info.coderType == CODER_TYPE_G711ULAW64K )
1459                            {
1460                                    audioMedia->addFormat("0");
1461                                    audioAttribute = audioAttrList->addItem();
1462                                    audioAttribute->setProperty("rtpmap");
1463                                    audioAttribute->setPropertyValue("0 PCMU/8000");
1464                            }
1465                            else if ( audio_coder_info.coderType == CODER_TYPE_G711ALAW64K )
1466                            {
1467                                    audioMedia->addFormat("8");
1468                                    audioAttribute = audioAttrList->addItem();
1469                                    audioAttribute->setProperty("rtpmap");
1470                                    audioAttribute->setPropertyValue("8 PCMA/8000");
1471                            }
1472                            else
1473                            {
1474                                    /* more */
1475                            }
1476                    }
1477                    if ( dtmf_mode_ == DTMF_RFC2833 )
1478                    {
1479                            rfc2833_payload_type_ = 101;
1480    
1481                            std::stringstream payload;
1482                            payload << rfc2833_payload_type_;
1483                            audioMedia->addFormat(payload.str().c_str());
1484    
1485                            audioAttribute = audioAttrList->addItem();
1486                            audioAttribute->setProperty("rtpmap");
1487                            std::string rtpmap = payload.str() + " telephone-event/8000";
1488                            audioAttribute->setPropertyValue(rtpmap.c_str());
1489                    }
1490    
1491                    audioAttribute = audioAttrList->addItem();
1492                    audioAttribute->setProperty("sendrecv");
1493                    audioAttribute->setPropertyValue("");
1494            }
1495    
1496            /* m=video
1497             */
1498            const Coders::video_coders_t& videoCoders = channelMgr_.getVideoCoders();
1499            if ( videoCoders.size() > 0 )
1500            {
1501                    IpInfo local_video_rtp;
1502                    if ( getLocalMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, local_video_rtp) )
1503                    {
1504                            SdpMediaDescription* videoMD = mdList->addItem();
1505                            SdpMedia* videoMedia = videoMD->media();
1506                            videoMedia->setMedia("video");
1507                            videoMedia->setPort(local_video_rtp.getPort());
1508                            videoMedia->setTransport("RTP/AVP");
1509                            videoMedia->setNumPorts(1);
1510    
1511                            SdpAttributeList* videoAttrList = videoMD->attributeList();
1512                            SdpAttribute* videoAttribute;
1513    
1514                            Coders::video_coders_t::const_iterator j;
1515                            for ( j = videoCoders.begin(); j != videoCoders.end(); ++j )
1516                            {
1517                                    const VideoCoderInfo& video_coder_info = *j;
1518    
1519                                    if ( (video_coder_info.coderType == CODER_TYPE_H263) ||
1520                                         (video_coder_info.coderType == CODER_TYPE_H263_1998) )
1521                                    {
1522                                            std::stringstream payload;
1523                                            payload.str("");
1524                                            payload << video_coder_info.coderPayloadType;
1525                                            videoMedia->addFormat(payload.str().c_str());
1526    
1527                                            videoAttribute = videoAttrList->addItem();
1528                                            std::stringstream rtpmap;
1529                                            rtpmap.str("");
1530                                            rtpmap << video_coder_info.coderPayloadType << " ";
1531                                            rtpmap << video_coder_info.encoding << '/' << 90000;
1532                                            videoAttribute->setProperty("rtpmap");
1533                                            videoAttribute->setPropertyValue(rtpmap.str().c_str());
1534    
1535                                            videoAttribute = videoAttrList->addItem();
1536                                            videoAttribute->setProperty("fmtp");
1537                                            std::stringstream fmtp;
1538                                            fmtp.str("");
1539                                            fmtp << video_coder_info.coderPayloadType << " ";
1540                                            std::vector<VideoCoderInfo::Fmt>::const_iterator k = video_coder_info.available_fmts.begin();
1541                                            while ( k != video_coder_info.available_fmts.end() )
1542                                            {
1543                                                    if ( ((*k).imageWidth == VIDEO_IMAGE_WIDTH_352) &&
1544                                                         ((*k).imageHeight == VIDEO_IMAGE_HEIGHT_288) )
1545                                                    {
1546                                                            fmtp << "CIF=";
1547                                                    }
1548                                                    else if ( ((*k).imageWidth == VIDEO_IMAGE_WIDTH_176) &&
1549                                                              ((*k).imageHeight == VIDEO_IMAGE_HEIGHT_144) )
1550                                                    {
1551                                                            fmtp << "QCIF=";
1552                                                    }
1553                                                    else
1554                                                    {
1555                                                            ;
1556                                                    }
1557                                                    fmtp << fps2mpi((*k).framesPerSec);
1558                                                    if ( ++k != video_coder_info.available_fmts.end() )
1559                                                    {
1560                                                            fmtp << ';';
1561          }          }
         LOGDEBUG(ss.str());  
1562  }  }
1563                                            videoAttribute->setPropertyValue(fmtp.str().c_str());
1564                                    }
1565                                    else if ( video_coder_info.coderType == CODER_TYPE_MP4V_ES )
1566                                    {
1567                                            std::stringstream payload;
1568                                            payload << video_coder_info.coderPayloadType;
1569                                            videoMedia->addFormat(payload.str().c_str());
1570    
1571                                            videoAttribute = videoAttrList->addItem();
1572                                            std::stringstream rtpmap;
1573                                            rtpmap << video_coder_info.coderPayloadType << " ";
1574                                            rtpmap << video_coder_info.encoding << '/' << 90000;
1575                                            SdpAttributeList* videoAttrList = videoMD->attributeList();
1576                                            SdpAttribute* videoAttribute = videoAttrList->addItem();
1577                                            videoAttribute->setProperty("rtpmap");
1578                                            videoAttribute->setPropertyValue(rtpmap.str().c_str());
1579    
1580                                            videoAttribute = videoAttrList->addItem();
1581                                            videoAttribute->setProperty("fmtp");
1582                                            std::stringstream fmtp;
1583                                            fmtp.str("");
1584                                            fmtp << video_coder_info.coderPayloadType << " ";
1585                                            std::vector<VideoCoderInfo::Fmt>::const_iterator k = video_coder_info.available_fmts.begin();
1586                                            while ( k != video_coder_info.available_fmts.end() )
1587                                            {
1588                                                    if ( (*k).profile == VIDEO_PROFILE_LEVEL_SP0_MPEG4 )
1589                                                    {
1590                                                            fmtp << "profile-level-id=0";
1591                                                    }
1592                                                    else if ( (*k).profile == VIDEO_PROFILE_LEVEL_SP1_MPEG4 )
1593                                                    {
1594                                                            fmtp << "profile-level-id=1";
1595                                                    }
1596                                                    else if ( (*k).profile == VIDEO_PROFILE_LEVEL_SP2_MPEG4 )
1597                                                    {
1598                                                            fmtp << "profile-level-id=2";
1599                                                    }
1600                                                    else if ( (*k).profile == VIDEO_PROFILE_LEVEL_SP3_MPEG4 )
1601                                                    {
1602                                                            fmtp << "profile-level-id=3";
1603                                                    }
1604                                                    if ( ++k != video_coder_info.available_fmts.end() )
1605                                                    {
1606                                                            fmtp << ';';
1607                                                    }
1608                                            }
1609                                            videoAttribute->setPropertyValue(fmtp.str().c_str());
1610                                    }
1611                            }
1612    
1613                            videoAttribute = videoAttrList->addItem();
1614                            videoAttribute->setProperty("sendrecv");
1615                            videoAttribute->setPropertyValue("");
1616    
1617                            std::stringstream bandwidth;
1618                            bandwidth << 384;
1619                            videoMD->bandwidth()->setModifier("AS");
1620                            videoMD->bandwidth()->setBandwidthValue(bandwidth.str().c_str());
1621                    }
1622            }
1623    }
1624    
1625    
1626    /*
1627     * Answer sdpS return all 'm' (media) headers that were 'offered'.
1628     * Unused/unsupported ones have their port set to 0.
1629     */
1630    void IpmDevice::buildAnswerSdp( SdpSessionDescription& sdp )
1631    {
1632            /* get here so it can be used for the origin address */
1633            IpInfo local_audio_rtp;
1634            getLocalMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, local_audio_rtp);
1635    
1636            sdp.version()->setVersion("0");
1637    
1638            sdp.origin()->setUserName("DiaStarServer");
1639            sdp.origin()->setNetworkType("IN");
1640            sdp.origin()->setAddressType("IP4");
1641            sdp.origin()->setAddress(local_audio_rtp.getAddress().c_str());
1642    
1643            /* use a common c= for all media */
1644            sdp.connection()->setNetworkType("IN");
1645            sdp.connection()->setAddressType("IP4");
1646            sdp.connection()->setAddress(local_audio_rtp.getAddress().c_str());
1647    
1648            time_t t;
1649            time(&t);
1650            std::stringstream sessionIdandVersion;
1651            sessionIdandVersion << t;
1652            sdp.origin()->setSessionId(sessionIdandVersion.str().c_str());
1653            sdp.origin()->setVersion(sessionIdandVersion.str().c_str());
1654    
1655            sdp.sessionName()->setName("DiaStarServer");
1656    
1657            SdpTimeDescription* timeDescription = sdp.timeDescriptionList()->addItem();
1658            timeDescription->time()->setStart(0);
1659            timeDescription->time()->setStop(0);
1660    
1661            /*
1662             * media
1663             */
1664            SdpMediaDescriptionList* mdList = sdp.mediaDescriptionList();
1665            mdList->clear();
1666    
1667            /* m=audio
1668             */
1669            SdpMediaDescription* audioMD = mdList->addItem();
1670            SdpMedia* audioMedia = audioMD->media();
1671            audioMedia->setMedia("audio");
1672            audioMedia->setPort(local_audio_rtp.getPort());
1673            audioMedia->setTransport("RTP/AVP");
1674            audioMedia->setNumPorts(1);
1675    
1676            unsigned int accepted = 0;
1677            RemoteMedia::audio_t::const_iterator i;
1678            for ( i = offered_media_.audio.begin(); i != offered_media_.audio.end(); ++i )
1679            {
1680                    /* chosen codec.
1681                     */
1682                    if ( (*i).coder == remoteAudioCoder_ )
1683                    {
1684                            SdpAttributeList* audioAttrList = audioMD->attributeList();
1685                            SdpAttribute* audioAttribute = audioAttrList->addItem();
1686                            audioAttribute->setProperty("rtpmap");
1687    
1688                            if ( remoteAudioCoder_.coderType == CODER_TYPE_G711ULAW64K )
1689                            {
1690                                    audioMedia->addFormat("0");
1691                                    audioAttribute->setPropertyValue("0 PCMU/8000");
1692                            }
1693                            else if ( remoteAudioCoder_.coderType == CODER_TYPE_G711ALAW64K )
1694                            {
1695                                    audioMedia->addFormat("8");
1696                                    audioAttribute->setPropertyValue("8 PCMA/8000");
1697                            }
1698                            else
1699                            {
1700                                    ;
1701                            }
1702                            audioAttribute = audioAttrList->addItem();
1703                            audioAttribute->setProperty((*i).direction.c_str());
1704                            audioAttribute->setPropertyValue("");
1705    
1706                            accepted++;
1707                    }
1708    
1709                    if ( (*i).rfc2833 && (dtmf_mode_ == DTMF_RFC2833) )
1710                    {
1711                            /* save the offered payload type as it may differ from the local default. */
1712                            rfc2833_payload_type_ = (*i).coder.coderPayloadType;
1713    
1714                            std::stringstream payload;
1715                            payload << rfc2833_payload_type_;
1716                            audioMedia->addFormat(payload.str().c_str());
1717    
1718                            SdpAttributeList* audioAttrList = audioMD->attributeList();
1719                            SdpAttribute* audioAttribute = audioAttrList->addItem();
1720                            audioAttribute->setProperty("rtpmap");
1721                            std::string rtpmap = payload.str() + " telephone-event/8000";
1722                            audioAttribute->setPropertyValue(rtpmap.c_str());
1723    
1724                            accepted++;
1725                    }
1726            }
1727    
1728            /* rejected media, send m= with port set to zero.
1729             */
1730            if  ( (i == offered_media_.audio.end()) || (offered_media_.audio.size() > accepted) )
1731            {
1732                    SdpMediaDescription* audioMD = mdList->addItem();
1733                    SdpMedia* audioMedia = audioMD->media();
1734                    audioMedia->setMedia("audio");
1735                    audioMedia->setPort(0);               /* important! */
1736                    audioMedia->setTransport("RTP/AVP");
1737                    audioMedia->setNumPorts(1);
1738    
1739                    for ( i = offered_media_.audio.begin(); i != offered_media_.audio.end(); ++i )
1740                    {
1741                            if ( ((*i).coder != remoteAudioCoder_ ) &&
1742                                 !((*i).rfc2833 && (dtmf_mode_ == DTMF_RFC2833)) )
1743                            {
1744                                    std::stringstream payload;
1745                                    payload << (*i).coder.coderPayloadType;
1746                                    audioMedia->addFormat(payload.str().c_str());
1747                                    payload.str("");
1748                            }
1749                    }
1750            }
1751    
1752            /* m=video
1753             */
1754            IpInfo local_video_rtp;
1755            getLocalMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, local_video_rtp);
1756    
1757            RemoteMedia::video_t::const_iterator j;
1758            for ( j = offered_media_.video.begin(); j != offered_media_.video.end(); ++j )
1759            {
1760                    /* chosen codec.
1761                     */
1762                    if ( (*j).coder == remoteVideoCoder_ )
1763                    {
1764                            SdpMediaDescription* videoMD = mdList->addItem();
1765                            SdpMedia* videoMedia = videoMD->media();
1766                            videoMedia->setMedia("video");
1767                            videoMedia->setPort(local_video_rtp.getPort());
1768                            videoMedia->setTransport("RTP/AVP");
1769                            videoMedia->setNumPorts(1);
1770    
1771                            if ( (remoteVideoCoder_.coderType == CODER_TYPE_H263) ||
1772                                     (remoteVideoCoder_.coderType == CODER_TYPE_H263_1998) )
1773                            {
1774                                    std::stringstream payload;
1775                                    payload << remoteVideoCoder_.coderPayloadType;
1776                                    videoMedia->addFormat(payload.str().c_str());
1777    
1778                                    std::stringstream rtpmap;
1779                                    rtpmap << remoteVideoCoder_.coderPayloadType << " ";
1780                                    rtpmap << remoteVideoCoder_.encoding << '/' << 90000;
1781                                    SdpAttributeList* videoAttrList = videoMD->attributeList();
1782                                    SdpAttribute* videoAttribute = videoAttrList->addItem();
1783                                    videoAttribute->setProperty("rtpmap");
1784                                    videoAttribute->setPropertyValue(rtpmap.str().c_str());
1785    
1786                                    videoAttribute = videoAttrList->addItem();
1787                                    videoAttribute->setProperty("fmtp");
1788                                    std::stringstream fmtp;
1789                                    fmtp << remoteVideoCoder_.coderPayloadType << " " << remoteVideoCoder_.active_fmt.fmtpName;
1790                                    videoAttribute->setPropertyValue(fmtp.str().c_str());
1791    
1792                                    videoAttribute = videoAttrList->addItem();
1793                                    videoAttribute->setProperty((*j).direction.c_str());
1794                                    videoAttribute->setPropertyValue("");
1795    
1796                                    std::stringstream bandwidth;
1797                                    bandwidth << 384;
1798                                    videoMD->bandwidth()->setModifier("AS");
1799                                    videoMD->bandwidth()->setBandwidthValue(bandwidth.str().c_str());
1800                            }
1801                            else if ( remoteVideoCoder_.coderType == CODER_TYPE_MP4V_ES )
1802                            {
1803                                    std::stringstream payload;
1804                                    payload << remoteVideoCoder_.coderPayloadType;
1805                                    videoMedia->addFormat(payload.str().c_str());
1806    
1807                                    std::stringstream rtpmap;
1808                                    rtpmap << remoteVideoCoder_.coderPayloadType << " ";
1809                                    rtpmap << remoteVideoCoder_.encoding << '/' << 90000;
1810                                    SdpAttributeList* videoAttrList = videoMD->attributeList();
1811                                    SdpAttribute* videoAttribute = videoAttrList->addItem();
1812                                    videoAttribute->setProperty("rtpmap");
1813                                    videoAttribute->setPropertyValue(rtpmap.str().c_str());
1814    
1815                                    videoAttribute = videoAttrList->addItem();
1816                                    videoAttribute->setProperty("fmtp");
1817                                    std::stringstream fmtp;
1818                                    fmtp << remoteVideoCoder_.coderPayloadType << " " << remoteVideoCoder_.active_fmt.fmtpName;
1819                                    videoAttribute->setPropertyValue(fmtp.str().c_str());
1820    
1821                                    videoAttribute = videoAttrList->addItem();
1822                                    videoAttribute->setProperty((*j).direction.c_str());
1823                                    videoAttribute->setPropertyValue("");
1824    
1825                                    std::stringstream bandwidth;
1826                                    bandwidth << 384;
1827                                    videoMD->bandwidth()->setModifier("AS");
1828                                    videoMD->bandwidth()->setBandwidthValue(bandwidth.str().c_str());
1829                            }
1830                            else
1831                            {
1832                                    /* more coders */
1833                            }
1834                            break;
1835                    }
1836            }
1837            /* rejected media, send m= with port set to zero.
1838             */
1839            if  ( ((j == offered_media_.video.end()) && (offered_media_.video.size() > 0)) ||
1840                  (offered_media_.video.size() > 1) )
1841            {
1842                    SdpMediaDescription* videoMD = mdList->addItem();
1843                    SdpMedia* videoMedia = videoMD->media();
1844                    videoMedia->setMedia("video");
1845                    videoMedia->setPort(0);               /* important! */
1846                    videoMedia->setTransport("RTP/AVP");
1847                    videoMedia->setNumPorts(1);
1848    
1849                    for ( j = offered_media_.video.begin(); j != offered_media_.video.end(); ++j )
1850                    {
1851                            if ( (*j).coder != remoteVideoCoder_ )
1852                            {
1853                                    std::stringstream payload;
1854                                    payload << (*j).coder.coderPayloadType;
1855                                    videoMedia->addFormat(payload.str().c_str());
1856                                    payload.str("");
1857                            }
1858                    }
1859            }
1860    }
1861    
1862    
1863    /*
1864     * Extract the media details from the sdp and choose a coder from those offered.
1865     */
1866    void IpmDevice::onSdp( SdpSessionDescription& sdp )
1867    {
1868            parseSdp(sdp);  /* parses the sdp into offered_media_ */
1869    
1870            setRemoteMediaInfo(MEDIATYPE_AUDIO_REMOTE_RTP_INFO, IpInfo());  /* clear */
1871    
1872            const Coders::audio_coders_t&  audioCoders = channelMgr_.getAudioCoders();
1873            Coders::audio_coders_t::const_iterator i;
1874            for ( i = audioCoders.begin(); i != audioCoders.end(); ++i )
1875            {
1876                    RemoteMedia::audio_t::const_iterator j;
1877                    for ( j = offered_media_.audio.begin(); j != offered_media_.audio.end(); ++j )
1878                    {
1879                            if ( *i == (*j).coder )
1880                            {
1881                                    remoteAudioCoder_ = (*j).coder;
1882                                    setRemoteMediaInfo(MEDIATYPE_AUDIO_REMOTE_RTP_INFO, (*j).rtp);
1883                                    LOGDEBUG("IpmDevice::onSdp() chose: \"" << remoteAudioCoder_.encoding << "\" for audio");
1884    
1885                                    /* the remoteAudioCoder_ preserves the encoding name from the
1886                                     * remote party, which may differ from the name defined in the
1887                                     * master coder set. The localAudioCoder_ uses the internal
1888                                     * encoding name to allow it to be safely compared.
1889                                     */
1890                                    localAudioCoder_ = *i;
1891                                    break;
1892                            }
1893                    }
1894                    if ( j != offered_media_.audio.end() )
1895                    {
1896                            break;
1897                    }
1898            }
1899    
1900            setRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, IpInfo());  /* clear */
1901    
1902            const Coders::video_coders_t&  videoCoders = channelMgr_.getVideoCoders();
1903            Coders::video_coders_t::const_iterator k;
1904            for ( k = videoCoders.begin(); k != videoCoders.end(); ++k )
1905            {
1906                    RemoteMedia::video_t::const_iterator l;
1907                    for ( l = offered_media_.video.begin(); l != offered_media_.video.end(); ++l )
1908                    {
1909                            if ( *k == (*l).coder )
1910                            {
1911                                    remoteVideoCoder_ = (*l).coder;
1912                                    /* use the first fmt offered, there is always at least one */
1913                                    remoteVideoCoder_.active_fmt = (*l).coder.available_fmts[0];
1914                                    setRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, (*l).rtp);
1915                                    LOGDEBUG("IpmDevice::onSdp() chose: \"" << remoteVideoCoder_.encoding << "\" for video");
1916    
1917                                    /* the remoteVideoCoder_ preserves the encoding name from the
1918                                     * remote party, which may differ from the name defined in the
1919                                     * master coder set. The localVideoCoder_ uses the internal
1920                                     * encoding name to allow it to be safely compared.
1921                                     */
1922                                    localVideoCoder_ = *k;
1923                                    localVideoCoder_.active_fmt = remoteVideoCoder_.active_fmt;
1924                                    break;
1925                            }
1926                    }
1927                    if ( l != offered_media_.video.end() )
1928                    {
1929                            break;
1930                    }
1931            }
1932    }
1933    
1934    
1935    /*
1936     * Extract media details from an sdp.
1937     */
1938    void IpmDevice::parseSdp( SdpSessionDescription& sdp )
1939    {
1940            offered_media_.audio.clear();
1941            offered_media_.video.clear();
1942    
1943            std::string addr(sdp.connection()->getAddress());
1944    /*
1945            int bandwidth = atoi(sdp.bandwidth()->getBandwidthValue());
1946            std::string modifier = sdp.bandwidth()->getModifier();
1947    */
1948            std::string direction = "sendrecv";
1949            SdpAttributeList* attributeList = sdp.attributeList();
1950            int nAttribute = attributeList->numItem();
1951            for ( int n = 0; n < nAttribute; n++ )
1952            {
1953                    SdpAttribute* attribute = attributeList->getItem(n);
1954    
1955                    if ( !strcmp(attribute->getProperty(), "sendonly") )
1956                    {
1957                            direction = "sendonly";
1958                    }
1959                    if ( !strcmp(attribute->getProperty(), "recvonly") )
1960                    {
1961                            direction = "recvonly";
1962                    }
1963                    if ( !strcmp(attribute->getProperty(), "sendrecv") )
1964                    {
1965                            direction = "sendrecv";
1966                    }
1967                    if ( !strcmp(attribute->getProperty(), "inactive") )
1968                    {
1969                            direction = "inactive";
1970                    }
1971            }
1972            // TODO add direction check inside each media description
1973    
1974            int num_media = sdp.mediaDescriptionList()->numItem();
1975            for ( int i = 0; i < num_media; i++ )
1976            {
1977                    SdpMediaDescription* md = sdp.mediaDescriptionList()->getItem(i);
1978    
1979                    /* m=audio
1980                     */
1981                    SdpMedia* media = md->media();
1982                    if ( !strcmp(media->getMedia(), "audio") &&
1983                         !strcmp(media->getTransport(), "RTP/AVP") &&
1984                         (media->getPort() != 0) )
1985                    {
1986                            IpInfo rtp(addr, media->getPort());
1987    
1988                            int num_format = media->getNumFormat();
1989                            for ( int j = 0; j < num_format; j++ )
1990                            {
1991                                    RemoteMedia::Audio audio_media;
1992                                    audio_media.rtp = rtp;
1993    
1994                                    audio_media.coder.coderPayloadType = atoi(media->getFormat(j));
1995                                    audio_media.coder.coderType = CODER_TYPE_NONSTANDARD;
1996    
1997                                    /* set defaults for fixed formats, these may be overridden by
1998                                     * an fmtp attribute.
1999                                     */
2000                                    if ( audio_media.coder.coderPayloadType == 0 )  /* PCMU */
2001                                    {
2002                                            audio_media.coder.encoding = "PCMU";
2003                                            audio_media.coder.coderType = CODER_TYPE_G711ULAW64K;
2004                                            audio_media.coder.coderFramesize = CODER_FRAMESIZE_20;
2005                                            audio_media.coder.framesPerPkt = 1;
2006                                            audio_media.coder.vadEnable = CODER_VAD_ENABLE;
2007                                            audio_media.coder.redPayloadType = 0;
2008                                    }
2009                                    else if ( audio_media.coder.coderPayloadType == 8 )  /* PCMA */
2010                                    {
2011                                            audio_media.coder.encoding = "PCMA";
2012                                            audio_media.coder.coderType = CODER_TYPE_G711ALAW64K;
2013                                            audio_media.coder.coderFramesize = CODER_FRAMESIZE_20;
2014                                            audio_media.coder.framesPerPkt = 1;
2015                                            audio_media.coder.vadEnable = CODER_VAD_ENABLE;
2016                                            audio_media.coder.redPayloadType = 0;
2017                                    }
2018                                    else
2019                                    {
2020                                            /* more payload types go here. */
2021                                    }
2022                                    audio_media.direction = direction;
2023                                    audio_media.rfc2833  = false;
2024                                    offered_media_.audio.push_back(audio_media);
2025                            }
2026    
2027                            SdpAttributeList* attributeList = md->attributeList();
2028                            int nAttribute = attributeList->numItem();
2029                            for ( int k = 0; k < nAttribute; k++ )
2030                            {
2031                                    SdpAttribute* attribute = attributeList->getItem(k);
2032    
2033                                    if ( strcmp(attribute->getProperty(), "rtpmap") == 0 )
2034                                    {
2035                                            StringTokeniser rtpmap(attribute->getPropertyValue());
2036    
2037                                            int payload = atoi(rtpmap.token(' ').c_str());
2038                                            std::string encoding = rtpmap.token('/');
2039                                            int clockrate = atoi(rtpmap.token().c_str());
2040                                            if ( clockrate != 8000 )
2041                                            {
2042                                                    LOGWARN("IpmDevice::parseSdp() payload: " << payload <<
2043                                                            " has an unsupported clockrate: " << clockrate);
2044                                            }
2045                                            RemoteMedia::audio_t::iterator i;
2046                                            for ( i = offered_media_.audio.begin(); i != offered_media_.audio.end(); ++i )
2047                                            {
2048                                                    if ( (*i).coder.coderPayloadType == payload )
2049                                                    {
2050                                                            (*i).coder.encoding = encoding;
2051    
2052                                                            if ( strcasecmp((*i).coder.encoding.c_str(), "PCMU") == 0 )
2053                                                            {
2054                                                                    (*i).coder.coderType = CODER_TYPE_G711ULAW64K;
2055                                                            }
2056                                                            else if ( strcasecmp((*i).coder.encoding.c_str(), "PCMA") == 0 )
2057                                                            {
2058                                                                    (*i).coder.coderType = CODER_TYPE_G711ALAW64K;
2059                                                            }
2060                                                            else if ( strcasecmp((*i).coder.encoding.c_str(), "telephone-event") == 0 )
2061                                                            {
2062                                                                    /* not really a codec. */
2063                                                                    (*i).coder.coderType = CODER_TYPE_NONSTANDARD;
2064                                                                    (*i).rfc2833 = true;
2065                                                            }
2066                                                            else
2067                                                            {
2068                                                            }
2069                                                            break;
2070                                                    }
2071                                            }
2072                                    }
2073                                    else if ( strcmp(attribute->getProperty(), "fmtp") == 0 )
2074                                    {
2075                                            StringTokeniser fmtp(attribute->getPropertyValue());
2076    
2077                                            int format = atoi(fmtp.token(' ').c_str());
2078    
2079                                            RemoteMedia::audio_t::iterator i;
2080                                            for ( i = offered_media_.audio.begin(); i != offered_media_.audio.end(); ++i )
2081                                            {
2082                                                    if ( (*i).coder.coderPayloadType == format )
2083                                                    {
2084                                                            if ( ((*i).coder.coderType == CODER_TYPE_NONSTANDARD) && ((*i).rfc2833) )
2085                                                            {
2086                                                                    /* TODO use this */
2087                                                            }
2088                                                            else
2089                                                            {
2090                                                                    /* more payload types */
2091                                                            }
2092                                                            break;
2093                                                    }
2094                                            }
2095                                    }
2096                                    else
2097                                    {
2098                                            /* more attributes */
2099                                    }
2100                            }
2101                    }
2102    
2103                    /* m=video
2104                     */
2105                    if ( !strcmp(media->getMedia(), "video") &&
2106                         !strcmp(media->getTransport(), "RTP/AVP") &&
2107                         (media->getPort() != 0) )
2108                    {
2109                            IpInfo rtp(addr, media->getPort());
2110    
2111                            int num_format = media->getNumFormat();
2112                            for ( int j = 0; j < num_format; j++ )
2113                            {
2114                                    RemoteMedia::Video video_media;
2115                                    video_media.rtp = rtp;
2116    
2117                                    video_media.coder.coderPayloadType = atoi(media->getFormat(j));
2118    
2119                                    /* set defaults for fixed formats, these may be overridden by
2120                                     * an fmtp attribute.
2121                                     */
2122                                    if ( video_media.coder.coderPayloadType == 34 )   /* H.263 */
2123                                    {
2124                                            video_media.coder.encoding = "H263";
2125                                            video_media.coder.coderType = CODER_TYPE_H263;
2126                                            video_media.coder.profile = VIDEO_PROFILE_0_H263;
2127                                            video_media.coder.level = VIDEO_LEVEL_10_H263;
2128                                            video_media.coder.samplingRate = VIDEO_SAMPLING_RATE_DEFAULT;
2129                                            video_media.coder.bitRate = VIDEO_BITRATE_384K;
2130    
2131                                            /* Set default fmt (rfc4629 8.2.1).
2132                                             * This will be removed if an fmtp attribute is found.
2133                                             */
2134                                            VideoCoderInfo::Fmt fmt;
2135                                            fmt.imageWidth = VIDEO_IMAGE_WIDTH_176;
2136                                            fmt.imageHeight = VIDEO_IMAGE_HEIGHT_144;
2137                                            fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2138                                            video_media.coder.available_fmts.push_back(fmt);
2139                                    }
2140                                    else
2141                                    {
2142                                            /* more *known* payload types */
2143                                    }
2144                                    video_media.direction = direction;
2145                                    offered_media_.video.push_back(video_media);
2146                            }
2147    
2148                            SdpAttributeList* attributeList = md->attributeList();
2149                            int nAttribute = attributeList->numItem();
2150                            for ( int k = 0; k < nAttribute; k++ )
2151                            {
2152                                    SdpAttribute* attribute = attributeList->getItem(k);
2153    
2154                                    if ( strcmp(attribute->getProperty(), "rtpmap") == 0 )
2155                                    {
2156                                            StringTokeniser rtpmap(attribute->getPropertyValue());
2157    
2158                                            int payload = atoi(rtpmap.token(' ').c_str());
2159                                            std::string encoding = rtpmap.token('/');
2160                                            int clockrate = atoi(rtpmap.token().c_str());
2161                                            if ( clockrate != 90000 )
2162                                            {
2163                                                    LOGWARN("IpmDevice::parseSdp() payload: " << payload <<
2164                                                            " has an unsupported clockrate: " << clockrate);
2165                                            }
2166                                            RemoteMedia::video_t::iterator i;
2167                                            for ( i = offered_media_.video.begin(); i != offered_media_.video.end(); ++i )
2168                                            {
2169                                                    if ( (*i).coder.coderPayloadType == payload )
2170                                                    {
2171                                                            (*i).coder.encoding = encoding;
2172    
2173                                                            if ( strcasecmp((*i).coder.encoding.c_str(), "H263") == 0 )
2174                                                            {
2175                                                                    /* static payload type; defaults already set */
2176                                                                    (*i).coder.coderType = CODER_TYPE_H263;
2177                                                            }
2178                                                            else if ( strcasecmp((*i).coder.encoding.c_str(), "H263-1998") == 0 )
2179                                                            {
2180                                                                    (*i).coder.coderType = CODER_TYPE_H263_1998;
2181                                                                    (*i).coder.profile = VIDEO_PROFILE_0_H263;
2182                                                                    (*i).coder.level = VIDEO_LEVEL_10_H263;
2183                                                                    (*i).coder.samplingRate = VIDEO_SAMPLING_RATE_DEFAULT;
2184                                                                    (*i).coder.bitRate = VIDEO_BITRATE_384K;
2185    
2186                                                                    /* set default fmt, this will be removed if an
2187                                                                     * fmtp attribute is found.
2188                                                                     */
2189                                                                    VideoCoderInfo::Fmt fmt;
2190                                                                    fmt.imageWidth = VIDEO_IMAGE_WIDTH_176;
2191                                                                    fmt.imageHeight = VIDEO_IMAGE_HEIGHT_144;
2192                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2193                                                                    (*i).coder.available_fmts.push_back(fmt);
2194                                                            }
2195                                                            else if ( (strcasecmp((*i).coder.encoding.c_str(), "MP4V-ES") == 0) ||
2196                                                                      (strcasecmp((*i).coder.encoding.c_str(), "MPEG4") == 0) )
2197                                                            {
2198                                                                    (*i).coder.coderType = CODER_TYPE_MP4V_ES;
2199                                                                    (*i).coder.profile = VIDEO_PROFILE_LEVEL_SP3_MPEG4;
2200                                                                    (*i).coder.level = VIDEO_LEVEL_DEFAULT;
2201                                                                    (*i).coder.samplingRate = VIDEO_SAMPLING_RATE_DEFAULT;
2202                                                                    (*i).coder.bitRate = VIDEO_BITRATE_384K;
2203    
2204                                                                    /* set default fmt, this will be removed if an
2205                                                                     * fmtp attribute is found.
2206                                                                     */
2207                                                                    VideoCoderInfo::Fmt fmt;
2208                                                                    fmt.imageWidth = VIDEO_IMAGE_WIDTH_352;
2209                                                                    fmt.imageHeight = VIDEO_IMAGE_HEIGHT_288;
2210                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2211                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP3_MPEG4;
2212                                                                    (*i).coder.available_fmts.push_back(fmt);
2213                                                            }
2214                                                            else
2215                                                            {
2216                                                                    /* more encodings */
2217                                                            }
2218                                                            break;
2219                                                    }
2220                                            }
2221                                    }
2222                                    else if ( strcmp(attribute->getProperty(), "fmtp") == 0 )
2223                                    {
2224                                            StringTokeniser fmtp(attribute->getPropertyValue());
2225    
2226                                            int format = atoi(fmtp.token(' ').c_str());
2227    
2228                                            RemoteMedia::video_t::iterator i;
2229                                            for ( i = offered_media_.video.begin(); i != offered_media_.video.end(); ++i )
2230                                            {
2231                                                    if ( (*i).coder.coderPayloadType == format )
2232                                                    {
2233                                                            VideoCoderInfo::Fmt fmt;
2234                                                            bool done = false;
2235                                                            while ( !done )
2236                                                            {
2237                                                                    std::string name = fmtp.token('=');
2238                                                                    trim(name);
2239                                                                    if ( name.empty() )
2240                                                                    {
2241                                                                            break;
2242                                                                    }
2243                                                                    std::string value = fmtp.token("; ");
2244                                                                    trim(value);
2245                                                                    if ( value.empty() )
2246                                                                    {
2247                                                                            value = fmtp.token();
2248                                                                            done = true;
2249                                                                    }
2250    
2251                                                                    if ( name == "CIF" )
2252                                                                    {
2253                                                                            fmt.fmtpName = name + "=" + value;
2254                                                                            fmt.imageWidth = VIDEO_IMAGE_WIDTH_352;
2255                                                                            fmt.imageHeight = VIDEO_IMAGE_HEIGHT_288;
2256                                                                            int fps = mpi2fps(atoi(value.c_str()));
2257                                                                            if ( fps > VIDEO_FRAMESPERSEC_30 )
2258                                                                            {
2259                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2260                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP3_MPEG4;
2261                                                                            }
2262                                                                            else
2263                                                                            {
2264                                                                                    fmt.framesPerSec = (eVIDEO_FRAMESPERSEC)fps;
2265                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP2_MPEG4;
2266                                                                            }
2267                                                                            (*i).coder.available_fmts.push_back(fmt);
2268                                                                    }
2269                                                                    else if ( name == "QCIF" )
2270                                                                    {
2271                                                                            fmt.fmtpName = name + "=" + value;
2272                                                                            fmt.imageWidth = VIDEO_IMAGE_WIDTH_176;
2273                                                                            fmt.imageHeight = VIDEO_IMAGE_HEIGHT_144;
2274                                                                            int fps = mpi2fps(atoi(value.c_str()));
2275                                                                            if ( fps > VIDEO_FRAMESPERSEC_30 )
2276                                                                            {
2277                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2278                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP1_MPEG4;
2279                                                                            }
2280                                                                            else
2281                                                                            {
2282                                                                                    fmt.framesPerSec = (eVIDEO_FRAMESPERSEC)fps;
2283                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP0_MPEG4;
2284                                                                            }
2285                                                                            (*i).coder.available_fmts.push_back(fmt);
2286                                                                    }
2287                                                                    else if ( name == "Sub-QCIF" )
2288                                                                    {
2289                                                                            fmt.fmtpName = name + "=" + value;
2290                                                                            fmt.imageWidth = VIDEO_IMAGE_WIDTH_128;
2291                                                                            fmt.imageHeight = VIDEO_IMAGE_HEIGHT_96;
2292                                                                            int fps = mpi2fps(atoi(value.c_str()));
2293                                                                            if ( fps > VIDEO_FRAMESPERSEC_30 )
2294                                                                            {
2295                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2296                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP1_MPEG4;
2297                                                                            }
2298                                                                            else
2299                                                                            {
2300                                                                                    fmt.framesPerSec = (eVIDEO_FRAMESPERSEC)fps;
2301                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP0_MPEG4;
2302                                                                            }
2303                                                                            (*i).coder.available_fmts.push_back(fmt);
2304                                                                    }
2305                                                                    else if ( name == "profile" )
2306                                                                    {
2307                                                                            (*i).coder.profile = (eVIDEO_PROFILE)atoi(value.c_str());
2308                                                                    }
2309                                                                    else if ( name == "level" )
2310                                                                    {
2311                                                                            (*i).coder.level = (eVIDEO_LEVEL)atoi(value.c_str());
2312                                                                    }
2313                                                                    else if ( name == "profile-level-id" )
2314                                                                    {
2315                                                                            fmt.fmtpName = name + "=" + value;
2316                                                                            if ( value == "0" )
2317                                                                            {
2318                                                                                    (*i).coder.profile = VIDEO_PROFILE_LEVEL_SP0_MPEG4;
2319                                                                                    fmt.imageWidth = VIDEO_IMAGE_WIDTH_176;
2320                                                                                    fmt.imageHeight = VIDEO_IMAGE_HEIGHT_144;
2321                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_15;
2322                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP0_MPEG4;
2323                                                                                    (*i).coder.available_fmts.push_back(fmt);
2324                                                                            }
2325                                                                            else if ( value == "1" )
2326                                                                            {
2327                                                                                    (*i).coder.profile = VIDEO_PROFILE_LEVEL_SP1_MPEG4;
2328                                                                                    fmt.imageWidth = VIDEO_IMAGE_WIDTH_176;
2329                                                                                    fmt.imageHeight = VIDEO_IMAGE_HEIGHT_144;
2330                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_15;
2331                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP1_MPEG4;
2332                                                                                    (*i).coder.available_fmts.push_back(fmt);
2333                                                                            }
2334                                                                            else if ( value == "2" )
2335                                                                            {
2336                                                                                    (*i).coder.profile = VIDEO_PROFILE_LEVEL_SP2_MPEG4;
2337                                                                                    fmt.imageWidth = VIDEO_IMAGE_WIDTH_352;
2338                                                                                    fmt.imageHeight = VIDEO_IMAGE_HEIGHT_288;
2339                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_15;
2340                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP2_MPEG4;
2341                                                                                    (*i).coder.available_fmts.push_back(fmt);
2342                                                                            }
2343                                                                            else if ( value == "3" )
2344                                                                            {
2345                                                                                    (*i).coder.profile = VIDEO_PROFILE_LEVEL_SP3_MPEG4;
2346                                                                                    fmt.imageWidth = VIDEO_IMAGE_WIDTH_352;
2347                                                                                    fmt.imageHeight = VIDEO_IMAGE_HEIGHT_288;
2348                                                                                    fmt.framesPerSec = VIDEO_FRAMESPERSEC_30;
2349                                                                                    fmt.profile = VIDEO_PROFILE_LEVEL_SP3_MPEG4;
2350                                                                                    (*i).coder.available_fmts.push_back(fmt);
2351                                                                            }
2352                                                                            else
2353                                                                            {
2354                                                                                    continue;
2355                                                                            }
2356                                                                    }
2357                                                                    else if ( name == "MaxBR" )
2358                                                                    {
2359                                                                            (*i).coder.bitRate = atoi(value.c_str()) * 100;
2360                                                                    }
2361                                                                    else
2362                                                                    {
2363                                                                            continue; /* ignore unsupported params. */
2364                                                                    }
2365                                                            }
2366    
2367                                                            /* remove the default fmt, no longer needed. */
2368                                                            if ( (*i).coder.available_fmts.size() > 1 )
2369                                                            {
2370                                                                    (*i).coder.available_fmts.erase((*i).coder.available_fmts.begin());
2371                                                            }
2372                                                            break;
2373                                                    }
2374                                                    else
2375                                                    {
2376                                                            /* more payload types */
2377                                                    }
2378                                            }
2379                                    }
2380                                    else
2381                                    {
2382                                            /* more attributes */
2383                                    }
2384                            }
2385                    }
2386            }
2387    }
2388    
2389    
2390    
2391  /* vim:ts=4:set nu:  /* vim:ts=4:set nu:

Legend:
Removed from v.142  
changed lines
  Added in v.634

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.8