From 8b4a8b1610810c50ac7afe68577cd86cf04b2b06 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 29 Apr 2017 01:27:33 +0200 Subject: [PATCH] Support other sample rates than 48 kHz. --- bmusb.cpp | 27 +++++++++++++++++++++++++++ bmusb/bmusb.h | 1 + 2 files changed, 28 insertions(+) diff --git a/bmusb.cpp b/bmusb.cpp index ed6fa26..663a235 100644 --- a/bmusb.cpp +++ b/bmusb.cpp @@ -241,6 +241,26 @@ bool decode_video_format(uint16_t video_format, VideoFormat *decoded_video_forma return false; } +// There are seemingly no direct indicators of sample rate; you just get +// one frame's worth and have to guess from that. +int guess_sample_rate(const VideoFormat &video_format, size_t len) +{ + size_t num_samples = len / 3 / 8; + size_t num_samples_per_second = num_samples * video_format.frame_rate_nom / video_format.frame_rate_den; + + // See if we match or are very close to any of the mandatory HDMI sample rates. + const int candidate_sample_rates[] = { 32000, 44100, 48000 }; + for (int rate : candidate_sample_rates) { + if (abs(int(num_samples_per_second) - rate) < 50) { + return rate; + } + } + + fprintf(stderr, "%ld samples at %d/%d fps (%ld Hz) matches no known sample rate, assuming 48000 Hz\n", + num_samples, video_format.frame_rate_nom, video_format.frame_rate_den, num_samples_per_second); + return 48000; +} + } // namespace FrameAllocator::~FrameAllocator() {} @@ -332,6 +352,7 @@ void BMUSBCapture::dequeue_thread_func() if (has_dequeue_callbacks) { dequeue_init_callback(); } + size_t last_sample_rate = 48000; while (!dequeue_thread_should_quit) { unique_lock lock(queue_lock); queues_not_empty.wait(lock, [this]{ return dequeue_thread_should_quit || (!pending_video_frames.empty() && !pending_audio_frames.empty()); }); @@ -343,6 +364,7 @@ void BMUSBCapture::dequeue_thread_func() AudioFormat audio_format; audio_format.bits_per_sample = 24; audio_format.num_channels = 8; + audio_format.sample_rate = last_sample_rate; if (uint16_less_than_with_wraparound(video_timecode, audio_timecode)) { printf("Video block 0x%04x without corresponding audio block, dropping.\n", video_timecode); @@ -383,10 +405,15 @@ void BMUSBCapture::dequeue_thread_func() VideoFormat video_format; audio_format.id = audio_frame.format; if (decode_video_format(video_frame.format, &video_format)) { + if (audio_frame.frame.len != 0) { + audio_format.sample_rate = guess_sample_rate(video_format, audio_frame.frame.len); + last_sample_rate = audio_format.sample_rate; + } frame_callback(video_timecode, video_frame.frame, HEADER_SIZE, video_format, audio_frame.frame, AUDIO_HEADER_SIZE, audio_format); } else { + audio_format.sample_rate = last_sample_rate; frame_callback(video_timecode, FrameAllocator::Frame(), 0, video_format, audio_frame.frame, AUDIO_HEADER_SIZE, audio_format); diff --git a/bmusb/bmusb.h b/bmusb/bmusb.h index 7a31a4d..6d6f097 100644 --- a/bmusb/bmusb.h +++ b/bmusb/bmusb.h @@ -126,6 +126,7 @@ struct AudioFormat { uint16_t id = 0; // For debugging/logging only. unsigned bits_per_sample = 0; unsigned num_channels = 0; + unsigned sample_rate = 48000; }; enum PixelFormat { -- 2.39.2