std::shared_ptr<SipTransport>
SipTransportBroker::createUdpTransport(const SipTransportDescr& d)
{
    RETURN_IF_FAIL(d.listenerPort != 0, nullptr, "Could not determine port for this transport");
    auto family = pjsip_transport_type_get_af(d.type);

    IpAddr listeningAddress = (d.interface == ip_utils::DEFAULT_INTERFACE) ?
        ip_utils::getAnyHostAddr(family) :
        ip_utils::getInterfaceAddr(d.interface, family);
    listeningAddress.setPort(d.listenerPort);

    RETURN_IF_FAIL(listeningAddress, nullptr, "Could not determine IP address for this transport");
    pjsip_transport *transport = nullptr;
    pj_status_t status = listeningAddress.isIpv4()
        ? pjsip_udp_transport_start (endpt_, &static_cast<const pj_sockaddr_in&>(listeningAddress),  nullptr, 1, &transport)
        : pjsip_udp_transport_start6(endpt_, &static_cast<const pj_sockaddr_in6&>(listeningAddress), nullptr, 1, &transport);
    if (status != PJ_SUCCESS) {
        RING_ERR("pjsip_udp_transport_start* failed with error %d: %s", status,
                 sip_utils::sip_strerror(status).c_str());
        RING_ERR("UDP IPv%s Transport did not start on %s",
            listeningAddress.isIpv4() ? "4" : "6",
            listeningAddress.toString(true).c_str());
        return nullptr;
    }

    RING_DBG("Created UDP transport on %s : %s", d.interface.c_str(), listeningAddress.toString(true).c_str());
    auto ret = std::make_shared<SipTransport>(transport);
    // dec ref because the refcount starts at 1 and SipTransport increments it ?
    // pjsip_transport_dec_ref(transport);
    return ret;
}
Esempio n. 2
0
int
exportAccounts(std::vector<std::string> accountIDs,
                        std::string filepath,
                        std::string password)
{
    if (filepath.empty() || !accountIDs.size()) {
        RING_ERR("Missing arguments");
        return EINVAL;
    }

    std::size_t found = filepath.find_last_of(DIR_SEPARATOR_STR);
    auto toDir = filepath.substr(0,found);
    auto filename = filepath.substr(found+1);

    if (!fileutils::isDirectory(toDir)) {
        RING_ERR("%s is not a directory", toDir.c_str());
        return ENOTDIR;
    }

    // Add
    Json::Value root;
    Json::Value array;

    for (size_t i = 0; i < accountIDs.size(); ++i) {
        auto detailsMap = Manager::instance().getAccountDetails(accountIDs[i]);
        if (detailsMap.empty()) {
            RING_WARN("Can't export account %s", accountIDs[i].c_str());
            continue;
        }

        auto jsonAccount = accountToJsonValue(detailsMap);
        array.append(jsonAccount);
    }
    root["accounts"] = array;
    Json::FastWriter fastWriter;
    std::string output = fastWriter.write(root);

    // Compress
    std::vector<uint8_t> compressed;
    try {
        compressed = compress(output);
    } catch (const std::runtime_error& ex) {
        RING_ERR("Export failed: %s", ex.what());
        return 1;
    }

    // Encrypt using provided password
    auto encrypted = dht::crypto::aesEncrypt(compressed, password);

    // Write
    try {
        fileutils::saveFile(toDir + DIR_SEPARATOR_STR + filename, encrypted);
    } catch (const std::runtime_error& ex) {
        RING_ERR("Export failed: %s", ex.what());
        return EIO;
    }
    return 0;
}
bool VideoInput::setup()
{
    if (not attach(sink_.get())) {
        RING_ERR("attach sink failed");
        return false;
    }

    if (!sink_->start())
        RING_ERR("start sink failed");

    RING_DBG("VideoInput ready to capture");
    return true;
}
Esempio n. 4
0
bool
ShmHolder::resizeArea(std::size_t frameSize) noexcept
{
    // aligned on 16-byte boundary frameSize
    frameSize = (frameSize + 15) & ~15;

    if (area_ != MAP_FAILED and frameSize == area_->frameSize)
        return true;

    // full area size: +15 to take care of maximum padding size
    const auto areaSize = sizeof(SHMHeader) + 2 * frameSize + 15;
    RING_DBG("ShmHolder[%s]: new sizes: f=%zu, a=%zu", openedName_.c_str(),
             frameSize, areaSize);

    unMapShmArea();

    if (::ftruncate(fd_, areaSize) < 0) {
        RING_ERR("ShmHolder[%s]: ftruncate(%zu) failed with errno %d",
                 openedName_.c_str(), areaSize, errno);
        return false;
    }

    area_ = static_cast<SHMHeader*>(::mmap(nullptr, areaSize,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED, fd_, 0));

    if (area_ == MAP_FAILED) {
        areaSize_ = 0;
        RING_ERR("ShmHolder[%s]: mmap(%zu) failed with errno %d",
                 openedName_.c_str(), areaSize, errno);
        return false;
    }

    areaSize_ = areaSize;

    if (frameSize) {
        SemGuardLock lk {area_->mutex};

        area_->frameSize = frameSize;
        area_->mapSize = areaSize;

        // Compute aligned IO pointers
        // Note: we not using std::align as not implemented in 4.9
        // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
        auto p = reinterpret_cast<std::uintptr_t>(area_->data);
        area_->writeOffset = ((p + 15) & ~15) - p;
        area_->readOffset = area_->writeOffset + frameSize;
    }

    return true;
}
void
AudioRtpSession::start(std::unique_ptr<IceSocket> rtp_sock, std::unique_ptr<IceSocket> rtcp_sock)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);

    if (not send_.enabled and not receive_.enabled) {
        stop();
        return;
    }

    try {
        if (rtp_sock and rtcp_sock)
            socketPair_.reset(new SocketPair(std::move(rtp_sock), std::move(rtcp_sock)));
        else
            socketPair_.reset(new SocketPair(getRemoteRtpUri().c_str(), receive_.addr.getPort()));

        if (send_.crypto and receive_.crypto) {
            socketPair_->createSRTP(receive_.crypto.getCryptoSuite().c_str(),
                                    receive_.crypto.getSrtpKeyInfo().c_str(),
                                    send_.crypto.getCryptoSuite().c_str(),
                                    send_.crypto.getSrtpKeyInfo().c_str());
        }
    } catch (const std::runtime_error& e) {
        RING_ERR("Socket creation failed: %s", e.what());
        return;
    }

    startSender();
    startReceiver();
}
void
AudioRtpSession::startSender()
{
    if (not send_.enabled or send_.holding) {
        RING_WARN("Audio sending disabled");
        if (sender_) {
            if (socketPair_)
                socketPair_->interrupt();
            sender_.reset();
        }
        return;
    }

    if (sender_)
        RING_WARN("Restarting audio sender");


    // be sure to not send any packets before saving last RTP seq value
    socketPair_->stopSendOp();
    if (sender_)
        initSeqVal_ = sender_->getLastSeqValue() + 1;
    try {
        sender_.reset();
        socketPair_->stopSendOp(false);
        sender_.reset(new AudioSender(callID_, getRemoteRtpUri(), send_,
                                      *socketPair_, initSeqVal_, muteState_, mtu_));
    } catch (const MediaEncoderException &e) {
        RING_ERR("%s", e.what());
        send_.enabled = false;
    }
}
Esempio n. 7
0
void
SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
{
    if (not inv or not inv->dlg)
        throw VoipLinkException("Couldn't get invite dialog");

    pj_str_t methodName = CONST_PJ_STR("INFO");
    pjsip_method method;
    pjsip_method_init_np(&method, &methodName);

    /* Create request message. */
    pjsip_tx_data *tdata;

    if (pjsip_dlg_create_request(inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) {
        RING_ERR("[call:%s] Could not create dialog", getCallId().c_str());
        return;
    }

    /* Create "application/<subtype>" message body. */
    pj_str_t content;
    pj_cstr(&content, body);
    const pj_str_t type = CONST_PJ_STR("application");
    pj_str_t pj_subtype;
    pj_cstr(&pj_subtype, subtype);
    tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &pj_subtype, &content);

    if (tdata->msg->body == NULL)
        pjsip_tx_data_dec_ref(tdata);
    else
        pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
}
bool
AudioSender::setup(SocketPair& socketPair)
{
    audioEncoder_.reset(new MediaEncoder);
    muxContext_.reset(socketPair.createIOContext(mtu_));

    try {
        /* Encoder setup */
        RING_DBG("audioEncoder_->openOutput %s", dest_.c_str());
        audioEncoder_->setMuted(muteState_);
        audioEncoder_->openOutput(dest_.c_str(), args_);
        audioEncoder_->setInitSeqVal(seqVal_);
        audioEncoder_->setIOContext(muxContext_);
        audioEncoder_->startIO();
    } catch (const MediaEncoderException &e) {
        RING_ERR("%s", e.what());
        return false;
    }

#ifdef DEBUG_SDP
    audioEncoder_->print_sdp();
#endif

    return true;
}
Esempio n. 9
0
int
tapdisk_xenblkif_disconnect(const domid_t domid, const int devid)
{
    struct td_xenblkif *blkif;

    blkif = tapdisk_xenblkif_find(domid, devid);
    if (!blkif)
        return -ENODEV;

    if (tapdisk_xenblkif_reqs_pending(blkif)) {
        RING_DEBUG(blkif, "disconnect from ring with %d pending requests\n",
                blkif->ring_size - blkif->n_reqs_free);
		if (td_flag_test(blkif->vbd->state, TD_VBD_PAUSED))
			RING_ERR(blkif, "disconnect from ring with %d pending requests "
                    "and the VBD paused\n",
                    blkif->ring_size - blkif->n_reqs_free);
        list_move(&blkif->entry, &blkif->vbd->dead_rings);
        blkif->dead = true;
        if (blkif->ctx && blkif->port >= 0) {
            xc_evtchn_unbind(blkif->ctx->xce_handle, blkif->port);
            blkif->port = -1;
        }
        /*
         * FIXME shall we unmap the ring or will that lead to some fatal error
         * in tapdisk? IIUC if we don't unmap it we'll get errors during grant
         * copy.
         */
        return 0;
	} else
        return tapdisk_xenblkif_destroy(blkif);
}
Esempio n. 10
0
void
ShmHolder::renderFrame(VideoFrame& src) noexcept
{
    const auto width = src.width();
    const auto height = src.height();
    const auto format = VIDEO_PIXFMT_BGRA;
    const auto frameSize = videoFrameSize(format, width, height);

    if (!resizeArea(frameSize)) {
        RING_ERR("ShmHolder[%s]: could not resize area",
                 openedName_.c_str());
        return;
    }

    {
        VideoFrame dst;
        VideoScaler scaler;

        dst.setFromMemory(area_->data + area_->writeOffset, format, width, height);
        scaler.scale(src, dst);
    }

    {
        SemGuardLock lk {area_->mutex};

        ++area_->frameGen;
        std::swap(area_->readOffset, area_->writeOffset);
        ::sem_post(&area_->frameGenMutex);
    }
}
Esempio n. 11
0
std::shared_ptr<TlsListener>
SipTransportBroker::getTlsListener(const SipTransportDescr& d, const pjsip_tls_setting* settings)
{
    RETURN_IF_FAIL(settings, nullptr, "TLS settings not specified");
    auto family = pjsip_transport_type_get_af(d.type);

    IpAddr listeningAddress = (d.interface == ip_utils::DEFAULT_INTERFACE) ?
        ip_utils::getAnyHostAddr(family) :
        ip_utils::getInterfaceAddr(d.interface, family);
    listeningAddress.setPort(d.listenerPort);

    RETURN_IF_FAIL(listeningAddress, nullptr, "Could not determine IP address for this transport");
    RING_DBG("Creating TLS listener %s on %s...", d.toString().c_str(), listeningAddress.toString(true).c_str());
#if 0
    RING_DBG(" ca_list_file : %s", settings->ca_list_file.ptr);
    RING_DBG(" cert_file    : %s", settings->cert_file.ptr);
    RING_DBG(" ciphers_num    : %d", settings->ciphers_num);
    RING_DBG(" verify server %d client %d client_cert %d", settings->verify_server, settings->verify_client, settings->require_client_cert);
    RING_DBG(" reuse_addr    : %d", settings->reuse_addr);
#endif

    pjsip_tpfactory *listener = nullptr;
    const pj_status_t status = pjsip_tls_transport_start2(endpt_, settings, listeningAddress.pjPtr(), nullptr, 1, &listener);
    if (status != PJ_SUCCESS) {
        RING_ERR("TLS listener did not start: %s", sip_utils::sip_strerror(status).c_str());
        return nullptr;
    }
    return std::make_shared<TlsListener>(listener);
}
Esempio n. 12
0
bool
HardwareAccel::extractData(VideoFrame& input)
{
    try {
        auto inFrame = input.pointer();

        if (inFrame->format != format_) {
            std::stringstream buf;
            buf << "Frame format mismatch: expected " << av_get_pix_fmt_name(format_);
            buf << ", got " << av_get_pix_fmt_name((AVPixelFormat)inFrame->format);
            throw std::runtime_error(buf.str());
        }

        // FFmpeg requires a second frame in which to transfer the data
        // from the GPU buffer to the main memory
        auto output = std::unique_ptr<VideoFrame>(new VideoFrame());
        auto outFrame = output->pointer();
        outFrame->format = AV_PIX_FMT_YUV420P;

        extractData(input, *output);

        // move outFrame into inFrame so the caller receives extracted image data
        // but we have to delete inFrame first
        av_frame_unref(inFrame);
        av_frame_move_ref(inFrame, outFrame);
    } catch (const std::runtime_error& e) {
        fail(false);
        RING_ERR("%s", e.what());
        return false;
    }

    succeed();
    return true;
}
Esempio n. 13
0
std::vector<std::string>
ip_utils::getAllIpInterfaceByName()
{
    std::vector<std::string> ifaceList;
    ifaceList.push_back("default");
#ifndef _WIN32
    static ifreq ifreqs[20];
    ifconf ifconf;

    ifconf.ifc_buf = (char*) (ifreqs);
    ifconf.ifc_len = sizeof(ifreqs);

    int sock = socket(AF_INET6, SOCK_STREAM, 0);

    if (sock >= 0) {
        if (ioctl(sock, SIOCGIFCONF, &ifconf) >= 0)
            for (unsigned i = 0; i < ifconf.ifc_len / sizeof(ifreq); ++i)
                ifaceList.push_back(std::string(ifreqs[i].ifr_name));

        close(sock);
    }

#else
        RING_ERR("Not implemented yet. (iphlpapi.h problem)");
#endif
    return ifaceList;
}
Esempio n. 14
0
void
AudioStream::stateChanged(pa_stream* s)
{
    UNUSED char str[PA_SAMPLE_SPEC_SNPRINT_MAX];

    switch (pa_stream_get_state(s)) {
        case PA_STREAM_CREATING:
            RING_DBG("Stream is creating...");
            break;

        case PA_STREAM_TERMINATED:
            RING_DBG("Stream is terminating...");
            break;

        case PA_STREAM_READY:
            RING_DBG("Stream successfully created, connected to %s", pa_stream_get_device_name(s));
            //RING_DBG("maxlength %u", pa_stream_get_buffer_attr(s)->maxlength);
            //RING_DBG("tlength %u", pa_stream_get_buffer_attr(s)->tlength);
            //RING_DBG("prebuf %u", pa_stream_get_buffer_attr(s)->prebuf);
            //RING_DBG("minreq %u", pa_stream_get_buffer_attr(s)->minreq);
            //RING_DBG("fragsize %u", pa_stream_get_buffer_attr(s)->fragsize);
            //RING_DBG("samplespec %s", pa_sample_spec_snprint(str, sizeof(str), pa_stream_get_sample_spec(s)));
            break;

        case PA_STREAM_UNCONNECTED:
            RING_DBG("Stream unconnected");
            break;

        case PA_STREAM_FAILED:
        default:
            RING_ERR("Stream failure: %s" , pa_strerror(pa_context_errno(pa_stream_get_context(s))));
            break;
    }
}
Esempio n. 15
0
void
VideoInput::createDecoder()
{
    deleteDecoder();

    switchPending_ = false;

    if (decOpts_.input.empty()) {
        foundDecOpts(decOpts_);
        return;
    }

    auto decoder = std::unique_ptr<MediaDecoder>(new MediaDecoder());

    if (emulateRate_)
        decoder->emulateRate();

    decoder->setInterruptCallback(
        [](void* data) -> int { return not static_cast<VideoInput*>(data)->isCapturing(); },
        this);

    if (decoder->openInput(decOpts_) < 0) {
        RING_ERR("Could not open input \"%s\"", decOpts_.input.c_str());
        foundDecOpts(decOpts_);
        return;
    }

    /* Data available, finish the decoding */
    if (decoder->setupFromVideoData() < 0) {
        RING_ERR("decoder IO startup failed");
        foundDecOpts(decOpts_);
        return;
    }

    decOpts_.width = decoder->getWidth();
    decOpts_.height = decoder->getHeight();
    decOpts_.framerate = decoder->getFps();

    RING_DBG("created decoder with video params : size=%dX%d, fps=%lf",
             decOpts_.width, decOpts_.height, decOpts_.framerate.real());

    decoder_ = std::move(decoder);
    foundDecOpts(decOpts_);

    /* Signal the client about readable sink */
    sink_->setFrameSize(decoder_->getWidth(), decoder_->getHeight());
}
Esempio n. 16
0
Controller::Controller()
{
    try {
        upnpContext_ = getUPnPContext();
    } catch (std::runtime_error& e) {
        RING_ERR("UPnP context error: %s", e.what());
    }
}
Esempio n. 17
0
int
SIPCall::SIPSessionReinvite()
{
    // Do nothing if no invitation processed yet
    if (not inv or inv->invite_tsx)
        return PJ_SUCCESS;

    RING_DBG("[call:%s] Processing reINVITE (state=%s)", getCallId().c_str(),
             pjsip_inv_state_name(inv->state));

    // Generate new ports to receive the new media stream
    // LibAV doesn't discriminate SSRCs and will be confused about Seq changes on a given port
    generateMediaPorts();
    sdp_->clearIce();
    auto& acc = getSIPAccount();
    if (not sdp_->createOffer(acc.getActiveAccountCodecInfoList(MEDIA_AUDIO),
                              acc.getActiveAccountCodecInfoList(acc.isVideoEnabled() ? MEDIA_VIDEO : MEDIA_NONE),
                              acc.getSrtpKeyExchange(),
                              getState() == CallState::HOLD))
        return !PJ_SUCCESS;

    if (initIceTransport(true))
        setupLocalSDPFromIce();

    pjsip_tx_data* tdata;
    auto local_sdp = sdp_->getLocalSdpSession();
    auto result = pjsip_inv_reinvite(inv.get(), nullptr, local_sdp, &tdata);
    if (result == PJ_SUCCESS) {
        if (!tdata)
            return PJ_SUCCESS;
        result = pjsip_inv_send_msg(inv.get(), tdata);
        if (result == PJ_SUCCESS)
            return PJ_SUCCESS;
        RING_ERR("[call:%s] Failed to send REINVITE msg (pjsip: %s)", getCallId().c_str(),
                 sip_utils::sip_strerror(result).c_str());
        // Canceling internals without sending (anyways the send has just failed!)
        pjsip_inv_cancel_reinvite(inv.get(), &tdata);
    } else
        RING_ERR("[call:%s] Failed to create REINVITE msg (pjsip: %s)", getCallId().c_str(),
                 sip_utils::sip_strerror(result).c_str());

    return !PJ_SUCCESS;
}
Esempio n. 18
0
JackLayer::~JackLayer()
{
    stopStream();

    for (auto p : out_ports_)
        jack_port_unregister(playbackClient_, p);
    for (auto p : in_ports_)
        jack_port_unregister(captureClient_, p);

    if (jack_client_close(playbackClient_))
        RING_ERR("JACK client could not close");
    if (jack_client_close(captureClient_))
        RING_ERR("JACK client could not close");

    for (auto r : out_ringbuffers_)
        jack_ringbuffer_free(r);
    for (auto r : in_ringbuffers_)
        jack_ringbuffer_free(r);
}
Esempio n. 19
0
void
RingBuffer::storeReadOffset(size_t offset, const std::string &call_id)
{
    ReadOffset::iterator iter = readoffsets_.find(call_id);

    if (iter != readoffsets_.end())
        iter->second = offset;
    else
        RING_ERR("RingBuffer::storeReadOffset() failed: unknown call '%s'", call_id.c_str());
}
Esempio n. 20
0
void
AccountFactory::removeAccount(const std::string& id)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);

    if (auto account = getAccount(id)) {
        removeAccount(*account);
    } else
        RING_ERR("No account with ID %s", id.c_str());
}
Esempio n. 21
0
static void
convertFromFloat(std::vector<float> &src, std::vector<AudioSample> &dest)
{
    if (dest.size() != src.size()) {
        RING_ERR("MISMATCH");
        return;
    }
    for (size_t i = 0; i < dest.size(); ++i)
        dest[i] = src[i] * SHRT_MAX;
}
Esempio n. 22
0
void
AudioSender::process()
{
    auto& mainBuffer = Manager::instance().getRingBufferPool();
    auto mainBuffFormat = mainBuffer.getInternalAudioFormat();

    // compute nb of byte to get corresponding to 1 audio frame
    const std::size_t samplesToGet = std::chrono::duration_cast<std::chrono::seconds>(mainBuffFormat.sample_rate * secondsPerPacket_).count();

    if (mainBuffer.availableForGet(id_) < samplesToGet) {
        const auto wait_time = std::chrono::duration_cast<std::chrono::milliseconds>(secondsPerPacket_);
        if (not mainBuffer.waitForDataAvailable(id_, samplesToGet, wait_time))
            return;
    }

    // get data
    micData_.setFormat(mainBuffFormat);
    micData_.resize(samplesToGet);
    const auto samples = mainBuffer.getData(micData_, id_);
    if (samples != samplesToGet)
        return;

    // down/upmix as needed
    auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec);
    micData_.setChannelNum(accountAudioCodec->audioformat.nb_channels, true);

    if (mainBuffFormat.sample_rate != accountAudioCodec->audioformat.sample_rate) {
        if (not resampler_) {
            RING_DBG("Creating audio resampler");
            resampler_.reset(new Resampler(accountAudioCodec->audioformat));
        }
        resampledData_.setFormat(accountAudioCodec->audioformat);
        resampledData_.resize(samplesToGet);
        resampler_->resample(micData_, resampledData_);
        Smartools::getInstance().setLocalAudioCodec(audioEncoder_->getEncoderName());
        if (audioEncoder_->encode_audio(resampledData_) < 0)
            RING_ERR("encoding failed");
    } else {
        if (audioEncoder_->encode_audio(micData_) < 0)
            RING_ERR("encoding failed");
    }
}
Esempio n. 23
0
static void
convertToFloat(const std::vector<AudioSample> &src, std::vector<float> &dest)
{
    static const float INV_SHORT_MAX = 1 / (float) SHRT_MAX;
    if (dest.size() != src.size()) {
        RING_ERR("MISMATCH");
        return;
    }
    for (size_t i = 0; i < dest.size(); ++i)
        dest[i] = src[i] * INV_SHORT_MAX;
}
Esempio n. 24
0
void Conference::add(const std::string &participant_id)
{
    if (participants_.insert(participant_id).second) {
#ifdef RING_VIDEO
        if (auto call = Manager::instance().callFactory.getCall<SIPCall>(participant_id))
            call->getVideoRtp().enterConference(this);
        else
            RING_ERR("no call associate to participant %s", participant_id.c_str());
#endif // RING_VIDEO
    }
}
Esempio n. 25
0
void
HardwareAccel::fail(bool forceFallback)
{
    ++failCount_;
    if (failCount_ >= MAX_ACCEL_FAILURES || forceFallback) {
        RING_ERR("Hardware acceleration failure");
        fallback_ = true;
        failCount_ = 0;
        codecCtx_->get_format = avcodec_default_get_format;
        codecCtx_->get_buffer2 = avcodec_default_get_buffer2;
    }
}
Esempio n. 26
0
JackLayer::JackLayer(const AudioPreference &p) :
    AudioLayer(p),
    captureClient_(nullptr),
    playbackClient_(nullptr),
    out_ports_(),
    in_ports_(),
    out_ringbuffers_(),
    in_ringbuffers_(),
    ringbuffer_thread_(),
    //workerAlive_(false),
    ringbuffer_thread_mutex_(),
    data_ready_(),
    playbackBuffer_(0, audioFormat_),
    playbackFloatBuffer_(),
    captureBuffer_(0, audioFormat_),
    captureFloatBuffer_(),
    hardwareBufferSize_(0),
    mainRingBuffer_(Manager::instance().getRingBufferPool().getRingBuffer(RingBufferPool::DEFAULT_ID))
{
    playbackClient_ = jack_client_open(PACKAGE_NAME,
            (jack_options_t) (JackNullOption | JackNoStartServer), NULL);
    if (!playbackClient_)
        throw std::runtime_error("Could not open JACK client");

    captureClient_ = jack_client_open(PACKAGE_NAME,
            (jack_options_t) (JackNullOption | JackNoStartServer), NULL);
    if (!captureClient_)
        throw std::runtime_error("Could not open JACK client");

    jack_set_process_callback(captureClient_, process_capture, this);
    jack_set_process_callback(playbackClient_, process_playback, this);

    createPorts(playbackClient_, out_ports_, true, out_ringbuffers_);
    createPorts(captureClient_, in_ports_, false, in_ringbuffers_);

    const auto playRate = jack_get_sample_rate(playbackClient_);
    const auto captureRate = jack_get_sample_rate(captureClient_);
    if (playRate != captureRate)
        RING_ERR("Mismatch between capture rate %u and playback rate %u", playRate, captureRate);

    hardwareBufferSize_ = jack_get_buffer_size(playbackClient_);

    auto update_buffer = [] (AudioBuffer &buf, size_t size, unsigned rate, unsigned nbChannels) {
        buf.setSampleRate(rate);
        buf.resize(size);
        buf.setChannelNum(nbChannels);
    };

    update_buffer(playbackBuffer_, hardwareBufferSize_, playRate, out_ports_.size());
    update_buffer(captureBuffer_, hardwareBufferSize_, captureRate, in_ports_.size());

    jack_on_shutdown(playbackClient_, onShutdown, this);
}
Esempio n. 27
0
bool
SinkClient::start() noexcept
{
    if (not shm_) {
        try {
            shm_ = std::make_shared<ShmHolder>();
        } catch (const std::runtime_error& e) {
            RING_ERR("SHMHolder ctor failure: %s", e.what());
        }
    }
    return static_cast<bool>(shm_);
}
void
RingBufferPool::unBindCallID(const std::string& call_id1,
                         const std::string& call_id2)
{
    const auto& rb_call1 = getRingBuffer(call_id1);
    if (not rb_call1) {
        RING_ERR("No ringbuffer associated to call '%s'", call_id1.c_str());
        return;
    }

    const auto& rb_call2 = getRingBuffer(call_id2);
    if (not rb_call2) {
        RING_ERR("No ringbuffer associated to call '%s'", call_id2.c_str());
        return;
    }

    std::lock_guard<std::recursive_mutex> lk(stateLock_);

    removeReaderFromRingBuffer(rb_call1, call_id2);
    removeReaderFromRingBuffer(rb_call2, call_id1);
}
Esempio n. 29
0
void
AudioReceiveThread::process()
{
    AudioFormat mainBuffFormat = Manager::instance().getRingBufferPool().getInternalAudioFormat();
    AudioFrame decodedFrame;

    switch (audioDecoder_->decode(decodedFrame)) {

        case MediaDecoder::Status::FrameFinished:
            audioDecoder_->writeToRingBuffer(decodedFrame, *ringbuffer_,
                                             mainBuffFormat);
            // Refresh the remote audio codec in the callback SmartInfo
            Smartools::getInstance().setRemoteAudioCodec(audioDecoder_->getDecoderName());
            return;

        case MediaDecoder::Status::DecodeError:
            RING_WARN("decoding failure, trying to reset decoder...");
            if (not setup()) {
                RING_ERR("fatal error, rx thread re-setup failed");
                loop_.stop();
                break;
            }
            if (not audioDecoder_->setupFromAudioData(format_)) {
                RING_ERR("fatal error, a-decoder setup failed");
                loop_.stop();
                break;
            }
            break;

        case MediaDecoder::Status::ReadError:
            RING_ERR("fatal error, read failed");
            loop_.stop();
            break;

        case MediaDecoder::Status::Success:
        case MediaDecoder::Status::EOFError:
        default:
            break;
    }
}
void
VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
{
    if (params.width and params.height) {
        auto pmt = capMap_.at(std::make_pair(params.width, params.height));
        if (pmt != nullptr) {
            ((VIDEOINFOHEADER*) pmt->pbFormat)->AvgTimePerFrame = (FrameRate(1e7) / params.framerate).real();
            if (FAILED(cInterface->streamConf_->SetFormat(pmt))) {
                RING_ERR("Could not set settings.");
            }
        }
    }
}