]> git.sesse.net Git - nageru/commitdiff
Hook up the preview window to a different chain.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 5 Oct 2015 00:00:47 +0000 (02:00 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 5 Oct 2015 00:00:47 +0000 (02:00 +0200)
glwidget.cpp
glwidget.h
mainwindow.cpp
mixer.cpp
mixer.h
ui_mainwindow.ui

index 1e676405e6258b1f62eea1cbf764faaf7f39a6ac..3fb4889dc314c7ce163d389477926dfe110d51bc 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <movit/resource_pool.h>
 #include <stdio.h>
+#include <mutex>
 
 #include "context.h"
 #include "mixer.h"
@@ -38,11 +39,14 @@ void GLWidget::initializeGL()
        printf("egl context=%p\n", eglGetCurrentContext());
        //printf("threads: %p %p\n", QThread::currentThread(), qGuiApp->thread());
 
-       global_mixer = new Mixer(QGLFormat::toSurfaceFormat(format()));
-       global_mixer->set_frame_ready_callback(Mixer::OUTPUT_LIVE, [this]{
+       static std::once_flag flag;
+       std::call_once(flag, [this]{
+               global_mixer = new Mixer(QGLFormat::toSurfaceFormat(format()));
+               global_mixer->start();
+       });
+       global_mixer->set_frame_ready_callback(output, [this]{
                QMetaObject::invokeMethod(this, "update", Qt::AutoConnection);
        });
-       global_mixer->start();
 
        // Prepare the shaders to actually get the texture shown (ick).
        glDisable(GL_BLEND);
@@ -93,12 +97,13 @@ void GLWidget::initializeGL()
 void GLWidget::resizeGL(int width, int height)
 {
        glViewport(0, 0, width, height);
+       global_mixer->set_preview_size(output, width, height);
 }
 
 void GLWidget::paintGL()
 {
        Mixer::DisplayFrame frame;
-       if (!global_mixer->get_display_frame(Mixer::OUTPUT_LIVE, &frame)) {
+       if (!global_mixer->get_display_frame(output, &frame)) {
                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                return;
index 1f6b6e74f14fa12c7f20334a45864044edd5d7d3..045ba5587204ea7ebb7351e2aad323dc79e0fb91 100644 (file)
@@ -4,6 +4,8 @@
 #include <epoxy/gl.h>
 #include <QGLWidget>
 
+#include "mixer.h"
+
 class QWidget;
 
 namespace movit {
@@ -22,12 +24,18 @@ public:
        GLWidget(QWidget *parent = 0);
        ~GLWidget();
 
+       void set_output(Mixer::Output output)
+       {
+               this->output = output;
+       }
+
 protected:
        void initializeGL() override;
        void resizeGL(int width, int height) override;
        void paintGL() override;
 
 private:
+       Mixer::Output output;
        movit::ResourcePool *resource_pool;
        GLuint vao, program_num;
        GLuint position_vbo, texcoord_vbo;
index badc2368c1900769e210032608f1866a8a64a9d0..65b95808e6c6f986a9a3d686fb133174f6499fdf 100644 (file)
@@ -14,6 +14,9 @@ MainWindow::MainWindow()
        Ui::MainWindow *ui = new Ui::MainWindow;
        ui->setupUi(this);
        connect(ui->cut_btn, SIGNAL(clicked()), this, SLOT(cut()));
+
+       ui->me_live->set_output(Mixer::OUTPUT_LIVE);
+       ui->me_preview->set_output(Mixer::OUTPUT_PREVIEW);
 }
 
 void MainWindow::cut()
index 742e3fd7bec634165bf984948f6fc8700486ec53..988d7e44e9910bcb6dc0dfe8b208e55918e0bd33 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -59,6 +59,7 @@ Mixer::Mixer(const QSurfaceFormat &format)
 
        resource_pool.reset(new ResourcePool);
        output_channel[OUTPUT_LIVE].parent = this;
+       output_channel[OUTPUT_PREVIEW].parent = this;
 
        ImageFormat inout_format;
        inout_format.color_space = COLORSPACE_sRGB;
@@ -80,6 +81,7 @@ Mixer::Mixer(const QSurfaceFormat &format)
        output_ycbcr_format.luma_coefficients = YCBCR_REC_601;
        output_ycbcr_format.full_range = false;
 
+       // Main chain.
        chain.reset(new EffectChain(WIDTH, HEIGHT, resource_pool.get()));
        check_error();
        input[0] = new YCbCrInput(inout_format, input_ycbcr_format, WIDTH, HEIGHT, YCBCR_INPUT_SPLIT_Y_AND_CBCR);
@@ -106,6 +108,16 @@ Mixer::Mixer(const QSurfaceFormat &format)
        chain->set_output_origin(OUTPUT_ORIGIN_TOP_LEFT);
        chain->finalize();
 
+       // Preview chain (always shows just first input for now).
+       preview_chain.reset(new EffectChain(WIDTH, HEIGHT, resource_pool.get()));
+       check_error();
+       preview_input = new YCbCrInput(inout_format, input_ycbcr_format, WIDTH, HEIGHT, YCBCR_INPUT_SPLIT_Y_AND_CBCR);
+       preview_chain->add_input(preview_input);
+       preview_chain->add_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+       preview_chain->set_dither_bits(0);  // Don't bother.
+       preview_chain->set_output_origin(OUTPUT_ORIGIN_TOP_LEFT);
+       preview_chain->finalize();
+
        h264_encoder.reset(new H264Encoder(h264_encoder_surface, WIDTH, HEIGHT, "test.mp4"));
 
        printf("Configuring first card...\n");
@@ -401,13 +413,18 @@ void Mixer::thread_func()
                                input[1]->set_pixel_data(0, (unsigned char *)BUFFER_OFFSET((1280 * 750 * 2 + 44) / 2 + 1280 * 25 + 22), input_tex_pbo);
                                input[1]->set_pixel_data(1, (unsigned char *)BUFFER_OFFSET(1280 * 25 + 22), input_tex_pbo);
                        }
+
+                       if (card_index == 0) {
+                               preview_input->set_pixel_data(0, (unsigned char *)BUFFER_OFFSET((1280 * 750 * 2 + 44) / 2 + 1280 * 25 + 22), input_tex_pbo);
+                               preview_input->set_pixel_data(1, (unsigned char *)BUFFER_OFFSET(1280 * 25 + 22), input_tex_pbo);
+                       }
                }
 
                GLuint y_tex, cbcr_tex;
                bool got_frame = h264_encoder->begin_frame(&y_tex, &cbcr_tex);
                assert(got_frame);
 
-               // Render chain.
+               // Render main chain.
                GLuint cbcr_full_tex = resource_pool->create_2d_texture(GL_RG8, WIDTH, HEIGHT);
                GLuint rgba_tex = resource_pool->create_2d_texture(GL_RGBA8, WIDTH, HEIGHT);
                GLuint fbo = resource_pool->create_fbo(y_tex, cbcr_full_tex, rgba_tex);
@@ -417,11 +434,18 @@ void Mixer::thread_func()
                subsample_chroma(cbcr_full_tex, cbcr_tex);
                resource_pool->release_2d_texture(cbcr_full_tex);
 
+               // Render preview chain.
+               GLuint preview_rgba_tex = resource_pool->create_2d_texture(GL_RGBA8, output_channel[OUTPUT_PREVIEW].width, output_channel[OUTPUT_PREVIEW].height);
+               fbo = resource_pool->create_fbo(preview_rgba_tex);
+               preview_chain->render_to_fbo(fbo, output_channel[OUTPUT_PREVIEW].width, output_channel[OUTPUT_PREVIEW].height);
+               resource_pool->release_fbo(fbo);
+
                RefCountedGLsync fence(GL_SYNC_GPU_COMMANDS_COMPLETE, /*flags=*/0);
                check_error();
                h264_encoder->end_frame(fence, input_frames_to_release);
 
                output_channel[OUTPUT_LIVE].output_frame(rgba_tex, fence);
+               output_channel[OUTPUT_PREVIEW].output_frame(preview_rgba_tex, fence);
 
                clock_gettime(CLOCK_MONOTONIC, &now);
                double elapsed = now.tv_sec - start.tv_sec +
@@ -571,3 +595,8 @@ void Mixer::OutputChannel::set_frame_ready_callback(Mixer::new_frame_ready_callb
        has_new_frame_ready_callback = true;
 }
 
+void Mixer::OutputChannel::set_size(int width, int height)
+{
+       this->width = width;
+       this->height = height;
+}
diff --git a/mixer.h b/mixer.h
index b89fd987175c902e9886eac1cf662949c560205d..92395a1b4c8e78ed8b44aca05a1d29fb28af5c42 100644 (file)
--- a/mixer.h
+++ b/mixer.h
@@ -38,6 +38,7 @@ public:
 
        enum Output {
                OUTPUT_LIVE = 0,
+               OUTPUT_PREVIEW,
                NUM_OUTPUTS
        };
 
@@ -56,6 +57,12 @@ public:
                output_channel[output].set_frame_ready_callback(callback);
        }
 
+       // Ignored for OUTPUT_LIVE.
+       void set_preview_size(Output output, int width, int height)
+       {
+               output_channel[output].set_size(width, height);
+       }
+
 private:
        void bm_frame(int card_index, uint16_t timecode,
                FrameAllocator::Frame video_frame, size_t video_offset, uint16_t video_format,
@@ -68,6 +75,7 @@ private:
        QSurface *mixer_surface, *h264_encoder_surface;
        std::unique_ptr<movit::ResourcePool> resource_pool;
        std::unique_ptr<movit::EffectChain> chain;
+       std::unique_ptr<movit::EffectChain> preview_chain;
        GLuint cbcr_program_num;  // Owned by <resource_pool>.
        std::unique_ptr<H264Encoder> h264_encoder;
 
@@ -76,6 +84,9 @@ private:
        movit::Effect *resample_effect, *resample2_effect;
        movit::Effect *padding_effect, *padding2_effect;
 
+       // Effects part of <preview_chain>. Owned by <preview_chain>.
+       movit::YCbCrInput *preview_input;
+
        Source current_source = SOURCE_INPUT1;
        int frame = 0;
 
@@ -103,6 +114,7 @@ private:
                void output_frame(GLuint tex, RefCountedGLsync fence);
                bool get_display_frame(DisplayFrame *frame);
                void set_frame_ready_callback(new_frame_ready_callback_t callback);
+               void set_size(int width, int height);  // Ignored for OUTPUT_LIVE.
 
        private:
                friend class Mixer;
@@ -113,6 +125,8 @@ private:
                bool has_current_frame = false, has_ready_frame = false;  // protected by <frame_mutex>
                new_frame_ready_callback_t new_frame_ready_callback;
                bool has_new_frame_ready_callback = false;
+
+               int width = 1280, height = 720;
        };
        OutputChannel output_channel[NUM_OUTPUTS];
 
index b7091f9231c914978bd3a3cf3a9392c56610b688..49eab4785fde7d663702272adce958018da6a4cc 100644 (file)
@@ -34,7 +34,7 @@
            <number>0</number>
           </property>
           <item>
-           <widget class="QGLWidget" name="me_preview">
+           <widget class="GLWidget" name="me_preview">
             <property name="sizePolicy">
              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
               <horstretch>1</horstretch>