57
57
, stream_(args_["receiving_sdp"])
58
58
, sdpContext_(SDP_BUFFER_SIZE, false, &readFunction, 0, 0, this)
61
61
, requestKeyFrameCallback_(0)
62
, loop_(std::bind(&VideoReceiveThread::setup, this),
63
std::bind(&VideoReceiveThread::process, this),
64
std::bind(&VideoReceiveThread::cleanup, this))
64
67
VideoReceiveThread::~VideoReceiveThread()
73
VideoReceiveThread::startLoop()
70
78
// We do this setup here instead of the constructor because we don't want the
91
99
input = args_["input"];
94
if (!args_["framerate"].empty())
95
videoDecoder_->setOption("framerate", args_["framerate"].c_str());
96
if (!args_["video_size"].empty())
97
videoDecoder_->setOption("video_size", args_["video_size"].c_str());
98
if (!args_["channel"].empty())
99
videoDecoder_->setOption("channel", args_["channel"].c_str());
101
102
videoDecoder_->setInterruptCallback(interruptCb, this);
103
104
if (input == SDP_FILENAME) {
104
105
#if HAVE_SDP_CUSTOM_IO
105
106
// custom_io so the SDP demuxer will not open any UDP connections
106
videoDecoder_->setOption("sdp_flags", "custom_io");
107
args_["sdp_flags"] = "custom_io";
108
109
WARN("libavformat too old for custom SDP demuxing");
112
113
videoDecoder_->setIOContext(&sdpContext_);
116
videoDecoder_->setOptions(args_);
115
118
EXIT_IF_FAIL(!videoDecoder_->openInput(input, format_str),
116
119
"Could not open input \"%s\"", input.c_str());
118
121
if (input == SDP_FILENAME) {
119
122
#if HAVE_SDP_CUSTOM_IO
120
// Now replace our custom AVIOContext with one that will read
123
// Now replace our custom AVIOContext with one that will read packets
122
124
videoDecoder_->setIOContext(demuxContext_);
168
170
int VideoReceiveThread::interruptCb(void *data)
170
172
VideoReceiveThread *context = static_cast<VideoReceiveThread*>(data);
171
return not context->isRunning();
173
return not context->loop_.isRunning();
174
176
int VideoReceiveThread::readFunction(void *opaque, uint8_t *buf, int buf_size)
188
190
bool VideoReceiveThread::decodeFrame()
190
int ret = videoDecoder_->decode(getNewFrame());
198
if (ret == -2 and requestKeyFrameCallback_) {
199
WARN("VideoDecoder error, restarting it...");
200
EXIT_IF_FAIL(!videoDecoder_->setupFromVideoData(), "Setup failed");
201
requestKeyFrameCallback_(id_);
202
} else if (ret < 0) {
203
ERROR("VideoDecoder fatal error, stopping it...");
193
const auto ret = videoDecoder_->decode(getNewFrame(), pkt);
196
case VideoDecoder::Status::FrameFinished:
200
case VideoDecoder::Status::DecodeError:
201
WARN("decoding failure, trying to reset decoder...");
202
delete videoDecoder_;
204
ERROR("fatal error, rx thread re-setup failed");
208
if (!videoDecoder_->setupFromVideoData()) {
209
ERROR("fatal error, v-decoder setup failed");
213
if (requestKeyFrameCallback_)
214
requestKeyFrameCallback_(id_);
217
case VideoDecoder::Status::ReadError:
218
ERROR("fatal error, read failed");
210
void VideoReceiveThread::addReceivingDetails(
211
std::map<std::string, std::string> &details)
213
if (isRunning() and dstWidth_ > 0 and dstHeight_ > 0) {
214
details["VIDEO_SHM_PATH"] = sink_.openedName();
215
std::ostringstream os;
217
details["VIDEO_WIDTH"] = os.str();
220
details["VIDEO_HEIGHT"] = os.str();
224
229
void VideoReceiveThread::enterConference()
231
if (!loop_.isRunning())
229
234
if (detach(&sink_)) {
230
Manager::instance().getVideoControls()->stoppedDecoding(id_, sink_.openedName());
235
Manager::instance().getVideoManager()->stoppedDecoding(id_, sink_.openedName(), false);
231
236
DEBUG("RX: shm sink <%s> detached", sink_.openedName().c_str());
235
240
void VideoReceiveThread::exitConference()
242
if (!loop_.isRunning())
240
245
if (dstWidth_ > 0 && dstHeight_ > 0) {
241
246
if (attach(&sink_)) {
242
Manager::instance().getVideoControls()->startedDecoding(id_, sink_.openedName(), dstWidth_, dstHeight_);
247
Manager::instance().getVideoManager()->startedDecoding(id_, sink_.openedName(), dstWidth_, dstHeight_, false);
243
248
DEBUG("RX: shm sink <%s> started: size = %dx%d",
244
249
sink_.openedName().c_str(), dstWidth_, dstHeight_);