diff --git a/src/media/video/filter_transpose.cpp b/src/media/video/filter_transpose.cpp index 8eaa3a236856fe38f5811de3c667fb555d4a69e1..ca96a4816a26f41f5103d8c0f3c50cc1b5e287d6 100644 --- a/src/media/video/filter_transpose.cpp +++ b/src/media/video/filter_transpose.cpp @@ -37,31 +37,29 @@ getTransposeFilter(int rotation, std::string inputName, int width, int height, i } std::stringstream ss; - ss << "[" << inputName << "]"; + ss << "[" << inputName << "] "; switch (rotation) { case 90: case -270: ss << "transpose=2"; - if (rescale) { - ss << ",scale=w=-1:h=" << height; - ss << ",pad=" << width << ":" << height << ":(ow-iw)/2"; - } + if (rescale) + ss << ", scale=w=-1:h=" << height + << ", pad=" << width << ":" << height << ":(ow-iw)/2"; break; case 180 : case -180 : - ss << "transpose=1,transpose=1"; + ss << "transpose=1, transpose=1"; break; case 270 : case -90 : ss << "transpose=1"; - if (rescale) { - ss << ",scale=w=-1:h=" << height; - ss << ",pad=" << width << ":" << height << ":(ow-iw)/2"; - } + if (rescale) + ss << ", scale=w=-1:h=" << height + << ", pad=" << width << ":" << height << ":(ow-iw)/2"; break; default : - ss << "null"; + return {}; } const auto one = rational<int>(1); diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp index fff6787d4960334eb6e38fb25ba489493494a4de..a196bde2a7ce6c3fbb33b25145e2e64c3894c0a1 100644 --- a/src/media/video/video_mixer.cpp +++ b/src/media/video/video_mixer.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2013-2019 Savoir-faire Linux Inc. * * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> + * Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +25,10 @@ #include "media_buffer.h" #include "client/videomanager.h" #include "manager.h" +#include "media_filter.h" #include "sinkclient.h" #include "logger.h" +#include "filter_transpose.h" #ifdef RING_ACCEL #include "accel.h" #endif @@ -33,10 +36,16 @@ #include <cmath> #include <unistd.h> +extern "C" { +#include <libavutil/display.h> +} + namespace jami { namespace video { struct VideoMixer::VideoMixerSource { - Observable<std::shared_ptr<MediaFrame>>* source = nullptr; + Observable<std::shared_ptr<MediaFrame>>* source {nullptr}; + int rotation {0}; + std::unique_ptr<MediaFilter> rotationFilter {nullptr}; std::unique_ptr<VideoFrame> update_frame; std::unique_ptr<VideoFrame> render_frame; void atomic_swap_render(std::unique_ptr<VideoFrame>& other) { @@ -156,7 +165,7 @@ VideoMixer::process() x->atomic_swap_render(input); if (input) - render_frame(output, *input, i); + render_frame(output, *input, x, i); x->atomic_swap_render(input); ++i; @@ -167,16 +176,16 @@ VideoMixer::process() } void -VideoMixer::render_frame(VideoFrame& output, const VideoFrame& input, int index) +VideoMixer::render_frame(VideoFrame& output, const VideoFrame& input, + const std::unique_ptr<VideoMixerSource>& source, int index) { if (!width_ or !height_ or !input.pointer()) return; #ifdef RING_ACCEL - auto framePtr = HardwareAccel::transferToMainMemory(input, AV_PIX_FMT_NV12); - const auto& swFrame = *framePtr; + std::shared_ptr<VideoFrame> frame { HardwareAccel::transferToMainMemory(input, AV_PIX_FMT_NV12) }; #else - const auto& swFrame = input; + std::shared_ptr<VideoFrame> frame = input; #endif const int n = sources_.size(); @@ -186,7 +195,25 @@ VideoMixer::render_frame(VideoFrame& output, const VideoFrame& input, int index) int xoff = (index % zoom) * cell_width; int yoff = (index / zoom) * cell_height; - scaler_.scale_and_pad(swFrame, output, xoff, yoff, cell_width, cell_height, true); + AVFrameSideData* sideData = av_frame_get_side_data(frame->pointer(), AV_FRAME_DATA_DISPLAYMATRIX); + int angle = 0; + if (sideData) { + auto matrixRotation = reinterpret_cast<int32_t*>(sideData->data); + angle = av_display_rotation_get(matrixRotation); + } + const constexpr char filterIn[] = "mixin"; + if (angle != source->rotation) { + source->rotationFilter = video::getTransposeFilter(angle, filterIn, + frame->width(), frame->height(), frame->format(), true); + source->rotation = angle; + } + if (source->rotationFilter) { + source->rotationFilter->feedInput(frame->pointer(), filterIn); + frame = std::static_pointer_cast<VideoFrame>(std::shared_ptr<MediaFrame>( + source->rotationFilter->readOutput())); + } + + scaler_.scale_and_pad(*frame, output, xoff, yoff, cell_width, cell_height, true); } void diff --git a/src/media/video/video_mixer.h b/src/media/video/video_mixer.h index 43e5534c77e3a16a86f50bf3f742c1a070b70cf4..056c472f209ee6a64d61d3922b9a7487dace3832 100644 --- a/src/media/video/video_mixer.h +++ b/src/media/video/video_mixer.h @@ -2,6 +2,7 @@ * Copyright (C) 2013-2019 Savoir-faire Linux Inc. * * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> + * Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +59,8 @@ private: struct VideoMixerSource; - void render_frame(VideoFrame& output, const VideoFrame& input, int index); + void render_frame(VideoFrame& output, const VideoFrame& input, + const std::unique_ptr<VideoMixerSource>& source, int index); void start_sink(); void stop_sink();