@@ -27,6 +27,7 @@ namespace image_io {
2727
2828#define TIMEOUT_IN_US_SHORTER 3 * 1000 * 1000
2929#define TIMEOUT_IN_US_LONGER 30 * 1000 * 1000
30+ #define FRAME_JUMP_THRESHOLD 1000
3031
3132class U3V {
3233protected:
@@ -517,6 +518,57 @@ class U3V {
517518 }
518519 }
519520
521+ // NOTE: The following are assumed to be class members:
522+ // - device_idx_
523+ // - devices_[device_idx_].stream_
524+ // - devices_[device_idx_].frame_count_
525+ // - frame_count_method_ (only TYPESPECIFIC3 or TIMESTAMP are expected)
526+ // - get_frame_count_from_genDC_descriptor(...)
527+
528+ /* *
529+ * Always re-pop a buffer from the stream, update the frame count,
530+ * and return the updated frame count.
531+ *
532+ * @param bufs Vector of ArvBuffer pointers (bufs[device_idx_] will be updated)
533+ * @param timeout_us Timeout for arv_stream_timeout_pop_buffer() in microseconds
534+ * @return Updated frame count
535+ *
536+ * @throws std::runtime_error if buffer pop times out
537+ */
538+ uint32_t repop_and_update_framecount (std::vector<ArvBuffer *> &bufs, int32_t timeout_us) {
539+ // 1) Always pop a new buffer and overwrite the current one
540+ ArvBuffer *new_buf =
541+ arv_stream_timeout_pop_buffer (devices_[device_idx_].stream_ , timeout_us);
542+
543+ if (new_buf == nullptr ) {
544+ // Failed to obtain a buffer within the timeout
545+ throw std::runtime_error (
546+ " arv_stream_timeout_pop_buffer() returned null (timeout)" );
547+ }
548+
549+ bufs[device_idx_] = new_buf;
550+
551+ // 2) Update the frame count (only two methods are expected)
552+ uint32_t frame_count;
553+
554+ if (frame_count_method_ == FrameCountMethod::TYPESPECIFIC3 ) {
555+ // Extract frame count from GenDC descriptor
556+ frame_count = static_cast <uint32_t >(
557+ get_frame_count_from_genDC_descriptor (
558+ bufs[device_idx_], devices_[device_idx_]));
559+ } else {
560+ // FrameCountMethod::TIMESTAMP is assumed here
561+ // Use the lower 32 bits of the timestamp as the frame count
562+ frame_count = static_cast <uint32_t >(
563+ arv_buffer_get_timestamp (bufs[device_idx_]) & 0x00000000FFFFFFFFULL );
564+ }
565+
566+ devices_[device_idx_].frame_count_ = frame_count;
567+
568+ // 3) Return the updated frame count
569+ return frame_count;
570+ }
571+
520572 g_object_unref_t g_object_unref;
521573
522574 arv_get_major_version_t arv_get_major_version;
@@ -818,6 +870,25 @@ class U3VRealCam: public U3V{
818870 latest_cnt = skip_invalid_framecount_0xFFFFFFFF (bufs, latest_cnt, timeout_us);
819871 }
820872
873+ const int64_t diff = static_cast <int64_t >(latest_cnt) - static_cast <int64_t >(frame_cnt_);
874+ const int64_t adiff = std::abs (diff);
875+
876+ // Re-acquire buffer if frame counter diff exceeds FRAME_JUMP_THRESHOLD or frame_cnt_ is 0
877+ if (adiff > FRAME_JUMP_THRESHOLD && frame_cnt_ != 0 ) {
878+
879+ // Record latest_cnt before and after repop
880+ const uint32_t before = latest_cnt;
881+
882+ // Execute repop (always re-acquire buffer & update framecount)
883+ const uint32_t after = repop_and_update_framecount (bufs, timeout_us);
884+ latest_cnt = after;
885+
886+ // Log output
887+ log::debug (" [U3V][DIFE][RealCam/REPOP] latest_cnt updated: before=0x{:x} after=0x{:x} ({} -> {}) frame_cnt_={} abs(diff)={}" ,
888+ before, after, before, after, frame_cnt_, adiff);
889+ }
890+
891+
821892 int internal_count = 0 ;
822893 int max_internal_count = 1000 ;
823894
@@ -844,6 +915,10 @@ class U3VRealCam: public U3V{
844915 }
845916 }
846917
918+
919+ log::debug (" [U3V][GETF][RealCam/Came1USB2] Get frame: before=0x{:x} after=0x{:x} ({} -> {})" ,
920+ frame_cnt_, latest_cnt, frame_cnt_, latest_cnt);
921+
847922 frame_cnt_ = latest_cnt;
848923 auto sz = (std::min)(devices_[device_idx_].image_payload_size_ , static_cast <int32_t >(outs[0 ].size_in_bytes ()));
849924 ::memcpy (outs[0 ].data(), arv_buffer_get_part_data(bufs[device_idx_], 0 , nullptr ), sz);
@@ -1104,11 +1179,11 @@ class U3VRealCam: public U3V{
11041179 }
11051180 log::info (" \t Device/USB {}::{} : {}" , index_on_opened_device, " OperationMode" , operation_mode_in_string);
11061181 }
1107-
1182+
11081183 index_on_opened_device += 1 ;
11091184 }else {
11101185 log::info (" \t Device/USB {}::{} : {} ... skipped" , index_on_opened_device, " device protocol" , device_protocol);
1111-
1186+
11121187 }
11131188 index_on_detected_device += 1 ;
11141189 }
@@ -1324,6 +1399,25 @@ class U3VGenDC: public U3V{
13241399 latest_cnt = skip_invalid_framecount_0xFFFFFFFF (bufs, latest_cnt, timeout_us);
13251400 }
13261401
1402+ const int64_t diff = static_cast <int64_t >(latest_cnt) - static_cast <int64_t >(frame_cnt_);
1403+ const int64_t adiff = std::abs (diff);
1404+
1405+ // Re-acquire buffer if frame counter diff exceeds FRAME_JUMP_THRESHOLD or frame_cnt_ is 0
1406+ if (adiff > FRAME_JUMP_THRESHOLD && frame_cnt_ != 0 ) {
1407+
1408+ // Record latest_cnt before and after repop
1409+ const uint32_t before = latest_cnt;
1410+
1411+ // Execute repop (always re-acquire buffer & update framecount)
1412+ const uint32_t after = repop_and_update_framecount (bufs, timeout_us);
1413+ latest_cnt = after;
1414+
1415+ // Log output
1416+
1417+ log::debug (" [U3V][DIFE][GenDC/REPOP] latest_cnt updated: before=0x{:x} after=0x{:x} ({} -> {}) frame_cnt_={} abs(diff)={}" ,
1418+ before, after, before, after, frame_cnt_, adiff);
1419+ }
1420+
13271421 int internal_count = 0 ;
13281422 int max_internal_count = 1000 ;
13291423
@@ -1349,6 +1443,9 @@ class U3VGenDC: public U3V{
13491443 }
13501444 }
13511445
1446+ log::debug (" [U3V][GETF][GenDC/Came1USB2] Get frame: before=0x{:x} after=0x{:x} ({} -> {})" ,
1447+ frame_cnt_, latest_cnt, frame_cnt_, latest_cnt);
1448+
13521449 frame_cnt_ = latest_cnt;
13531450 ::memcpy (outs[0 ], arv_buffer_get_data(bufs[device_idx_], nullptr ), devices_[device_idx_].u3v_payload_size_);
13541451 // ::memcpy(outs[1], &(devices_[device_idx_].header_info_), sizeof(ion::bb::image_io::rawHeader));
0 commit comments