From 708b44d7d12b3d8840ee31e540a3a4bcc9d7deba Mon Sep 17 00:00:00 2001 From: Tristan Matthews <tristan.matthews@savoirfairelinux.com> Date: Tue, 5 Jun 2012 18:08:05 -0400 Subject: [PATCH] * #12012: video: fix some regressions --- daemon/src/sip/sdp.cpp | 45 ++++++++++------------- daemon/src/sip/sdp.h | 10 ++--- daemon/src/video/libav_utils.cpp | 1 + daemon/src/video/shared_memory.cpp | 8 ++-- daemon/src/video/video_receive_thread.cpp | 36 ++++++++++++++---- daemon/src/video/video_receive_thread.h | 3 +- daemon/src/video/video_rtp_session.cpp | 6 +-- daemon/src/video/video_send_thread.cpp | 14 +++---- 8 files changed, 68 insertions(+), 55 deletions(-) diff --git a/daemon/src/sip/sdp.cpp b/daemon/src/sip/sdp.cpp index 94c33a66e2..6639abdadc 100644 --- a/daemon/src/sip/sdp.cpp +++ b/daemon/src/sip/sdp.cpp @@ -39,6 +39,7 @@ #include "manager.h" #ifdef SFL_VIDEO +#include <algorithm> #include "video/video_endpoint.h" #endif @@ -206,7 +207,7 @@ pjmedia_sdp_media *Sdp::setMediaDescriptorLine(bool audio) std::ostringstream s; s << payload; - pj_strdup2 (memPool_, &med->desc.fmt[i], s.str().c_str()); + pj_strdup2(memPool_, &med->desc.fmt[i], s.str().c_str()); // Add a rtpmap field for each codec // We could add one only for dynamic payloads because the codecs with static RTP payloads @@ -307,26 +308,20 @@ void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med) } #ifdef SFL_VIDEO -void Sdp::setLocalMediaVideoCapabilities(const std::vector<std::string> &videoCodecs) +void Sdp::setLocalMediaVideoCapabilities(const std::vector<std::string> &selectedCodecs) { - if (videoCodecs.empty()) - throw SdpException ("No selected video codec while building local SDP offer"); + if (selectedCodecs.empty()) + throw SdpException("No selected video codec while building local SDP offer"); video_codec_list_.clear(); const std::vector<std::string> &codecs_list = sfl_video::getCodecList(); - for (unsigned i = 0; i < videoCodecs.size(); ++i) { - const std::string &codec = videoCodecs[i]; - for (unsigned j = 0; j < codecs_list.size(); ++j) { - if (codecs_list[j] == codec) { - video_codec_list_.push_back(codec); - break; - } - } - } + for (std::vector<std::string>::const_iterator i = selectedCodecs.begin(); i != selectedCodecs.end(); ++i) + if (std::find(codecs_list.begin(), codecs_list.end(), *i) != codecs_list.end()) + video_codec_list_.push_back(*i); } #endif -void Sdp::setLocalMediaCapabilities(const std::vector<int> &selectedCodecs) +void Sdp::setLocalMediaAudioCapabilities(const std::vector<int> &selectedCodecs) { if (selectedCodecs.empty()) WARN("No selected codec while building local SDP offer"); @@ -338,7 +333,7 @@ void Sdp::setLocalMediaCapabilities(const std::vector<int> &selectedCodecs) if (codec) audio_codec_list_.push_back(codec); else - WARN("SDP: Couldn't find audio codec"); + WARN("Couldn't find audio codec"); } } @@ -353,10 +348,10 @@ namespace { } #ifdef SFL_VIDEO -int Sdp::createLocalSession(const std::vector<int> &selectedCodecs, const std::vector<std::string> &videoCodecs) +int Sdp::createLocalSession(const std::vector<int> &selectedAudioCodecs, const std::vector<std::string> &selectedVideoCodecs) { - setLocalMediaCapabilities(selectedCodecs); - setLocalMediaVideoCapabilities(videoCodecs); + setLocalMediaAudioCapabilities(selectedAudioCodecs); + setLocalMediaVideoCapabilities(selectedVideoCodecs); localSession_ = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_session); localSession_->conn = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_conn); @@ -402,7 +397,7 @@ int Sdp::createLocalSession(const std::vector<int> &selectedCodecs, const std::v #else int Sdp::createLocalSession(const std::vector<int> &selectedCodecs) { - setLocalMediaCapabilities(selectedCodecs); + setLocalMediaAudioCapabilities(selectedCodecs); localSession_ = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_session); if (!localSession_) { @@ -455,9 +450,9 @@ int Sdp::createLocalSession(const std::vector<int> &selectedCodecs) void Sdp::createOffer(const std::vector<int> &selectedCodecs, const std::vector<std::string> &videoCodecs) { if (createLocalSession(selectedCodecs, videoCodecs) != PJ_SUCCESS) - ERROR("SDP: Error: Failed to create initial offer"); - else if (pjmedia_sdp_neg_create_w_local_offer (memPool_, localSession_, &negotiator_) != PJ_SUCCESS) - ERROR("SDP: Error: Failed to create an initial SDP negotiator"); + ERROR("Failed to create initial offer"); + else if (pjmedia_sdp_neg_create_w_local_offer(memPool_, localSession_, &negotiator_) != PJ_SUCCESS) + ERROR("Failed to create an initial SDP negotiator"); } #else void Sdp::createOffer(const std::vector<int> &selectedCodecs) @@ -475,15 +470,15 @@ void Sdp::receiveOffer(const pjmedia_sdp_session* remote, const std::vector<std::string> &videoCodecs) { if (!remote) { - ERROR("SDP: Remote session is NULL"); + ERROR("Remote session is NULL"); return; } - DEBUG("SDP: Remote SDP Session:"); + DEBUG("Remote SDP Session:"); printSession(remote); if (!localSession_ and createLocalSession(selectedCodecs, videoCodecs) != PJ_SUCCESS) { - ERROR("SDP: Failed to create initial offer"); + ERROR("Failed to create initial offer"); return; } diff --git a/daemon/src/sip/sdp.h b/daemon/src/sip/sdp.h index 4af11cb16e..fa18d26cbd 100644 --- a/daemon/src/sip/sdp.h +++ b/daemon/src/sip/sdp.h @@ -308,7 +308,7 @@ class Sdp { */ std::vector<sfl::Codec *> audio_codec_list_; #ifdef SFL_VIDEO - std::vector<std::string> video_codec_list_; + std::vector<std::string> video_codec_list_; #endif /** @@ -352,18 +352,18 @@ class Sdp { * Build the local media capabilities for this session * @param List of codec in preference order */ - void setLocalMediaCapabilities(const std::vector<int> &selectedCodecs); + void setLocalMediaAudioCapabilities(const std::vector<int> &selected); #ifdef SFL_VIDEO - void setLocalMediaVideoCapabilities(const std::vector<std::string> &videoCodecs); + void setLocalMediaVideoCapabilities(const std::vector<std::string> &selected); #endif /* * Build the local SDP offer */ #ifdef SFL_VIDEO - int createLocalSession(const std::vector<int> &selectedCodecs, const std::vector<std::string> &videoCodecs); + int createLocalSession(const std::vector<int> &selectedAudio, const std::vector<std::string> &selectedVideo); #else - int createLocalSession(const std::vector<int> &selectedCodecs); + int createLocalSession(const std::vector<int> &selectedAudio); #endif /* * Adds a sdes attribute to the given media section. diff --git a/daemon/src/video/libav_utils.cpp b/daemon/src/video/libav_utils.cpp index 79a13b8d9e..f07da18590 100644 --- a/daemon/src/video/libav_utils.cpp +++ b/daemon/src/video/libav_utils.cpp @@ -113,6 +113,7 @@ void sfl_avcodec_init() av_register_all(); avdevice_register_all(); + avformat_network_init(); av_lockmgr_register(avcodecManageMutex); diff --git a/daemon/src/video/shared_memory.cpp b/daemon/src/video/shared_memory.cpp index bfd7e9b685..86c913f674 100644 --- a/daemon/src/video/shared_memory.cpp +++ b/daemon/src/video/shared_memory.cpp @@ -95,7 +95,7 @@ int createShmID(int key, int numBytes) int shm_id = shmget(key, numBytes, 0644 | IPC_CREAT); if (shm_id == -1) - ERROR("%s:shmget:%m", __PRETTY_FUNCTION__); + ERROR("shmget:%m"); return shm_id; } @@ -106,7 +106,7 @@ uint8_t *attachShm(int shm_id) /* attach to the segment and get a pointer to it */ uint8_t *data = reinterpret_cast<uint8_t*>(shmat(shm_id, (void *) 0, 0)); if (data == reinterpret_cast<uint8_t *>(-1)) { - ERROR("%s:shmat:%m", __PRETTY_FUNCTION__); + ERROR("shmat:%m"); data = NULL; } return data; @@ -116,7 +116,7 @@ void detachShm(uint8_t *data) { /* detach from the segment: */ if (data and shmdt(data) == -1) - ERROR("%s:shmdt:%m", __PRETTY_FUNCTION__); + ERROR("shmdt:%m"); } void destroyShm(int shm_id) @@ -146,7 +146,7 @@ int createSemaphoreSetID(int semaphoreKey) whose counter is initialized to '0'. */ int semaphoreSetID = semget(semaphoreKey, 1, 0600 | IPC_CREAT); if (semaphoreSetID == -1) { - ERROR("%s:semget:%m", __PRETTY_FUNCTION__); + ERROR("semget:%m"); throw std::runtime_error("Could not create semaphore set"); } diff --git a/daemon/src/video/video_receive_thread.cpp b/daemon/src/video/video_receive_thread.cpp index ec0862b576..24e0a09d14 100644 --- a/daemon/src/video/video_receive_thread.cpp +++ b/daemon/src/video/video_receive_thread.cpp @@ -68,6 +68,22 @@ int getBufferSize(int width, int height, int format) return sizeof(uint8_t) * avpicture_get_size(fmt, width, height); } +string openTemp(string path, std::ofstream& f) +{ + path += "/XXXXXX"; + std::vector<char> dst_path(path.begin(), path.end()); + dst_path.push_back('\0'); + int fd = -1; + while (fd == -1) { + fd = mkstemp(&dst_path[0]); + if (fd != -1) { + path.assign(dst_path.begin(), dst_path.end() - 1); + f.open(path.c_str(), std::ios_base::trunc | std::ios_base::out); + close(fd); + } + } + return path; +} } // end anonymous namespace void VideoReceiveThread::loadSDP() @@ -75,9 +91,9 @@ void VideoReceiveThread::loadSDP() assert(not args_["receiving_sdp"].empty()); std::ofstream os; + sdpFilename_ = openTemp("/tmp", os); os << args_["receiving_sdp"]; - DEBUG("%s:loaded SDP %s", __PRETTY_FUNCTION__, - args_["receiving_sdp"].c_str()); + DEBUG("loaded SDP %s", args_["receiving_sdp"].c_str()); os.close(); } @@ -92,14 +108,17 @@ void VideoReceiveThread::setup() AVInputFormat *file_iformat = 0; std::string format_str; + std::string input; if (args_["input"].empty()) { loadSDP(); format_str = "sdp"; + input = sdpFilename_; } else if (args_["input"].substr(0, strlen("/dev/video")) == "/dev/video") { // it's a v4l device if starting with /dev/video // FIXME: This is not a robust way of checking if we mean to use a // v4l2 device format_str = "video4linux2"; + input = args_["input"]; } DEBUG("Using %s format", format_str.c_str()); @@ -115,16 +134,16 @@ void VideoReceiveThread::setup() av_dict_set(&options, "channel", args_["channel"].c_str(), 0); // Open video file - int ret = avformat_open_input(&inputCtx_, args_["input"].c_str(), file_iformat, - &options); - CHECK(ret == 0, "Could not open input \"%s\"", args_["input"].c_str()); + int ret = avformat_open_input(&inputCtx_, input.c_str(), file_iformat, &options); + CHECK(ret == 0, "Could not open input \"%s\"", input.c_str()); #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0) ret = av_find_stream_info(inputCtx_); #else ret = avformat_find_stream_info(inputCtx_, NULL); #endif - CHECK(ret >= 0, "Could not find stream info!"); + if (ret < 0) + DEBUG("Could not find stream info!"); // find the first video stream from the input streamIndex_ = -1; @@ -146,7 +165,7 @@ void VideoReceiveThread::setup() #else ret = avcodec_open2(decoderCtx_, inputDecoder, NULL); #endif - CHECK(ret >= 0, "Could not open codec"); + CHECK(ret == 0, "Could not open codec"); scaledPicture_ = avcodec_alloc_frame(); CHECK(scaledPicture_, "Could not allocate output frame"); @@ -183,7 +202,8 @@ VideoReceiveThread::VideoReceiveThread(const std::map<string, string> &args, sfl_video::SharedMemory &handle) : args_(args), frameNumber_(0), decoderCtx_(0), rawFrame_(0), scaledPicture_(0), streamIndex_(-1), inputCtx_(0), imgConvertCtx_(0), - dstWidth_(-1), dstHeight_(-1), sharedMemory_(handle), receiving_(false) + dstWidth_(0), dstHeight_(0), sharedMemory_(handle), receiving_(false), + sdpFilename_() {} void VideoReceiveThread::run() diff --git a/daemon/src/video/video_receive_thread.h b/daemon/src/video/video_receive_thread.h index 362b6adae0..4e1d27de12 100644 --- a/daemon/src/video/video_receive_thread.h +++ b/daemon/src/video/video_receive_thread.h @@ -67,12 +67,13 @@ class VideoReceiveThread : public ost::Thread { int dstHeight_; SharedMemory &sharedMemory_; + bool receiving_; + std::string sdpFilename_; void setup(); void createScalingContext(); void loadSDP(); public: - bool receiving_; VideoReceiveThread(const std::map<std::string, std::string> &args, SharedMemory &handle); virtual ~VideoReceiveThread(); diff --git a/daemon/src/video/video_rtp_session.cpp b/daemon/src/video/video_rtp_session.cpp index b7eaa66bed..f5753e3c4a 100644 --- a/daemon/src/video/video_rtp_session.cpp +++ b/daemon/src/video/video_rtp_session.cpp @@ -67,7 +67,7 @@ void VideoRtpSession::updateSDP(const Sdp &sdp) // if port has changed if (desc != rxArgs_["receiving_sdp"]) { rxArgs_["receiving_sdp"] = desc; - DEBUG("%s:Updated incoming SDP to:\n %s", __PRETTY_FUNCTION__, + DEBUG("Updated incoming SDP to:\n %s", rxArgs_["receiving_sdp"].c_str()); } @@ -117,8 +117,7 @@ void VideoRtpSession::updateDestination(const string &destination, if (tmp.str() != txArgs_["destination"]) { assert(sendThread_.get() == 0); txArgs_["destination"] = tmp.str(); - DEBUG("%s updated dest to %s", __PRETTY_FUNCTION__, - txArgs_["destination"].c_str()); + DEBUG("updated dest to %s", txArgs_["destination"].c_str()); } if (port == 0) { @@ -180,7 +179,6 @@ void VideoRtpSession::start() void VideoRtpSession::stop() { - DEBUG("%s", __PRETTY_FUNCTION__); receiveThread_.reset(); sendThread_.reset(); } diff --git a/daemon/src/video/video_send_thread.cpp b/daemon/src/video/video_send_thread.cpp index edd64ca0ff..be700ef56c 100644 --- a/daemon/src/video/video_send_thread.cpp +++ b/daemon/src/video/video_send_thread.cpp @@ -53,9 +53,9 @@ using std::string; void VideoSendThread::print_and_save_sdp() { - size_t sdp_size = outputCtx_->streams[0]->codec->extradata_size + 2048; - char *sdp = new char[sdp_size]; /* theora sdp can be huge */ - av_sdp_create(&outputCtx_, 1, sdp, sdp_size); + const size_t sdp_size = outputCtx_->streams[0]->codec->extradata_size + 2048; + std::string sdp(sdp_size, 0); /* theora sdp can be huge */ + av_sdp_create(&outputCtx_, 1, &(*sdp.begin()), sdp_size); std::istringstream iss(sdp); string line; sdp_ = ""; @@ -65,7 +65,6 @@ void VideoSendThread::print_and_save_sdp() sdp_ += line + "\n"; } DEBUG("%s", sdp_.c_str()); - delete [] sdp; sdpReady_.signal(); } @@ -119,11 +118,10 @@ void VideoSendThread::setup() { AVInputFormat *file_iformat = 0; const char *enc_name = args_["codec"].c_str(); - int ret; // it's a v4l device if starting with /dev/video static const char * const V4L_PATH = "/dev/video"; - if (args_["input"].substr(0, sizeof(V4L_PATH) - 1) == V4L_PATH) { - DEBUG("%s:Using v4l2 format", __PRETTY_FUNCTION__); + if (args_["input"].find(V4L_PATH) != std::string::npos) { + DEBUG("Using v4l2 format"); file_iformat = av_find_input_format("video4linux2"); CHECK(file_iformat, "Could not find format video4linux2"); } @@ -137,7 +135,7 @@ void VideoSendThread::setup() av_dict_set(&options, "channel", args_["channel"].c_str(), 0); // Open video file - ret = avformat_open_input(&inputCtx_, args_["input"].c_str(), + int ret = avformat_open_input(&inputCtx_, args_["input"].c_str(), file_iformat, &options); CHECK(ret == 0, "Could not open input file %s", args_["input"].c_str()); -- GitLab