From a98732df9454028ddaa54a9d07b5d7513767bfe9 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 21 Nov 2015 21:51:35 +0100 Subject: [PATCH] Open up for inputs that are different from the native resolution. No deinterlacing or proper scaling yet, though. --- bmusb | 2 +- mixer.cpp | 41 ++++++++++++++++++++++++++++------------- pbo_frame_allocator.cpp | 3 +++ pbo_frame_allocator.h | 1 + theme.cpp | 2 ++ theme.h | 12 +++++++++--- theme.lua | 2 ++ 7 files changed, 46 insertions(+), 17 deletions(-) diff --git a/bmusb b/bmusb index 8eb0e99..62463c9 160000 --- a/bmusb +++ b/bmusb @@ -1 +1 @@ -Subproject commit 8eb0e99394c2ffa361c9dd7eb22bc176e6e4c899 +Subproject commit 62463c958d6109af87bc22f3d5ccad0421889a5e diff --git a/mixer.cpp b/mixer.cpp index 5fd5d1f..e3af878 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -218,7 +218,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, { CaptureCard *card = &cards[card_index]; - int width, height, frame_rate_nom, frame_rate_den, extra_lines_top, extra_lines_bottom; + unsigned width, height, frame_rate_nom, frame_rate_den, extra_lines_top, extra_lines_bottom; bool interlaced; decode_video_format(video_format, &width, &height, &extra_lines_top, &extra_lines_bottom, @@ -300,8 +300,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, } if (video_frame.len - video_offset == 0 || - video_frame.len - video_offset != size_t(width * (height + extra_lines_top + extra_lines_bottom) * 2) || - width != WIDTH || height != HEIGHT) { // TODO: Remove this once the rest of the infrastructure is in place. + video_frame.len - video_offset != size_t(width * (height + extra_lines_top + extra_lines_bottom) * 2)) { if (video_frame.len != 0) { printf("Card %d: Dropping video frame with wrong length (%ld)\n", card_index, video_frame.len - video_offset); @@ -324,7 +323,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, return; } - const PBOFrameAllocator::Userdata *userdata = (const PBOFrameAllocator::Userdata *)video_frame.userdata; + PBOFrameAllocator::Userdata *userdata = (PBOFrameAllocator::Userdata *)video_frame.userdata; GLuint pbo = userdata->pbo; check_error(); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); @@ -339,14 +338,30 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, size_t cbcr_offset = video_offset / 2; size_t y_offset = video_frame.size / 2 + video_offset / 2; - glBindTexture(GL_TEXTURE_2D, userdata->tex_cbcr); - check_error(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cbcr_width, height, GL_RG, GL_UNSIGNED_BYTE, BUFFER_OFFSET(cbcr_offset + cbcr_width * extra_lines_top * sizeof(uint16_t))); - check_error(); - glBindTexture(GL_TEXTURE_2D, userdata->tex_y); - check_error(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, BUFFER_OFFSET(y_offset + width * extra_lines_top)); - check_error(); + if (width != userdata->last_width || height != userdata->last_height) { + // We changed resolution since last use of this texture, so we need to create + // a new object. Note that this each card has its own PBOFrameAllocator, + // we don't need to worry about these flip-flopping between resolutions. + glBindTexture(GL_TEXTURE_2D, userdata->tex_cbcr); + check_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, cbcr_width, height, 0, GL_RG, GL_UNSIGNED_BYTE, BUFFER_OFFSET(cbcr_offset + cbcr_width * extra_lines_top * sizeof(uint16_t))); + check_error(); + glBindTexture(GL_TEXTURE_2D, userdata->tex_y); + check_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, BUFFER_OFFSET(y_offset + width * extra_lines_top)); + check_error(); + userdata->last_width = width; + userdata->last_height = height; + } else { + glBindTexture(GL_TEXTURE_2D, userdata->tex_cbcr); + check_error(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cbcr_width, height, GL_RG, GL_UNSIGNED_BYTE, BUFFER_OFFSET(cbcr_offset + cbcr_width * extra_lines_top * sizeof(uint16_t))); + check_error(); + glBindTexture(GL_TEXTURE_2D, userdata->tex_y); + check_error(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, BUFFER_OFFSET(y_offset + width * extra_lines_top)); + check_error(); + } glBindTexture(GL_TEXTURE_2D, 0); check_error(); GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, /*flags=*/0); @@ -472,7 +487,7 @@ void Mixer::thread_func() check_error(); } const PBOFrameAllocator::Userdata *userdata = (const PBOFrameAllocator::Userdata *)card->new_frame->userdata; - theme->set_input_textures(card_index, userdata->tex_y, userdata->tex_cbcr); + theme->set_input_textures(card_index, userdata->tex_y, userdata->tex_cbcr, userdata->last_width, userdata->last_height); } // Get the main chain from the theme, and set its state immediately. diff --git a/pbo_frame_allocator.cpp b/pbo_frame_allocator.cpp index 1c370b4..613506d 100644 --- a/pbo_frame_allocator.cpp +++ b/pbo_frame_allocator.cpp @@ -59,6 +59,9 @@ PBOFrameAllocator::PBOFrameAllocator(size_t frame_size, GLuint width, GLuint hei glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width / 2, height, 0, GL_RG, GL_UNSIGNED_BYTE, NULL); check_error(); + userdata[i].last_width = width; + userdata[i].last_height = height; + freelist.push(frame); } glBindBuffer(buffer, 0); diff --git a/pbo_frame_allocator.h b/pbo_frame_allocator.h index 452c006..aedae3b 100644 --- a/pbo_frame_allocator.h +++ b/pbo_frame_allocator.h @@ -29,6 +29,7 @@ public: struct Userdata { GLuint pbo; GLuint tex_y, tex_cbcr; + GLuint last_width, last_height; }; private: diff --git a/theme.cpp b/theme.cpp index 61e2aed..61e149c 100644 --- a/theme.cpp +++ b/theme.cpp @@ -613,6 +613,8 @@ void Theme::connect_signal(YCbCrInput *input, int signal_num) } input->set_texture_num(0, input_textures[signal_num].tex_y); input->set_texture_num(1, input_textures[signal_num].tex_cbcr); + input->set_width(input_textures[signal_num].width); + input->set_height(input_textures[signal_num].height); } void Theme::transition_clicked(int transition_num, float t) diff --git a/theme.h b/theme.h index f00c7a2..a5ecebc 100644 --- a/theme.h +++ b/theme.h @@ -15,6 +15,8 @@ #include #include +#include "defs.h" + namespace movit { class ResourcePool; struct ImageFormat; @@ -41,9 +43,12 @@ public: std::pair> get_chain(unsigned num, float t, unsigned width, unsigned height); - void set_input_textures(int signal_num, GLuint tex_y, GLuint tex_cbcr) { - input_textures[signal_num].tex_y = tex_y; - input_textures[signal_num].tex_cbcr = tex_cbcr; + void set_input_textures(int signal_num, GLuint tex_y, GLuint tex_cbcr, GLuint width, GLuint height) { + auto &tex = input_textures[signal_num]; + tex.tex_y = tex_y; + tex.tex_cbcr = tex_cbcr; + tex.width = width; + tex.height = height; } int get_num_channels() { return num_channels; } std::string get_channel_name(unsigned channel); @@ -64,6 +69,7 @@ private: movit::ResourcePool *resource_pool; struct { GLuint tex_y = 0, tex_cbcr = 0; + GLuint width = WIDTH, height = HEIGHT; } input_textures[MAX_CARDS]; int num_channels; unsigned num_cards; diff --git a/theme.lua b/theme.lua index abba220..1243ad1 100644 --- a/theme.lua +++ b/theme.lua @@ -7,6 +7,8 @@ -- where all the low-level details (such as texture formats) are handled by the -- C++ side and you generally just build chains. +-- TODO: Deal with inputs that are different from our native 1280x720 resolution. + local transition_start = -2.0 local transition_end = -1.0 local zoom_src = 0.0 -- 2.39.2