~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/src/video/video_receive_thread.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include "video_receive_thread.h"
36
36
#include "socket_pair.h"
37
37
#include "manager.h"
38
 
#include "client/video_controls.h"
39
 
#include "check.h"
 
38
#include "client/videomanager.h"
 
39
#include "logger.h"
40
40
 
41
41
#include <unistd.h>
42
42
#include <map>
57
57
    , stream_(args_["receiving_sdp"])
58
58
    , sdpContext_(SDP_BUFFER_SIZE, false, &readFunction, 0, 0, this)
59
59
    , demuxContext_()
60
 
    , sink_(id+"_RX")
 
60
    , sink_(id)
61
61
    , requestKeyFrameCallback_(0)
 
62
    , loop_(std::bind(&VideoReceiveThread::setup, this),
 
63
            std::bind(&VideoReceiveThread::process, this),
 
64
            std::bind(&VideoReceiveThread::cleanup, this))
62
65
{}
63
66
 
64
67
VideoReceiveThread::~VideoReceiveThread()
65
68
{
66
 
    stop();
67
 
    join();
 
69
    loop_.join();
 
70
}
 
71
 
 
72
void
 
73
VideoReceiveThread::startLoop()
 
74
{
 
75
    loop_.start();
68
76
}
69
77
 
70
78
// We do this setup here instead of the constructor because we don't want the
91
99
        input = args_["input"];
92
100
    }
93
101
 
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());
100
 
 
101
102
    videoDecoder_->setInterruptCallback(interruptCb, this);
102
103
 
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";
107
108
#else
108
109
        WARN("libavformat too old for custom SDP demuxing");
109
110
#endif
112
113
        videoDecoder_->setIOContext(&sdpContext_);
113
114
    }
114
115
 
 
116
    videoDecoder_->setOptions(args_);
 
117
 
115
118
    EXIT_IF_FAIL(!videoDecoder_->openInput(input, format_str),
116
119
                 "Could not open input \"%s\"", input.c_str());
117
120
 
118
121
    if (input == SDP_FILENAME) {
119
122
#if HAVE_SDP_CUSTOM_IO
120
 
        // Now replace our custom AVIOContext with one that will read
121
 
        // packets
 
123
        // Now replace our custom AVIOContext with one that will read packets
122
124
        videoDecoder_->setIOContext(demuxContext_);
123
125
#endif
124
126
    }
154
156
void VideoReceiveThread::cleanup()
155
157
{
156
158
    if (detach(&sink_))
157
 
        Manager::instance().getVideoControls()->stoppedDecoding(id_, sink_.openedName());
 
159
        Manager::instance().getVideoManager()->stoppedDecoding(id_, sink_.openedName(), false);
158
160
    sink_.stop();
159
161
 
160
162
    if (videoDecoder_)
168
170
int VideoReceiveThread::interruptCb(void *data)
169
171
{
170
172
    VideoReceiveThread *context = static_cast<VideoReceiveThread*>(data);
171
 
    return not context->isRunning();
 
173
    return not context->loop_.isRunning();
172
174
}
173
175
 
174
176
int VideoReceiveThread::readFunction(void *opaque, uint8_t *buf, int buf_size)
187
189
 
188
190
bool VideoReceiveThread::decodeFrame()
189
191
{
190
 
    int ret = videoDecoder_->decode(getNewFrame());
191
 
 
192
 
    if (ret > 0) {
193
 
        publishFrame();
194
 
        return true;
195
 
    }
196
 
 
197
 
    // decoding error?
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...");
204
 
        stop();
 
192
    VideoPacket pkt;
 
193
    const auto ret = videoDecoder_->decode(getNewFrame(), pkt);
 
194
 
 
195
    switch (ret) {
 
196
        case VideoDecoder::Status::FrameFinished:
 
197
            publishFrame();
 
198
            return true;
 
199
 
 
200
        case VideoDecoder::Status::DecodeError:
 
201
            WARN("decoding failure, trying to reset decoder...");
 
202
            delete videoDecoder_;
 
203
            if (!setup()) {
 
204
                ERROR("fatal error, rx thread re-setup failed");
 
205
                loop_.stop();
 
206
                break;
 
207
            }
 
208
            if (!videoDecoder_->setupFromVideoData()) {
 
209
                ERROR("fatal error, v-decoder setup failed");
 
210
                loop_.stop();
 
211
                break;
 
212
            }
 
213
            if (requestKeyFrameCallback_)
 
214
                requestKeyFrameCallback_(id_);
 
215
            break;
 
216
 
 
217
        case VideoDecoder::Status::ReadError:
 
218
            ERROR("fatal error, read failed");
 
219
            loop_.stop();
 
220
 
 
221
        default:
 
222
            break;
205
223
    }
206
224
 
207
225
    return false;
208
226
}
209
227
 
210
 
void VideoReceiveThread::addReceivingDetails(
211
 
    std::map<std::string, std::string> &details)
212
 
{
213
 
    if (isRunning() and dstWidth_ > 0 and dstHeight_ > 0) {
214
 
        details["VIDEO_SHM_PATH"] = sink_.openedName();
215
 
        std::ostringstream os;
216
 
        os << dstWidth_;
217
 
        details["VIDEO_WIDTH"] = os.str();
218
 
        os.str("");
219
 
        os << dstHeight_;
220
 
        details["VIDEO_HEIGHT"] = os.str();
221
 
    }
222
 
}
223
228
 
224
229
void VideoReceiveThread::enterConference()
225
230
{
226
 
    if (!isRunning())
 
231
    if (!loop_.isRunning())
227
232
        return;
228
233
 
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());
232
237
    }
233
238
}
234
239
 
235
240
void VideoReceiveThread::exitConference()
236
241
{
237
 
    if (!isRunning())
 
242
    if (!loop_.isRunning())
238
243
        return;
239
244
 
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_);
245
250
        }