]> git.sesse.net Git - bmusb/blobdiff - bmusb.cpp
Fix wraparound in some timecode comparisons.
[bmusb] / bmusb.cpp
index 6867805e719e4c6983af99063f343cbb2dd94b1f..387e042900ea82bc10d3f7775e1915c7f8113c1e 100644 (file)
--- a/bmusb.cpp
+++ b/bmusb.cpp
@@ -93,6 +93,9 @@ FrameAllocator::Frame MallocFrameAllocator::alloc_frame()
 
 void MallocFrameAllocator::release_frame(Frame frame)
 {
+       if (frame.overflow > 0) {
+               printf("%d bytes overflow after last (malloc) frame\n", int(frame.overflow));
+       }
        unique_lock<mutex> lock(freelist_mutex);
        freelist.push(unique_ptr<uint8_t[]>(frame.data));
 }
@@ -155,16 +158,20 @@ void BMUSBCapture::dequeue_thread_func()
 
                uint16_t video_timecode = pending_video_frames.front().timecode;
                uint16_t audio_timecode = pending_audio_frames.front().timecode;
-               if (video_timecode < audio_timecode) {
+               if (uint16_less_than_with_wraparound(video_timecode, audio_timecode)) {
                        printf("Video block 0x%04x without corresponding audio block, dropping.\n",
                                video_timecode);
                        video_frame_allocator->release_frame(pending_video_frames.front().frame);
                        pending_video_frames.pop_front();
-               } else if (audio_timecode < video_timecode) {
-                       printf("Audio block 0x%04x without corresponding video block, dropping.\n",
+               } else if (uint16_less_than_with_wraparound(audio_timecode, video_timecode)) {
+                       printf("Audio block 0x%04x without corresponding video block, sending blank frame.\n",
                                audio_timecode);
-                       audio_frame_allocator->release_frame(pending_audio_frames.front().frame);
+                       QueuedFrame audio_frame = pending_audio_frames.front();
                        pending_audio_frames.pop_front();
+                       lock.unlock();
+                       frame_callback(audio_timecode,
+                                      FrameAllocator::Frame(), 0, 0x0000,
+                                      audio_frame.frame, AUDIO_HEADER_SIZE, audio_frame.format);
                } else {
                        QueuedFrame video_frame = pending_video_frames.front();
                        QueuedFrame audio_frame = pending_audio_frames.front();
@@ -195,6 +202,21 @@ void BMUSBCapture::start_new_frame(const uint8_t *start)
        uint16_t timecode = (start[1] << 8) | start[0];
 
        if (current_video_frame.len > 0) {
+               // If format is 0x0800 (no signal), add a fake (empty) audio
+               // frame to get it out of the queue.
+               // TODO: Figure out if there are other formats that come with
+               // no audio, and treat them the same.
+               if (format == 0x0800) {
+                       FrameAllocator::Frame fake_audio_frame = audio_frame_allocator->alloc_frame();
+                       if (fake_audio_frame.data == nullptr) {
+                               // Oh well, it's just a no-signal frame anyway.
+                               printf("Couldn't allocate fake audio frame, also dropping no-signal video frame.\n");
+                               current_video_frame.owner->release_frame(current_video_frame);
+                               current_video_frame = video_frame_allocator->alloc_frame();
+                               return;
+                       }
+                       queue_frame(format, timecode, fake_audio_frame, &pending_audio_frames);
+               }
                //dump_frame();
                queue_frame(format, timecode, current_video_frame, &pending_video_frames);
        }
@@ -263,8 +285,13 @@ void add_to_frame(FrameAllocator::Frame *current_frame, const char *frame_type_n
 
        int bytes = end - start;
        if (current_frame->len + bytes > current_frame->size) {
-               printf("%d bytes overflow after last %s frame\n",
-                       int(current_frame->len + bytes - current_frame->size), frame_type_name);
+               current_frame->overflow = current_frame->len + bytes - current_frame->size;
+               current_frame->len = current_frame->size;
+               if (current_frame->overflow > 1048576) {
+                       printf("%d bytes overflow after last %s frame\n",
+                               int(current_frame->overflow), frame_type_name);
+                       current_frame->overflow = 0;
+               }
                //dump_frame();
        } else {
                if (current_frame->interleaved) {