diff --git a/ChangeLog b/ChangeLog index 642e3492c5f75c1c0648f9258a693f779c35bf2e..157ded7cb9c8843ce2a343eead42d9e86b902600 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,2 @@ -2.0.0 (2015-03-31) ------------------- - -First DRing release (formely SFLPhone - released as 1.4.1) +This file is not used for logging changes but to satisfies autotool requirements. +Please, read NEWS file for changes. diff --git a/NEWS b/NEWS index f761319d22ef461aad85c176359550712e279f42..091ae3d3357551db25e910ce28f46b1b79d2dd4e 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,12 @@ -DRing (2.0.0) / 2015-03-31 +DRing (2.0.1) / 2015-03-27 + * Add FPS calculation for streamed files + * Set defaults video bitrate to 800 Kb/s + * Use RGBA for direct rendering (MacOSX) + * MacOSX: force video device format on supported values + * SecureSIP: fix race condition and incoming packet handling + * minor documentation fixes + +DRing (2.0.0) / 2015-03-25 * Project renaming * First release under this name * Ring account (DHT) introduced diff --git a/configure.ac b/configure.ac index fb75c5fab0df58bb49d83d260ce1530e79c8a89c..885a4e4ad1169c01ebb532e003ccfa4ded4f856a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Ring - configure.ac for automake 1.9 and autoconf 2.59 dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([Ring],[2.0.0],[ring@lists.savoirfairelinux.net],[ring]) +AC_INIT([Ring],[2.0.1],[ring@lists.savoirfairelinux.net],[ring]) AC_COPYRIGHT([[Copyright (c) Savoir-Faire Linux 2004-2015]]) AC_REVISION([$Revision$]) diff --git a/contrib/src/libav/osx.patch b/contrib/src/libav/osx.patch index 4f885fd6d14fe20309ff7304a90618ad39dac25d..b2632429d224bc90b2e6d4b90c427cefe02d2c3f 100644 --- a/contrib/src/libav/osx.patch +++ b/contrib/src/libav/osx.patch @@ -242,10 +242,10 @@ index 5dbe277..8439b5b 100644 REGISTER_INDEV (FBDEV, fbdev); diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m new file mode 100644 -index 0000000..f1b9c03 +index 0000000..6b60782 --- /dev/null +++ b/libavdevice/avfoundation_dec.m -@@ -0,0 +1,447 @@ +@@ -0,0 +1,517 @@ +/* + * AVFoundation input device + * Copyright (c) 2015 Luca Barbato @@ -281,13 +281,47 @@ index 0000000..f1b9c03 + +#include "avdevice.h" + ++struct AVFPixelFormatSpec { ++ enum AVPixelFormat ff_id; ++ OSType avf_id; ++}; ++ ++static const struct AVFPixelFormatSpec avf_pixel_formats[] = { ++ { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome }, ++ { AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 }, ++ { AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 }, ++ { AV_PIX_FMT_RGB565BE, kCVPixelFormatType_16BE565 }, ++ { AV_PIX_FMT_RGB565LE, kCVPixelFormatType_16LE565 }, ++ { AV_PIX_FMT_RGB24, kCVPixelFormatType_24RGB }, ++ { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR }, ++ { AV_PIX_FMT_ARGB, kCVPixelFormatType_32ARGB }, ++ { AV_PIX_FMT_BGRA, kCVPixelFormatType_32BGRA }, ++ { AV_PIX_FMT_ABGR, kCVPixelFormatType_32ABGR }, ++ { AV_PIX_FMT_RGBA, kCVPixelFormatType_32RGBA }, ++ { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB }, ++ { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 }, ++ { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R }, ++ { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 }, ++ { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 }, ++ { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 }, ++ { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 }, ++ { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 }, ++ { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar }, ++ { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange }, ++ { AV_PIX_FMT_YUYV422, kCVPixelFormatType_422YpCbCr8_yuvs }, ++#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 ++ { AV_PIX_FMT_GRAY8, kCVPixelFormatType_OneComponent8 }, ++#endif ++ { AV_PIX_FMT_NONE, 0 } ++}; ++ +typedef struct AVFoundationCaptureContext { + AVClass *class; + int list_devices; + CFTypeRef session; /** AVCaptureSession*/ + char* video_size; /**< String describing video size, + set by a private option. */ -+ char* pixel_format; /**< Set by a private option. */ ++ enum AVPixelFormat pixel_format; /**< Set by a private option. */ + int list_format; /**< Set by a private option. */ + char* framerate; /**< Set by a private option. */ + @@ -442,9 +476,46 @@ index 0000000..f1b9c03 + } + + [out setAlwaysDiscardsLateVideoFrames:YES]; -+ out.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; + -+ //[out setVideoSettings:nil]; ++ ++ // select pixel format ++ struct AVFPixelFormatSpec pxl_fmt_spec; ++ pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE; ++ ++ av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n"); ++ for (NSNumber *pxl_fmt in [out availableVideoCVPixelFormatTypes]) { ++ struct AVFPixelFormatSpec pxl_fmt_dummy; ++ pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE; ++ for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) { ++ if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) { ++ pxl_fmt_dummy = avf_pixel_formats[i]; ++ break; ++ } ++ } ++ ++ if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) { ++ av_log(s, AV_LOG_ERROR, " %s: %d \n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id), ++ pxl_fmt_dummy.avf_id); ++ ++ // select first supported pixel format instead of user selected (or default) pixel format ++ if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) { ++ pxl_fmt_spec = pxl_fmt_dummy; ++ } ++ } ++ } ++ ++ // fail if there is no appropriate pixel format or print a warning about overriding the pixel format ++ if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) { ++ return 1; ++ } else { ++ av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n", ++ av_get_pix_fmt_name(pxl_fmt_spec.ff_id)); ++ } ++ ctx->pixel_format = pxl_fmt_spec.ff_id; ++ NSNumber *pixel_format = [NSNumber numberWithUnsignedInt:pxl_fmt_spec.avf_id]; ++ NSDictionary *capture_dict = [NSDictionary dictionaryWithObject:pixel_format ++ forKey:(id)kCVPixelBufferPixelFormatTypeKey]; ++ [out setVideoSettings:capture_dict]; + + AVFFrameReceiver* delegate = [[AVFFrameReceiver alloc] initWithContext:ctx]; + @@ -507,8 +578,7 @@ index 0000000..f1b9c03 + stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; + stream->codec->width = (int)image_buffer_size.width; + stream->codec->height = (int)image_buffer_size.height; -+ // No support for pixel formats for now using default one -+ stream->codec->pix_fmt = AV_PIX_FMT_BGR32; ++ stream->codec->pix_fmt = ctx->pixel_format; + + CFRelease(ctx->current_frame); + ctx->current_frame = nil; @@ -527,7 +597,6 @@ index 0000000..f1b9c03 + + ctx->session = NULL; + -+ + pthread_mutex_destroy(&ctx->frame_lock); + pthread_cond_destroy(&ctx->frame_wait_cond); + @@ -585,7 +654,8 @@ index 0000000..f1b9c03 + if (matches.count > 0) { + for (NSTextCheckingResult *match in matches) { + NSRange range = [match rangeAtIndex:0]; -+ NSString *uniqueID = [filename substringWithRange:NSMakeRange(range.location + 1, range.length-2)]; av_log(s, AV_LOG_INFO, "opening device with ID: %s\n",[uniqueID UTF8String]); ++ NSString *uniqueID = [filename substringWithRange:NSMakeRange(range.location + 1, range.length-2)]; ++ av_log(s, AV_LOG_INFO, "opening device with ID: %s\n",[uniqueID UTF8String]); + if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) { + // report error + av_log(s, AV_LOG_ERROR, "Device with name %s not found",[filename UTF8String]); diff --git a/doc/doxygen/core-doc.cfg.in b/doc/doxygen/core-doc.cfg.in index d25075a3ab5da7617e494b104b7d5127607cea23..764a06e92425c230d4b8c596bba7f9aa8627e2f5 100644 --- a/doc/doxygen/core-doc.cfg.in +++ b/doc/doxygen/core-doc.cfg.in @@ -31,7 +31,7 @@ PROJECT_NAME = "Ring Daemon" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 2.0.0 +PROJECT_NUMBER = 2.0.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer diff --git a/src/account.cpp b/src/account.cpp index b042077de4e856bedda4e3dea9789ae135752ca6..2d713a86ba764d26bb5d7da19845081cd28a23be 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -335,11 +335,6 @@ Account::setActiveCodecs(const std::vector<unsigned>& list) }); allCodecStr_ = join_string(getActiveAccountCodecInfoIdList(MEDIA_ALL)); - - for (const auto& item : accountCodecInfoList_) - RING_DBG("[%s] order:%d, isActive=%s, codec=%s", accountID_.c_str(), - item->order, (item->isActive ? "true" : "false"), - item->systemCodecInfo.to_string().c_str()); } std::string diff --git a/src/media/libav_utils.cpp b/src/media/libav_utils.cpp index 95af5d2080336c1a4c80c54ab2d4eec8f5f5bbc6..e77cdf7a8534588f9aadfd758c9637d1bd470543 100644 --- a/src/media/libav_utils.cpp +++ b/src/media/libav_utils.cpp @@ -107,6 +107,7 @@ int libav_pixel_format(int fmt) { switch (fmt) { case video::VIDEO_PIXFMT_BGRA: return PIXEL_FORMAT(BGRA); + case video::VIDEO_PIXFMT_RGBA: return PIXEL_FORMAT(RGBA); case video::VIDEO_PIXFMT_YUV420P: return PIXEL_FORMAT(YUV420P); } return fmt; diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index c92564146730f82e7a0d931c525e0e1e3b948977..e24b368a2fa5854b5401facf7a48849787a59285 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -250,7 +250,8 @@ int MediaDecoder::setupFromVideoData() } // Get a pointer to the codec context for the video stream - decoderCtx_ = inputCtx_->streams[streamIndex_]->codec; + avStream_ = inputCtx_->streams[streamIndex_]; + decoderCtx_ = avStream_->codec; if (decoderCtx_ == 0) { RING_ERR("Decoder context is NULL"); return -1; @@ -428,6 +429,14 @@ int MediaDecoder::getWidth() const int MediaDecoder::getHeight() const { return decoderCtx_->height; } +int // TODO : use of float fps is more accurate +MediaDecoder::getFps() const +{ + return (avStream_->avg_frame_rate.den != 0 ? + (int)(avStream_->avg_frame_rate.num / avStream_->avg_frame_rate.den) + : 0); +} + int MediaDecoder::getPixelFormat() const { return libav_utils::ring_pixel_format(decoderCtx_->pix_fmt); } diff --git a/src/media/media_decoder.h b/src/media/media_decoder.h index 91f65194f88bacb3240342358b23455f357017f2..0a20a3aa3c1b1e2b99e6db0f9efd0afeabbffb25 100644 --- a/src/media/media_decoder.h +++ b/src/media/media_decoder.h @@ -99,6 +99,7 @@ class MediaDecoder { int getWidth() const; int getHeight() const; + int getFps() const; int getPixelFormat() const; void setOptions(const std::map<std::string, std::string>& options); @@ -109,6 +110,7 @@ class MediaDecoder { AVCodec *inputDecoder_ = nullptr; AVCodecContext *decoderCtx_ = nullptr; AVFormatContext *inputCtx_ = nullptr; + AVStream *avStream_ = nullptr; std::unique_ptr<Resampler> resampler_; int streamIndex_ = -1; bool emulateRate_ = false; diff --git a/src/media/system_codec_container.cpp b/src/media/system_codec_container.cpp index 66d41336cafeb5551a7743012fe998ddff9ad85c..4ce6b09f44a4f0d3a0efbd2486a1f6c8e84a562c 100644 --- a/src/media/system_codec_container.cpp +++ b/src/media/system_codec_container.cpp @@ -40,7 +40,7 @@ namespace ring { decltype(getGlobalInstance<SystemCodecContainer>)& getSystemCodecContainer = getGlobalInstance<SystemCodecContainer>; -constexpr static auto DEFAULT_VIDEO_BITRATE = 400; +constexpr static auto DEFAULT_VIDEO_BITRATE = 800; // in Kbits/second SystemCodecContainer::SystemCodecContainer() { diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp index 94664c3295812f8624d1d80acf4206023906242d..994d4d18023fb81f17ae2b3374e788a8a643ece8 100644 --- a/src/media/video/sinkclient.cpp +++ b/src/media/video/sinkclient.cpp @@ -316,7 +316,7 @@ SinkClient::update(Observable<std::shared_ptr<VideoFrame>>* /*obs*/, VideoScaler scaler; const int width = f->width(); const int height = f->height(); - const int format = VIDEO_PIXFMT_BGRA; + const int format = VIDEO_PIXFMT_RGBA; const auto bytes = videoFrameSize(format, width, height); targetData_.resize(bytes); diff --git a/src/media/video/video_base.h b/src/media/video/video_base.h index cd6dbad4e1923f87525f4f75f0c6b34480789484..e7299db06050f4526192e521fc3ed1696f6389a0 100644 --- a/src/media/video/video_base.h +++ b/src/media/video/video_base.h @@ -58,6 +58,7 @@ namespace ring { namespace video { enum VideoPixelFormat { VIDEO_PIXFMT_BGRA = -1, VIDEO_PIXFMT_YUV420P = -2, + VIDEO_PIXFMT_RGBA = -3, }; template <typename T> class Observer; diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp index a3d5a7b4dcb322c0ce015b2fc9327d8254b2880d..c11f19524c8beb496eb1e7aaafaef7308874e5f1 100644 --- a/src/media/video/video_input.cpp +++ b/src/media/video/video_input.cpp @@ -185,6 +185,11 @@ VideoInput::createDecoder() } decOpts_.width = decoder_->getWidth(); decOpts_.height = decoder_->getHeight(); + decOpts_.framerate = decoder_->getFps(); + RING_INFO("create decoder with video params : size=%dX%d, fps=%d", + decOpts_.width, + decOpts_.height, + decOpts_.framerate); foundDecOpts(decOpts_); } @@ -266,9 +271,6 @@ VideoInput::initFile(std::string path) decOpts_.framerate = 1; } else { RING_WARN("Guessing file type for %s", path.c_str()); - // FIXME: proper parsing of FPS etc. should be done in - // MediaDecoder, not here. - decOpts_.framerate = 25; } return true; diff --git a/src/ringdht/sips_transport_ice.cpp b/src/ringdht/sips_transport_ice.cpp index db3d54b7c6a7f38c4304ccb999fd35b2f8abbe68..c9de6027205bfda1d1ff781a491247dc6d7717c7 100644 --- a/src/ringdht/sips_transport_ice.cpp +++ b/src/ringdht/sips_transport_ice.cpp @@ -659,10 +659,14 @@ SipsIceTransport::setup() void SipsIceTransport::handleEvents() { - std::lock_guard<std::mutex> l(rxMtx_); - while (not rxPending_.empty()) { - auto pck_it = rxPending_.begin(); - auto& pck = *pck_it; + decltype(rxPending_) rx; + { + std::lock_guard<std::mutex> l(rxMtx_); + rx = std::move(rxPending_); + } + + for (auto it = rx.begin(); it != rx.end(); ++it) { + auto& pck = *it; pj_pool_reset(rdata_.tp_info.pool); pj_gettimeofday(&rdata_.pkt_info.timestamp); rdata_.pkt_info.len = pck.size(); @@ -670,21 +674,24 @@ SipsIceTransport::handleEvents() auto eaten = pjsip_tpmgr_receive_packet(trData_.base.tpmgr, &rdata_); if (eaten != rdata_.pkt_info.len) { // partial sip packet received - auto npck_it = std::next(pck_it); - if (npck_it != rxPending_.end()) { + auto npck_it = std::next(it); + if (npck_it != rx.end()) { // drop current packet, merge reminder with next one auto& npck = *npck_it; npck.insert(npck.begin(), pck.begin()+eaten, pck.end()); - rxPendingPool_.splice(rxPendingPool_.end(), rxPending_, pck_it); } else { // erase eaten part, keep reminder pck.erase(pck.begin(), pck.begin()+eaten); + { + std::lock_guard<std::mutex> l(rxMtx_); + rxPending_.splice(rxPending_.begin(), rx, it); + } break; } - } else { - rxPendingPool_.splice(rxPendingPool_.end(), rxPending_, pck_it); } } + putBuff(std::move(rx)); + rxCv_.notify_all(); } void @@ -753,20 +760,22 @@ SipsIceTransport::loop() if (state_ != TlsConnectionState::ESTABLISHED and not getTransportBase()->is_shutdown) return; - while (canRead_) { - std::lock_guard<std::mutex> l(rxMtx_); - if (rxPendingPool_.empty()) - rxPendingPool_.emplace_back(PJSIP_MAX_PKT_LEN); - auto& buf = rxPendingPool_.front(); - buf.resize(PJSIP_MAX_PKT_LEN); + decltype(rxPending_) rx; + while (canRead_ or gnutls_record_check_pending(session_)) { + if (rx.empty()) + getBuff(rx, PJSIP_MAX_PKT_LEN); + auto& buf = rx.front(); const auto decrypted_size = gnutls_record_recv(session_, buf.data(), buf.size()); if (decrypted_size > 0/* || transport error */) { buf.resize(decrypted_size); - rxPending_.splice(rxPending_.end(), rxPendingPool_, rxPendingPool_.begin()); + { + std::lock_guard<std::mutex> l(rxMtx_); + rxPending_.splice(rxPending_.end(), rx, rx.begin()); + } } else if (decrypted_size == 0) { /* EOF */ - shutdown(); + tlsThread_.stop(); break; } else if (decrypted_size == GNUTLS_E_AGAIN or decrypted_size == GNUTLS_E_INTERRUPTED) { @@ -795,6 +804,7 @@ SipsIceTransport::loop() break; } } + putBuff(std::move(rx)); flushOutputBuff(); } } @@ -821,7 +831,17 @@ SipsIceTransport::clean() cookie_key_.data = nullptr; cookie_key_.size = 0; } - rxPendingPool_.clear(); + { + // make sure all incoming packets are reported before closing + std::unique_lock<std::mutex> l(rxMtx_); + rxCv_.wait(l, [&](){ + return rxPending_.empty(); + }); + } + { + std::lock_guard<std::mutex> lk(buffPoolMtx_); + buffPool_.clear(); + } bool event = state_ == TlsConnectionState::ESTABLISHED; closeTlsSession(); @@ -923,19 +943,30 @@ SipsIceTransport::send(pjsip_tx_data *tdata, const pj_sockaddr_t *rem_addr, addr_len==sizeof(pj_sockaddr_in6)), PJ_EINVAL); - tdata->op_key.tdata = tdata; tdata->op_key.token = token; tdata->op_key.callback = callback; - { + if (state_ == TlsConnectionState::ESTABLISHED) { + decltype(txBuff_) tx; + size_t size = tdata->buf.cur - tdata->buf.start; + getBuff(tx, (uint8_t*)tdata->buf.start, (uint8_t*)tdata->buf.cur); + { + std::lock_guard<std::mutex> l(outputBuffMtx_); + txBuff_.splice(txBuff_.end(), std::move(tx)); + } + tdata->op_key.tdata = nullptr; + if (tdata->op_key.callback) + tdata->op_key.callback(getTransportBase(), token, size); + } else { std::lock_guard<std::mutex> l(outputBuffMtx_); + tdata->op_key.tdata = tdata; outputBuff_.emplace_back(DelayedTxData{&tdata->op_key, {}}); if (tdata->msg && tdata->msg->type == PJSIP_REQUEST_MSG) { auto& dtd = outputBuff_.back(); dtd.timeout = clock::now(); dtd.timeout += std::chrono::milliseconds(pjsip_cfg()->tsx.td); } - canWrite_ = true; } + canWrite_ = true; cv_.notify_all(); return PJ_EPENDING; } @@ -944,14 +975,14 @@ pj_status_t SipsIceTransport::flushOutputBuff() { ssize_t status = PJ_SUCCESS; + + // send delayed data first while (true) { DelayedTxData f; { std::lock_guard<std::mutex> l(outputBuffMtx_); - if (outputBuff_.empty()) { - canWrite_ = false; + if (outputBuff_.empty()) break; - } else { f = outputBuff_.front(); outputBuff_.pop_front(); @@ -967,6 +998,30 @@ SipsIceTransport::flushOutputBuff() if (status < 0) break; } + if (status < 0) + return status; + + decltype(txBuff_) tx; + { + std::lock_guard<std::mutex> l(outputBuffMtx_); + tx = std::move(txBuff_); + canWrite_ = false; + } + for (auto it = tx.begin(); it != tx.end(); ++it) { + const auto& msg = *it; + const auto nwritten = gnutls_record_send(session_, msg.data(), msg.size()); + if (nwritten <= 0) { + RING_ERR("gnutls_record_send: %s", gnutls_strerror(nwritten)); + status = tls_status_from_err(nwritten); + { + std::lock_guard<std::mutex> l(outputBuffMtx_); + txBuff_.splice(txBuff_.begin(), tx, it, tx.end()); + canWrite_ = true; + } + break; + } + } + putBuff(std::move(tx)); return status > 0 ? PJ_SUCCESS : (pj_status_t)status; } @@ -1009,6 +1064,40 @@ SipsIceTransport::shutdown() cv_.notify_all(); } +void +SipsIceTransport::getBuff(decltype(buffPool_)& l, const uint8_t* b, const uint8_t* e) +{ + std::lock_guard<std::mutex> lk(buffPoolMtx_); + if (buffPool_.empty()) + l.emplace_back(b, e); + else { + l.splice(l.end(), buffPool_, buffPool_.begin()); + auto& buf = l.back(); + buf.resize(std::distance(b, e)); + std::copy(b, e, buf.begin()); + } +} + +void +SipsIceTransport::getBuff(decltype(buffPool_)& l, const size_t s) +{ + std::lock_guard<std::mutex> lk(buffPoolMtx_); + if (buffPool_.empty()) + l.emplace_back(s); + else { + l.splice(l.end(), buffPool_, buffPool_.begin()); + auto& buf = l.back(); + buf.resize(s); + } +} + +void +SipsIceTransport::putBuff(decltype(buffPool_)&& l) +{ + std::lock_guard<std::mutex> lk(buffPoolMtx_); + buffPool_.splice(buffPool_.end(), l); +} + pj_status_t SipsIceTransport::tls_status_from_err(int err) { diff --git a/src/ringdht/sips_transport_ice.h b/src/ringdht/sips_transport_ice.h index 1517b2e6c5ae059062346402229cd89fdd390c56..f6d5af410d26e2e9ac301526631fac11266bddf7 100644 --- a/src/ringdht/sips_transport_ice.h +++ b/src/ringdht/sips_transport_ice.h @@ -161,13 +161,21 @@ private: ssize_t trySend(pjsip_tx_data_op_key* tdata); pj_status_t flushOutputBuff(); std::list<DelayedTxData> outputBuff_; + std::list<std::vector<uint8_t>> txBuff_; std::mutex outputBuffMtx_; std::mutex rxMtx_; + std::condition_variable_any rxCv_; std::list<std::vector<uint8_t>> rxPending_; - std::list<std::vector<uint8_t>> rxPendingPool_; pjsip_rx_data rdata_; + // data buffer pool + std::list<std::vector<uint8_t>> buffPool_; + std::mutex buffPoolMtx_; + void getBuff(decltype(buffPool_)& l, const uint8_t* b, const uint8_t* e); + void getBuff(decltype(buffPool_)& l, const size_t s); + void putBuff(decltype(buffPool_)&& l); + // GnuTLS <-> ICE ssize_t tlsSend(const void*, size_t); ssize_t tlsRecv(void* d , size_t s);