]> git.sesse.net Git - nageru/blobdiff - mixer.cpp
Support audio-only FFmpeg inputs. Somewhat wonky, though.
[nageru] / mixer.cpp
index deaa8e73079710b7f13b8dffd6a9f084f0ae9b4c..b26e097e9e49bffc208dc890b047cdf1ea1f3978 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -731,9 +731,6 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                }
        }
 
-       int64_t frame_length = int64_t(TIMEBASE) * video_format.frame_rate_den / video_format.frame_rate_nom;
-       assert(frame_length > 0);
-
        size_t num_samples = (audio_frame.len > audio_offset) ? (audio_frame.len - audio_offset) / audio_format.num_channels / (audio_format.bits_per_sample / 8) : 0;
        if (num_samples > OUTPUT_FREQUENCY / 10 && card->type != CardType::FFMPEG_INPUT) {
                printf("%s: Dropping frame with implausible audio length (len=%d, offset=%d) [timecode=0x%04x video_len=%d video_offset=%d video_format=%x)\n",
@@ -748,6 +745,17 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                return;
        }
 
+       int64_t frame_length;
+       bool audio_only_frame = false;
+       if (video_frame.len - video_offset == 0 && num_samples > 0) {
+               // Audio-only frame (probably from FFmpegCapture).
+               frame_length = int64_t(TIMEBASE) * num_samples / OUTPUT_FREQUENCY;
+               audio_only_frame = true;
+       } else {
+               frame_length = int64_t(TIMEBASE) * video_format.frame_rate_den / video_format.frame_rate_nom;
+       }
+       assert(frame_length > 0);
+
        int dropped_frames = 0;
        if (card->last_timecode != -1) {
                dropped_frames = unwrap_timecode(timecode, card->last_timecode) - card->last_timecode - 1;
@@ -819,7 +827,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.
+               // so that pts can go up accordingly. (This is also used for audio-only frames.)
                {
                        unique_lock<mutex> lock(card_mutex);
                        CaptureCard::NewFrame new_frame;
@@ -827,6 +835,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                        new_frame.length = frame_length;
                        new_frame.interlaced = false;
                        new_frame.dropped_frames = dropped_frames;
+                       new_frame.audio_only = audio_only_frame;
                        new_frame.received_timestamp = video_frame.received_timestamp;
                        card->new_frames.push_back(move(new_frame));
                        card->jitter_history.frame_arrived(video_frame.received_timestamp, frame_length, dropped_frames);
@@ -1032,7 +1041,8 @@ void Mixer::thread_func()
                        if (card_index == master_card_index || !has_new_frame[card_index]) {
                                continue;
                        }
-                       if (new_frames[card_index].frame->len == 0) {
+                       if (new_frames[card_index].frame->len == 0 &&
+                           !new_frames[card_index].audio_only) {
                                ++new_frames[card_index].dropped_frames;
                        }
                        if (new_frames[card_index].dropped_frames > 0) {