]> git.sesse.net Git - nageru/blobdiff - mixer.cpp
Rename bmusb_mutex to card_mutex; it is not really bound to bmusb anymore.
[nageru] / mixer.cpp
index d544b0bf0801ba5208d10ddb0f37b396cd6911a8..05013b10e3569387d0b0538a3afd6d42b9267640 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -203,7 +203,7 @@ Mixer::~Mixer()
 
        for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
                {
-                       unique_lock<mutex> lock(bmusb_mutex);
+                       unique_lock<mutex> lock(card_mutex);
                        cards[card_index].should_quit = true;  // Unblock thread.
                        cards[card_index].new_frames_changed.notify_all();
                }
@@ -269,7 +269,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                        // Found a stable signal, so stop scanning.
                        is_mode_scanning[card_index] = false;
                } else {
-                       static constexpr double switch_time_s = 0.5;  // Should be enough time for the signal to stabilize.
+                       static constexpr double switch_time_s = 0.1;  // Should be enough time for the signal to stabilize.
                        steady_clock::time_point now = steady_clock::now();
                        double sec_since_last_switch = duration<double>(steady_clock::now() - last_mode_scan_change[card_index]).count();
                        if (sec_since_last_switch > switch_time_s) {
@@ -347,7 +347,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                // Still send on the information that we _had_ a frame, even though it's corrupted,
                // so that pts can go up accordingly.
                {
-                       unique_lock<mutex> lock(bmusb_mutex);
+                       unique_lock<mutex> lock(card_mutex);
                        CaptureCard::NewFrame new_frame;
                        new_frame.frame = RefCountedFrame(FrameAllocator::Frame());
                        new_frame.length = frame_length;
@@ -363,6 +363,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
 
        unsigned num_fields = video_format.interlaced ? 2 : 1;
        steady_clock::time_point frame_upload_start;
+       bool interlaced_stride = false;
        if (video_format.interlaced) {
                // Send the two fields along as separate frames; the other side will need to add
                // a deinterlacer to actually get this right.
@@ -371,6 +372,9 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                assert(frame_length % 2 == 0);
                frame_length /= 2;
                num_fields = 2;
+               if (video_format.second_field_start == 1) {
+                       interlaced_stride = true;
+               }
                frame_upload_start = steady_clock::now();
        }
        userdata->last_interlaced = video_format.interlaced;
@@ -394,8 +398,13 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                // Note that this means we must hold on to the actual frame data in <userdata>
                // until the upload command is run, but we hold on to <frame> much longer than that
                // (in fact, all the way until we no longer use the texture in rendering).
-               auto upload_func = [field, video_format, y_offset, cbcr_offset, cbcr_width, userdata]() {
-                       unsigned field_start_line = (field == 1) ? video_format.second_field_start : video_format.extra_lines_top + field * (video_format.height + 22);
+               auto upload_func = [field, video_format, y_offset, cbcr_offset, cbcr_width, interlaced_stride, userdata]() {
+                       unsigned field_start_line;
+                       if (field == 1) {
+                               field_start_line = video_format.second_field_start;
+                       } else {
+                               field_start_line = video_format.extra_lines_top;
+                       }
 
                        if (userdata->tex_y[field] == 0 ||
                            userdata->tex_cbcr[field] == 0 ||
@@ -433,16 +442,32 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
 
                        glBindTexture(GL_TEXTURE_2D, userdata->tex_cbcr[field]);
                        check_error();
+                       if (interlaced_stride) {
+                               glPixelStorei(GL_UNPACK_ROW_LENGTH, cbcr_width * 2);
+                               check_error();
+                       } else {
+                               glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+                               check_error();
+                       }
                        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cbcr_width, video_format.height, GL_RG, GL_UNSIGNED_BYTE, BUFFER_OFFSET(field_cbcr_start));
                        check_error();
                        glBindTexture(GL_TEXTURE_2D, userdata->tex_y[field]);
                        check_error();
+                       if (interlaced_stride) {
+                               glPixelStorei(GL_UNPACK_ROW_LENGTH, video_format.width * 2);
+                               check_error();
+                       } else {
+                               glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+                               check_error();
+                       }
                        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_format.width, video_format.height, GL_RED, GL_UNSIGNED_BYTE, BUFFER_OFFSET(field_y_start));
                        check_error();
                        glBindTexture(GL_TEXTURE_2D, 0);
                        check_error();
                        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
                        check_error();
+                       glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+                       check_error();
                };
 
                if (field == 1) {
@@ -458,7 +483,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                }
 
                {
-                       unique_lock<mutex> lock(bmusb_mutex);
+                       unique_lock<mutex> lock(card_mutex);
                        CaptureCard::NewFrame new_frame;
                        new_frame.frame = frame;
                        new_frame.length = frame_length;
@@ -628,7 +653,7 @@ Mixer::OutputFrameInfo Mixer::get_one_frame_from_each_card(unsigned master_card_
 start:
        // The first card is the master timer, so wait for it to have a new frame.
        // TODO: Add a timeout.
-       unique_lock<mutex> lock(bmusb_mutex);
+       unique_lock<mutex> lock(card_mutex);
        cards[master_card_index].new_frames_changed.wait(lock, [this, master_card_index]{ return !cards[master_card_index].new_frames.empty() || cards[master_card_index].capture->get_disconnected(); });
 
        if (cards[master_card_index].new_frames.empty()) {