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