From: Steinar H. Gunderson Date: Mon, 5 Oct 2015 00:00:47 +0000 (+0200) Subject: Hook up the preview window to a different chain. X-Git-Tag: 1.0.0~296 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=8e79fed3ca7ca12b0575c416454ba43b44c4c514;p=nageru Hook up the preview window to a different chain. --- diff --git a/glwidget.cpp b/glwidget.cpp index 1e67640..3fb4889 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -11,6 +11,7 @@ #include #include +#include #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; diff --git a/glwidget.h b/glwidget.h index 1f6b6e7..045ba55 100644 --- a/glwidget.h +++ b/glwidget.h @@ -4,6 +4,8 @@ #include #include +#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; diff --git a/mainwindow.cpp b/mainwindow.cpp index badc236..65b9580 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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() diff --git a/mixer.cpp b/mixer.cpp index 742e3fd..988d7e4 100644 --- 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 b89fd98..92395a1 100644 --- 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 resource_pool; std::unique_ptr chain; + std::unique_ptr preview_chain; GLuint cbcr_program_num; // Owned by . std::unique_ptr h264_encoder; @@ -76,6 +84,9 @@ private: movit::Effect *resample_effect, *resample2_effect; movit::Effect *padding_effect, *padding2_effect; + // Effects part of . Owned by . + 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 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]; diff --git a/ui_mainwindow.ui b/ui_mainwindow.ui index b7091f9..49eab47 100644 --- a/ui_mainwindow.ui +++ b/ui_mainwindow.ui @@ -34,7 +34,7 @@ 0 - + 1