/* $Id$ */ /* * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "util.hpp" using namespace pj; using namespace std; #define THIS_FILE "media.cpp" #define MAX_FILE_NAMES 64 #define MAX_DEV_COUNT 64 /////////////////////////////////////////////////////////////////////////////// void MediaFormatAudio::fromPj(const pjmedia_format &format) { if ((format.type != PJMEDIA_TYPE_AUDIO) && (format.detail_type != PJMEDIA_FORMAT_DETAIL_AUDIO)) { type = PJMEDIA_TYPE_UNKNOWN; return; } id = format.id; type = format.type; /* Detail. */ clockRate = format.det.aud.clock_rate; channelCount = format.det.aud.channel_count; frameTimeUsec = format.det.aud.frame_time_usec; bitsPerSample = format.det.aud.bits_per_sample; avgBps = format.det.aud.avg_bps; maxBps = format.det.aud.max_bps; } pjmedia_format MediaFormatAudio::toPj() const { pjmedia_format pj_format; pj_format.id = id; pj_format.type = type; pj_format.detail_type = PJMEDIA_FORMAT_DETAIL_AUDIO; pj_format.det.aud.clock_rate = clockRate; pj_format.det.aud.channel_count = channelCount; pj_format.det.aud.frame_time_usec = frameTimeUsec; pj_format.det.aud.bits_per_sample = bitsPerSample; pj_format.det.aud.avg_bps = avgBps; pj_format.det.aud.max_bps = maxBps; return pj_format; } /////////////////////////////////////////////////////////////////////////////// /* Audio Media operations. */ void ConfPortInfo::fromPj(const pjsua_conf_port_info &port_info) { portId = port_info.slot_id; name = pj2Str(port_info.name); format.fromPj(port_info.format); txLevelAdj = port_info.tx_level_adj; rxLevelAdj = port_info.rx_level_adj; /* format.id = PJMEDIA_FORMAT_PCM; format.type = PJMEDIA_TYPE_AUDIO; format.clockRate = port_info.clock_rate; format.channelCount = port_info.channel_count; format.bitsPerSample = port_info.bits_per_sample; format.frameTimeUsec = (port_info.samples_per_frame * 1000000) / (port_info.clock_rate * port_info.channel_count); format.avgBps = format.maxBps = port_info.clock_rate * port_info.channel_count * port_info.bits_per_sample; */ listeners.clear(); for (unsigned i=0; i(media); } /////////////////////////////////////////////////////////////////////////////// AudioMediaPlayer::AudioMediaPlayer() : playerId(PJSUA_INVALID_ID) { } AudioMediaPlayer::~AudioMediaPlayer() { if (playerId != PJSUA_INVALID_ID) { unregisterMediaPort(); pjsua_player_destroy(playerId); } } void AudioMediaPlayer::createPlayer(const string &file_name, unsigned options) throw(Error) { if (playerId != PJSUA_INVALID_ID) { PJSUA2_RAISE_ERROR(PJ_EEXISTS); } pj_str_t pj_name = str2Pj(file_name); PJSUA2_CHECK_EXPR( pjsua_player_create(&pj_name, options, &playerId) ); /* Register EOF callback */ pjmedia_port *port; pj_status_t status; status = pjsua_player_get_port(playerId, &port); if (status != PJ_SUCCESS) { pjsua_player_destroy(playerId); PJSUA2_RAISE_ERROR2(status, "AudioMediaPlayer::createPlayer()"); } status = pjmedia_wav_player_set_eof_cb(port, this, &eof_cb); if (status != PJ_SUCCESS) { pjsua_player_destroy(playerId); PJSUA2_RAISE_ERROR2(status, "AudioMediaPlayer::createPlayer()"); } /* Get media port id. */ id = pjsua_player_get_conf_port(playerId); registerMediaPort(NULL); } void AudioMediaPlayer::createPlaylist(const StringVector &file_names, const string &label, unsigned options) throw(Error) { if (playerId != PJSUA_INVALID_ID) { PJSUA2_RAISE_ERROR(PJ_EEXISTS); } pj_str_t pj_files[MAX_FILE_NAMES]; unsigned i, count = 0; pj_str_t pj_lbl = str2Pj(label); pj_status_t status; count = PJ_ARRAY_SIZE(pj_files); for(i=0; i(media); } pj_status_t AudioMediaPlayer::eof_cb(pjmedia_port *port, void *usr_data) { PJ_UNUSED_ARG(port); AudioMediaPlayer *player = (AudioMediaPlayer*)usr_data; return player->onEof() ? PJ_SUCCESS : PJ_EEOF; } /////////////////////////////////////////////////////////////////////////////// AudioMediaRecorder::AudioMediaRecorder() : recorderId(PJSUA_INVALID_ID) { } AudioMediaRecorder::~AudioMediaRecorder() { if (recorderId != PJSUA_INVALID_ID) { unregisterMediaPort(); pjsua_recorder_destroy(recorderId); } } void AudioMediaRecorder::createRecorder(const string &file_name, unsigned enc_type, pj_ssize_t max_size, unsigned options) throw(Error) { PJ_UNUSED_ARG(max_size); if (recorderId != PJSUA_INVALID_ID) { PJSUA2_RAISE_ERROR(PJ_EEXISTS); } pj_str_t pj_name = str2Pj(file_name); PJSUA2_CHECK_EXPR( pjsua_recorder_create(&pj_name, enc_type, NULL, -1, options, &recorderId) ); /* Get media port id. */ id = pjsua_recorder_get_conf_port(recorderId); registerMediaPort(NULL); } AudioMediaRecorder* AudioMediaRecorder::typecastFromAudioMedia( AudioMedia *media) { return static_cast(media); } /////////////////////////////////////////////////////////////////////////////// ToneGenerator::ToneGenerator() : pool(NULL), tonegen(NULL) { } ToneGenerator::~ToneGenerator() { if (tonegen) { unregisterMediaPort(); pjmedia_port_destroy(tonegen); tonegen = NULL; } if (pool) { pj_pool_release(pool); pool = NULL; } } void ToneGenerator::createToneGenerator(unsigned clock_rate, unsigned channel_count) throw(Error) { pj_status_t status; if (pool) { PJSUA2_RAISE_ERROR(PJ_EEXISTS); } pool = pjsua_pool_create( "tonegen%p", 512, 512); if (!pool) { PJSUA2_RAISE_ERROR(PJ_ENOMEM); } status = pjmedia_tonegen_create( pool, clock_rate, channel_count, clock_rate * 20 / 1000, 16, 0, &tonegen); if (status != PJ_SUCCESS) { PJSUA2_RAISE_ERROR(status); } registerMediaPort(tonegen); } bool ToneGenerator::isBusy() const { return tonegen && pjmedia_tonegen_is_busy(tonegen) != 0; } void ToneGenerator::stop() throw(Error) { pj_status_t status; if (!tonegen) { PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); } status = pjmedia_tonegen_stop(tonegen); PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::stop()"); } void ToneGenerator::rewind() throw(Error) { pj_status_t status; if (!tonegen) { PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); } status = pjmedia_tonegen_rewind(tonegen); PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::rewind()"); } void ToneGenerator::play(const ToneDescVector &tones, bool loop) throw(Error) { pj_status_t status; if (!tonegen) { PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); } if (tones.size() == 0) { PJSUA2_RAISE_ERROR(PJ_EINVAL); } status = pjmedia_tonegen_play(tonegen, tones.size(), &tones[0], loop? PJMEDIA_TONEGEN_LOOP : 0); PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::play()"); } void ToneGenerator::playDigits(const ToneDigitVector &digits, bool loop) throw(Error) { pj_status_t status; if (!tonegen) { PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); } if (digits.size() == 0) { PJSUA2_RAISE_ERROR(PJ_EINVAL); } status = pjmedia_tonegen_play_digits(tonegen, digits.size(), &digits[0], loop? PJMEDIA_TONEGEN_LOOP : 0); PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::playDigits()"); } ToneDigitMapVector ToneGenerator::getDigitMap() const throw(Error) { const pjmedia_tone_digit_map *pdm; ToneDigitMapVector tdm; unsigned i; pj_status_t status; if (!tonegen) { PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); } status = pjmedia_tonegen_get_digit_map(tonegen, &pdm); PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::getDigitMap()"); for (i=0; icount; ++i) { ToneDigitMapDigit d; char str_digit[2]; str_digit[0] = pdm->digits[i].digit; str_digit[1] = '\0'; d.digit = str_digit; d.freq1 = pdm->digits[i].freq1; d.freq2 = pdm->digits[i].freq2; tdm.push_back(d); } return tdm; } void ToneGenerator::setDigitMap(const ToneDigitMapVector &digit_map) throw(Error) { unsigned i; pj_status_t status; if (!tonegen) { PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); } digitMap.count = digit_map.size(); if (digitMap.count > PJ_ARRAY_SIZE(digitMap.digits)) digitMap.count = PJ_ARRAY_SIZE(digitMap.digits); for (i=0; ifromPj(dev_info.ext_fmt[i]); if (format->type == PJMEDIA_TYPE_AUDIO) extFmt.push_back(format); } } AudioDevInfo::~AudioDevInfo() { for(unsigned i=0;iid = 0; registerMediaPort(NULL); } DevAudioMedia::~DevAudioMedia() { /* Avoid removing this port (conf port id=0) from conference */ this->id = PJSUA_INVALID_ID; } /////////////////////////////////////////////////////////////////////////////// /* Audio device operations. */ AudDevManager::AudDevManager() : devMedia(NULL) { } AudDevManager::~AudDevManager() { // At this point, devMedia should have been cleaned up by Endpoint, // as AudDevManager destructor is called after Endpoint destructor. //delete devMedia; clearAudioDevList(); } int AudDevManager::getCaptureDev() const throw(Error) { return getActiveDev(true); } AudioMedia &AudDevManager::getCaptureDevMedia() throw(Error) { if (!devMedia) devMedia = new DevAudioMedia; return *devMedia; } int AudDevManager::getPlaybackDev() const throw(Error) { return getActiveDev(false); } AudioMedia &AudDevManager::getPlaybackDevMedia() throw(Error) { if (!devMedia) devMedia = new DevAudioMedia; return *devMedia; } void AudDevManager::setCaptureDev(int capture_dev) const throw(Error) { int playback_dev = getPlaybackDev(); PJSUA2_CHECK_EXPR( pjsua_set_snd_dev(capture_dev, playback_dev) ); } void AudDevManager::setPlaybackDev(int playback_dev) const throw(Error) { int capture_dev = getCaptureDev(); PJSUA2_CHECK_EXPR( pjsua_set_snd_dev(capture_dev, playback_dev) ); } const AudioDevInfoVector &AudDevManager::enumDev() throw(Error) { pjmedia_aud_dev_info pj_info[MAX_DEV_COUNT]; unsigned count = MAX_DEV_COUNT; PJSUA2_CHECK_EXPR( pjsua_enum_aud_devs(pj_info, &count) ); pj_enter_critical_section(); clearAudioDevList(); for (unsigned i = 0; ifromPj(pj_info[i]); audioDevList.push_back(dev_info); } pj_leave_critical_section(); return audioDevList; } void AudDevManager::setNullDev() throw(Error) { PJSUA2_CHECK_EXPR( pjsua_set_null_snd_dev() ); } MediaPort *AudDevManager::setNoDev() { return (MediaPort*)pjsua_set_no_snd_dev(); } void AudDevManager::setEcOptions(unsigned tail_msec, unsigned options) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_set_ec(tail_msec, options) ); } unsigned AudDevManager::getEcTail() const throw(Error) { unsigned tail_msec = 0; PJSUA2_CHECK_EXPR( pjsua_get_ec_tail(&tail_msec) ); return tail_msec; } bool AudDevManager::sndIsActive() const { return PJ2BOOL(pjsua_snd_is_active()); } void AudDevManager::refreshDevs() throw(Error) { PJSUA2_CHECK_EXPR( pjmedia_aud_dev_refresh() ); } unsigned AudDevManager::getDevCount() const { return pjmedia_aud_dev_count(); } AudioDevInfo AudDevManager::getDevInfo(int id) const throw(Error) { AudioDevInfo dev_info; pjmedia_aud_dev_info pj_info; PJSUA2_CHECK_EXPR( pjmedia_aud_dev_get_info(id, &pj_info) ); dev_info.fromPj(pj_info); return dev_info; } int AudDevManager::lookupDev(const string &drv_name, const string &dev_name) const throw(Error) { pjmedia_aud_dev_index pj_idx = 0; PJSUA2_CHECK_EXPR( pjmedia_aud_dev_lookup(drv_name.c_str(), dev_name.c_str(), &pj_idx) ); return pj_idx; } string AudDevManager::capName(pjmedia_aud_dev_cap cap) const { return pjmedia_aud_dev_cap_name(cap, NULL); } void AudDevManager::setExtFormat(const MediaFormatAudio &format, bool keep) throw(Error) { pjmedia_format pj_format = format.toPj(); PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_EXT_FORMAT, &pj_format, keep) ); } MediaFormatAudio AudDevManager::getExtFormat() const throw(Error) { pjmedia_format pj_format; MediaFormatAudio format; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_EXT_FORMAT, &pj_format) ); format.fromPj(pj_format); return format; } void AudDevManager::setInputLatency(unsigned latency_msec, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY, &latency_msec, keep) ); } unsigned AudDevManager::getInputLatency() const throw(Error) { unsigned latency_msec = 0; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY, &latency_msec) ); return latency_msec; } void AudDevManager::setOutputLatency(unsigned latency_msec, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY, &latency_msec, keep) ); } unsigned AudDevManager::getOutputLatency() const throw(Error) { unsigned latency_msec = 0; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY, &latency_msec) ); return latency_msec; } void AudDevManager::setInputVolume(unsigned volume, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING, &volume, keep) ); } unsigned AudDevManager::getInputVolume() const throw(Error) { unsigned volume = 0; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING, &volume) ); return volume; } void AudDevManager::setOutputVolume(unsigned volume, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &volume, keep) ); } unsigned AudDevManager::getOutputVolume() const throw(Error) { unsigned volume = 0; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &volume) ); return volume; } unsigned AudDevManager::getInputSignal() const throw(Error) { unsigned signal = 0; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER, &signal) ); return signal; } unsigned AudDevManager::getOutputSignal() const throw(Error) { unsigned signal = 0; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER, &signal) ); return signal; } void AudDevManager::setInputRoute(pjmedia_aud_dev_route route, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE, &route, keep) ); } pjmedia_aud_dev_route AudDevManager::getInputRoute() const throw(Error) { pjmedia_aud_dev_route route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE, &route) ); return route; } void AudDevManager::setOutputRoute(pjmedia_aud_dev_route route, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE, &route, keep) ); } pjmedia_aud_dev_route AudDevManager::getOutputRoute() const throw(Error) { pjmedia_aud_dev_route route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE, &route) ); return route; } void AudDevManager::setVad(bool enable, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_VAD, &enable, keep) ); } bool AudDevManager::getVad() const throw(Error) { bool enable = false; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_VAD, &enable) ); return enable; } void AudDevManager::setCng(bool enable, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_CNG, &enable, keep) ); } bool AudDevManager::getCng() const throw(Error) { bool enable = false; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_CNG, &enable) ); return enable; } void AudDevManager::setPlc(bool enable, bool keep) throw(Error) { PJSUA2_CHECK_EXPR( pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_PLC, &enable, keep) ); } bool AudDevManager::getPlc() const throw(Error) { bool enable = false; PJSUA2_CHECK_EXPR( pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_PLC, &enable) ); return enable; } void AudDevManager::clearAudioDevList() { for(unsigned i=0;irendId = prm.rend_id; this->show = PJ2BOOL(prm.show); this->windowFlags = prm.wnd_flags; this->format.id = prm.format.id; this->format.type = prm.format.type; this->window.type = prm.wnd.type; this->window.handle.window = prm.wnd.info.window; #else PJ_UNUSED_ARG(prm); #endif } pjsua_vid_preview_param VideoPreviewOpParam::toPj() const { pjsua_vid_preview_param param; pj_bzero(¶m, sizeof(param)); #if PJSUA_HAS_VIDEO param.rend_id = this->rendId; param.show = this->show; param.wnd_flags = this->windowFlags; param.format.id = this->format.id; param.format.type = this->format.type; param.wnd.type = this->window.type; param.wnd.info.window = this->window.handle.window; #endif return param; } VideoPreview::VideoPreview(int dev_id) : devId(dev_id) { } bool VideoPreview::hasNative() { #if PJSUA_HAS_VIDEO return(PJ2BOOL(pjsua_vid_preview_has_native(devId))); #else return false; #endif } void VideoPreview::start(const VideoPreviewOpParam ¶m) throw(Error) { #if PJSUA_HAS_VIDEO pjsua_vid_preview_param prm = param.toPj(); PJSUA2_CHECK_EXPR(pjsua_vid_preview_start(devId, &prm)); #else PJ_UNUSED_ARG(param); PJ_UNUSED_ARG(devId); #endif } void VideoPreview::stop() throw(Error) { #if PJSUA_HAS_VIDEO pjsua_vid_preview_stop(devId); #endif } VideoWindow VideoPreview::getVideoWindow() { #if PJSUA_HAS_VIDEO return (VideoWindow(pjsua_vid_preview_get_win(devId))); #else return (VideoWindow(PJSUA_INVALID_ID)); #endif } /////////////////////////////////////////////////////////////////////////////// void MediaFormatVideo::fromPj(const pjmedia_format &format) { #if PJSUA_HAS_VIDEO if ((format.type != PJMEDIA_TYPE_VIDEO) && (format.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO)) { type = PJMEDIA_TYPE_UNKNOWN; return; } id = format.id; type = format.type; /* Detail. */ width = format.det.vid.size.w; height = format.det.vid.size.h; fpsNum = format.det.vid.fps.num; fpsDenum = format.det.vid.fps.denum; avgBps = format.det.vid.avg_bps; maxBps = format.det.vid.max_bps; #else PJ_UNUSED_ARG(format); type = PJMEDIA_TYPE_UNKNOWN; #endif } pjmedia_format MediaFormatVideo::toPj() const { pjmedia_format pj_format; #if PJSUA_HAS_VIDEO pj_format.id = id; pj_format.type = type; pj_format.detail_type = PJMEDIA_FORMAT_DETAIL_VIDEO; pj_format.det.vid.size.w = width; pj_format.det.vid.size.h = height; pj_format.det.vid.fps.num = fpsNum; pj_format.det.vid.fps.denum = fpsDenum; pj_format.det.vid.avg_bps = avgBps; pj_format.det.vid.max_bps = maxBps; #else pj_format.type = PJMEDIA_TYPE_UNKNOWN; #endif return pj_format; } /////////////////////////////////////////////////////////////////////////////// void VideoDevInfo::fromPj(const pjmedia_vid_dev_info &dev_info) { #if PJSUA_HAS_VIDEO id = dev_info.id; name = dev_info.name; driver = dev_info.driver; dir = dev_info.dir; caps = dev_info.caps; for (unsigned i = 0; ifromPj(dev_info.fmt[i]); if (format->type == PJMEDIA_TYPE_VIDEO) fmt.push_back(format); } #else PJ_UNUSED_ARG(dev_info); #endif } VideoDevInfo::~VideoDevInfo() { #if PJSUA_HAS_VIDEO for (unsigned i = 0;ifromPj(pj_info[i]); videoDevList.push_back(dev_info); } pj_leave_critical_section(); #endif return videoDevList; } int VidDevManager::lookupDev(const string &drv_name, const string &dev_name) const throw(Error) { pjmedia_vid_dev_index pj_idx = 0; #if PJSUA_HAS_VIDEO PJSUA2_CHECK_EXPR(pjmedia_vid_dev_lookup(drv_name.c_str(), dev_name.c_str(), &pj_idx)); #else PJ_UNUSED_ARG(drv_name); PJ_UNUSED_ARG(dev_name); #endif return pj_idx; } string VidDevManager::capName(pjmedia_vid_dev_cap cap) const { string cap_name; #if PJSUA_HAS_VIDEO cap_name = pjmedia_vid_dev_cap_name(cap, NULL); #else PJ_UNUSED_ARG(cap); #endif return cap_name; } void VidDevManager::setFormat(int dev_id, const MediaFormatVideo &format, bool keep) throw(Error) { #if PJSUA_HAS_VIDEO pjmedia_format pj_format = format.toPj(); PJSUA2_CHECK_EXPR(pjsua_vid_dev_set_setting(dev_id, PJMEDIA_VID_DEV_CAP_FORMAT, &pj_format, keep)); #else PJ_UNUSED_ARG(dev_id); PJ_UNUSED_ARG(format); PJ_UNUSED_ARG(keep); #endif } MediaFormatVideo VidDevManager::getFormat(int dev_id) const throw(Error) { MediaFormatVideo vid_format; pj_bzero(&vid_format, sizeof(vid_format)); #if PJSUA_HAS_VIDEO pjmedia_format pj_format; PJSUA2_CHECK_EXPR(pjsua_vid_dev_get_setting(dev_id, PJMEDIA_VID_DEV_CAP_FORMAT, &pj_format)); vid_format.fromPj(pj_format); #else PJ_UNUSED_ARG(dev_id); #endif return vid_format; } void VidDevManager::setInputScale(int dev_id, const MediaSize &scale, bool keep) throw(Error) { #if PJSUA_HAS_VIDEO pjmedia_rect_size pj_size; pj_size.w = scale.w; pj_size.h = scale.h; PJSUA2_CHECK_EXPR(pjsua_vid_dev_set_setting(dev_id, PJMEDIA_VID_DEV_CAP_INPUT_SCALE, &pj_size, keep)); #else PJ_UNUSED_ARG(dev_id); PJ_UNUSED_ARG(scale); PJ_UNUSED_ARG(keep); #endif } MediaSize VidDevManager::getInputScale(int dev_id) const throw(Error) { MediaSize scale; pj_bzero(&scale, sizeof(scale)); #if PJSUA_HAS_VIDEO pjmedia_rect_size pj_size; PJSUA2_CHECK_EXPR(pjsua_vid_dev_get_setting(dev_id, PJMEDIA_VID_DEV_CAP_INPUT_SCALE, &pj_size)); scale.w = pj_size.w; scale.h = pj_size.h; #else PJ_UNUSED_ARG(dev_id); #endif return scale; } void VidDevManager::setOutputWindowFlags(int dev_id, int flags, bool keep) throw(Error) { #if PJSUA_HAS_VIDEO PJSUA2_CHECK_EXPR(pjsua_vid_dev_set_setting(dev_id, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS, &flags, keep)); #else PJ_UNUSED_ARG(dev_id); PJ_UNUSED_ARG(flags); PJ_UNUSED_ARG(keep); #endif } int VidDevManager::getOutputWindowFlags(int dev_id) throw(Error) { int flags = 0; #if PJSUA_HAS_VIDEO PJSUA2_CHECK_EXPR(pjsua_vid_dev_get_setting(dev_id, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS, &flags)); #else PJ_UNUSED_ARG(dev_id); #endif return flags; } void VidDevManager::switchDev(int dev_id, const VideoSwitchParam ¶m) throw(Error) { #if PJSUA_HAS_VIDEO pjmedia_vid_dev_switch_param pj_param; pj_param.target_id = param.target_id; PJSUA2_CHECK_EXPR(pjsua_vid_dev_set_setting(dev_id, PJMEDIA_VID_DEV_CAP_SWITCH, &pj_param, PJ_FALSE)); #else PJ_UNUSED_ARG(dev_id); PJ_UNUSED_ARG(param); #endif } void VidDevManager::clearVideoDevList() { #if PJSUA_HAS_VIDEO for (unsigned i = 0;i= PJMEDIA_CODEC_MAX_FMTP_CNT) { break; } out_fmtp.param[out_fmtp.cnt].name = str2Pj((*i).name); out_fmtp.param[out_fmtp.cnt].val = str2Pj((*i).val); ++out_fmtp.cnt; } }