Skip to content
Snippets Groups Projects
Commit 0176c99c authored by Aline Gondim Santos's avatar Aline Gondim Santos
Browse files

conference: keep frame sizes if frame is empty

This is needed to have a proper overlay for conference participant with muted video.

GitLab: #484
Change-Id: Ie037728f4651d937741b24a656b7c49cf7670856
parent 781014a9
Branches
No related tags found
No related merge requests found
...@@ -58,7 +58,8 @@ struct VideoMixer::VideoMixerSource ...@@ -58,7 +58,8 @@ struct VideoMixer::VideoMixerSource
render_frame = newFrame; render_frame = newFrame;
} }
std::shared_ptr<VideoFrame> getRenderFrame() { std::shared_ptr<VideoFrame> getRenderFrame()
{
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
return render_frame; return render_frame;
} }
...@@ -68,7 +69,7 @@ struct VideoMixer::VideoMixerSource ...@@ -68,7 +69,7 @@ struct VideoMixer::VideoMixerSource
int y {}; int y {};
int w {}; int w {};
int h {}; int h {};
bool hasVideo {false}; bool hasVideo {true};
private: private:
std::mutex mutex_; std::mutex mutex_;
...@@ -140,7 +141,8 @@ VideoMixer::switchInput(const std::string& input) ...@@ -140,7 +141,8 @@ VideoMixer::switchInput(const std::string& input)
} }
void void
VideoMixer::switchSecondaryInput(const std::string& input) { VideoMixer::switchSecondaryInput(const std::string& input)
{
if (auto local = videoLocalSecondary_) { if (auto local = videoLocalSecondary_) {
// Detach videoInput from mixer // Detach videoInput from mixer
local->detach(this); local->detach(this);
...@@ -216,7 +218,8 @@ VideoMixer::detached(Observable<std::shared_ptr<MediaFrame>>* ob) ...@@ -216,7 +218,8 @@ VideoMixer::detached(Observable<std::shared_ptr<MediaFrame>>* ob)
// Handle the case where the current shown source leave the conference // Handle the case where the current shown source leave the conference
if (activeSource_ == ob) { if (activeSource_ == ob) {
currentLayout_ = Layout::GRID; currentLayout_ = Layout::GRID;
activeSource_ = videoLocalSecondary_ ? videoLocalSecondary_.get() : videoLocal_.get(); activeSource_ = videoLocalSecondary_ ? videoLocalSecondary_.get()
: videoLocal_.get();
} }
sources_.remove(x); sources_.remove(x);
updateLayout(); updateLayout();
...@@ -236,7 +239,9 @@ VideoMixer::update(Observable<std::shared_ptr<MediaFrame>>* ob, ...@@ -236,7 +239,9 @@ VideoMixer::update(Observable<std::shared_ptr<MediaFrame>>* ob,
#ifdef RING_ACCEL #ifdef RING_ACCEL
std::shared_ptr<VideoFrame> frame; std::shared_ptr<VideoFrame> frame;
try { try {
frame = HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>(frame_p), AV_PIX_FMT_NV12); frame = HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>(
frame_p),
AV_PIX_FMT_NV12);
x->atomic_copy(*std::static_pointer_cast<VideoFrame>(frame)); x->atomic_copy(*std::static_pointer_cast<VideoFrame>(frame));
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
JAMI_ERR("Accel failure: %s", e.what()); JAMI_ERR("Accel failure: %s", e.what());
...@@ -284,16 +289,7 @@ VideoMixer::process() ...@@ -284,16 +289,7 @@ VideoMixer::process()
// make rendered frame temporarily unavailable for update() // make rendered frame temporarily unavailable for update()
// to avoid concurrent access. // to avoid concurrent access.
std::shared_ptr<VideoFrame> input = x->getRenderFrame(); std::shared_ptr<VideoFrame> input = x->getRenderFrame();
std::shared_ptr<VideoFrame> fooInput = std::make_shared<VideoFrame>();
if (!input->height() or !input->width())
continue;
// If orientation changed or if the first valid frame for source
// is received -> trigger layout calculation and confInfo update
if (x->rotation != input->getOrientation() or !x->w or !x->h) {
updateLayout();
needsUpdate = true;
}
auto wantedIndex = i; auto wantedIndex = i;
if (currentLayout_ == Layout::ONE_BIG) { if (currentLayout_ == Layout::ONE_BIG) {
...@@ -308,16 +304,35 @@ VideoMixer::process() ...@@ -308,16 +304,35 @@ VideoMixer::process()
} }
} }
auto hasVideo = x->hasVideo;
bool blackFrame = false;
if (!input->height() or !input->width()) {
successfullyRendered = true;
fooInput->reserve(format_, width_, height_);
blackFrame = true;
} else {
fooInput.swap(input);
}
// If orientation changed or if the first valid frame for source
// is received -> trigger layout calculation and confInfo update
if (x->rotation != fooInput->getOrientation() or !x->w or !x->h) {
updateLayout();
needsUpdate = true;
}
if (needsUpdate) if (needsUpdate)
calc_position(x, input, wantedIndex); calc_position(x, fooInput, wantedIndex);
if (input) if (!blackFrame) {
successfullyRendered |= render_frame(output, input, x); if (fooInput)
else successfullyRendered |= render_frame(output, fooInput, x);
JAMI_WARN("Nothing to render for %p", x->source); else
JAMI_WARN("Nothing to render for %p", x->source);
}
auto hasVideo = x->hasVideo; x->hasVideo = !blackFrame && successfullyRendered;
x->hasVideo = input && successfullyRendered;
if (hasVideo != x->hasVideo) { if (hasVideo != x->hasVideo) {
updateLayout(); updateLayout();
needsUpdate = true; needsUpdate = true;
...@@ -348,10 +363,10 @@ VideoMixer::process() ...@@ -348,10 +363,10 @@ VideoMixer::process()
} }
output.pointer()->pts = av_rescale_q_rnd(av_gettime() - startTime_, output.pointer()->pts = av_rescale_q_rnd(av_gettime() - startTime_,
{1, AV_TIME_BASE}, {1, AV_TIME_BASE},
{1, MIXER_FRAMERATE}, {1, MIXER_FRAMERATE},
static_cast<AVRounding>(AV_ROUND_NEAR_INF static_cast<AVRounding>(AV_ROUND_NEAR_INF
| AV_ROUND_PASS_MINMAX)); | AV_ROUND_PASS_MINMAX));
lastTimestamp_ = output.pointer()->pts; lastTimestamp_ = output.pointer()->pts;
publishFrame(); publishFrame();
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment