From 82f82f4cb7644db337d3e171a812c2949f3e8d8a Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Mon, 19 Aug 2024 15:33:20 +0100 Subject: [PATCH 1/4] Only use buffered frame if num samples equals requested num samples A growing file may change the num samples when making the same request for a frame. E.g. the previous request may have returned 0 samples. --- src/mxf_reader/EssenceReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mxf_reader/EssenceReader.cpp b/src/mxf_reader/EssenceReader.cpp index 9e08a234..f16b3de0 100644 --- a/src/mxf_reader/EssenceReader.cpp +++ b/src/mxf_reader/EssenceReader.cpp @@ -83,7 +83,7 @@ bool EssenceReaderBuffer::PopOrPrepareRead(int64_t position, uint32_t num_sample { size_t offset = GetFrameBufferOffset(position); if (offset < GetBufferSize()) { - if (mRequestSampleCounts[offset] == num_samples) { + if (mRequestSampleCounts[offset] == num_samples && mReadSampleCounts[offset] == num_samples) { if (!mBufferFrames) { ClearBeforeFrames(offset); offset = 0; From 13dc2b5b6cc648da7787df88268d91f69331af25 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Mon, 19 Aug 2024 15:59:46 +0100 Subject: [PATCH 2/4] Use 64 bit tick count in apps to avoid rollover --- apps/bmxtranswrap/bmxtranswrap.cpp | 4 ++-- apps/mxf2raw/mxf2raw.cpp | 4 ++-- apps/raw2bmx/raw2bmx.cpp | 2 +- include/bmx/apps/AppUtils.h | 6 +++--- src/apps/AppUtils.cpp | 24 +++++++++++++----------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/apps/bmxtranswrap/bmxtranswrap.cpp b/apps/bmxtranswrap/bmxtranswrap.cpp index 85c3ddaf..e75a6a85 100644 --- a/apps/bmxtranswrap/bmxtranswrap.cpp +++ b/apps/bmxtranswrap/bmxtranswrap.cpp @@ -4586,7 +4586,7 @@ int main(int argc, const char** argv) // realtime transwrapping - uint32_t rt_start = 0; + uint64_t rt_start = 0; if (realtime) rt_start = get_tick_count(); @@ -4596,7 +4596,7 @@ int main(int argc, const char** argv) unsigned int gf_retry_count = 0; bool gf_read_failure = false; int64_t gf_failure_num_read = 0; - uint32_t gf_failure_start = 0; + uint64_t gf_failure_start = 0; // create clip file(s) and write samples diff --git a/apps/mxf2raw/mxf2raw.cpp b/apps/mxf2raw/mxf2raw.cpp index 470c2af1..3e52d408 100644 --- a/apps/mxf2raw/mxf2raw.cpp +++ b/apps/mxf2raw/mxf2raw.cpp @@ -2892,7 +2892,7 @@ int main(int argc, const char** argv) max_samples_per_read = 1920; // realtime reading - uint32_t rt_start = 0; + uint64_t rt_start = 0; if (realtime) rt_start = get_tick_count(); @@ -2900,7 +2900,7 @@ int main(int argc, const char** argv) unsigned int gf_retry_count = 0; bool gf_read_failure = false; int64_t gf_failure_num_read = 0; - uint32_t gf_failure_start = 0; + uint64_t gf_failure_start = 0; // read data bmx::ByteArray sound_buffer; diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index bea3ea84..9d9e5f79 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -6135,7 +6135,7 @@ int main(int argc, const char** argv) // realtime wrapping - uint32_t rt_start = 0; + uint64_t rt_start = 0; if (realtime) rt_start = get_tick_count(); diff --git a/include/bmx/apps/AppUtils.h b/include/bmx/apps/AppUtils.h index 083c324e..e75b955b 100644 --- a/include/bmx/apps/AppUtils.h +++ b/include/bmx/apps/AppUtils.h @@ -194,9 +194,9 @@ void init_progress(float *next_update); void print_progress(int64_t count, int64_t duration, float *next_update); void sleep_msec(uint32_t msec); -uint32_t get_tick_count(); -uint32_t delta_tick_count(uint32_t from, uint32_t to); -void rt_sleep(float rt_factor, uint32_t start_tick, Rational sample_rate, int64_t num_samples); +uint64_t get_tick_count(); +uint64_t delta_tick_count(uint64_t from, uint64_t to); +void rt_sleep(float rt_factor, uint64_t start_tick, Rational sample_rate, int64_t num_samples); diff --git a/src/apps/AppUtils.cpp b/src/apps/AppUtils.cpp index 13b86dbb..c8d93db7 100644 --- a/src/apps/AppUtils.cpp +++ b/src/apps/AppUtils.cpp @@ -1526,7 +1526,7 @@ void bmx::sleep_msec(uint32_t msec) #endif } -uint32_t bmx::get_tick_count() +uint64_t bmx::get_tick_count() { #if HAVE_CLOCK_GETTIME struct timespec now; @@ -1536,30 +1536,32 @@ uint32_t bmx::get_tick_count() if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) #endif return 0; - return (uint32_t)(now.tv_sec * 1000LL + now.tv_nsec / 1000000L); + return (uint64_t)(now.tv_sec * 1000LL + now.tv_nsec / 1000000L); #elif defined(_WIN32) - return GetTickCount(); + return GetTickCount64(); #else struct timeval now; if (gettimeofday(&now, 0) != 0) return 0; - return (uint32_t)(now.tv_sec * 1000LL + now.tv_usec / 1000); + return (uint64_t)(now.tv_sec * 1000LL + now.tv_usec / 1000); #endif } -uint32_t bmx::delta_tick_count(uint32_t from, uint32_t to) +uint64_t bmx::delta_tick_count(uint64_t from, uint64_t to) { - return (uint32_t)((int64_t)to - from + UINT32_MAX); + if (from >= to) + return 0; + return to - from; } -void bmx::rt_sleep(float rt_factor, uint32_t start_tick, Rational sample_rate, int64_t num_samples) +void bmx::rt_sleep(float rt_factor, uint64_t start_tick, Rational sample_rate, int64_t num_samples) { - uint32_t tick = get_tick_count(); - uint32_t target_tick = (uint32_t)(start_tick + 1000 * num_samples * - sample_rate.denominator / (rt_factor * sample_rate.numerator)); - uint32_t delta_tick = delta_tick_count(tick, target_tick); + uint64_t tick = get_tick_count(); + uint64_t target_tick = start_tick + (uint64_t)(1000 * num_samples * + sample_rate.denominator / (rt_factor * sample_rate.numerator)); + uint64_t delta_tick = delta_tick_count(tick, target_tick); if (delta_tick < 10000) // don't sleep if target_tick < tick or there are bogus tick values sleep_msec(delta_tick); } From 8dd6bb1931724c9c5ca01847b64e581032cb0a46 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Mon, 19 Aug 2024 16:00:44 +0100 Subject: [PATCH 3/4] Remove sleep limit for growing file and realtime processing in apps --- src/apps/AppUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/AppUtils.cpp b/src/apps/AppUtils.cpp index c8d93db7..6af0a5ae 100644 --- a/src/apps/AppUtils.cpp +++ b/src/apps/AppUtils.cpp @@ -1562,7 +1562,7 @@ void bmx::rt_sleep(float rt_factor, uint64_t start_tick, Rational sample_rate, i uint64_t target_tick = start_tick + (uint64_t)(1000 * num_samples * sample_rate.denominator / (rt_factor * sample_rate.numerator)); uint64_t delta_tick = delta_tick_count(tick, target_tick); - if (delta_tick < 10000) // don't sleep if target_tick < tick or there are bogus tick values + if (delta_tick) sleep_msec(delta_tick); } From 7f27a4e146fd5122cdb4fb412165a30751731b18 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Mon, 9 Sep 2024 17:14:23 +0100 Subject: [PATCH 4/4] mxfreader: Don't immediately log essence read errors Set the the MXF reader's mReadErrorMessage when less essence data is read from a file than was requested, but don't log the error. This avoids it being logged when reading a growing file where a later attempt succeeds. Note that this doesn't prevent non-essence read errors, e.g other KLVs. --- include/bmx/BMXException.h | 8 ++++++++ src/mxf_reader/EssenceReader.cpp | 4 ++-- test/growing_file/growing_file.md5 | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/bmx/BMXException.h b/include/bmx/BMXException.h index e6ec14e0..547d94fc 100644 --- a/include/bmx/BMXException.h +++ b/include/bmx/BMXException.h @@ -51,6 +51,14 @@ BMX_EXCEPTION(("'%s' check failed", #cond)); \ } while (0) +#define BMX_CHECK_NOLOG(cond) \ + do { \ + if (!(cond)) { \ + throw BMXException( \ + "'%s' check failed near %s:%d", #cond, __FILENAME__, __LINE__); \ + } \ + } while (0) + #define BMX_CHECK_M(cond, err) \ do { \ if (!(cond)) \ diff --git a/src/mxf_reader/EssenceReader.cpp b/src/mxf_reader/EssenceReader.cpp index f16b3de0..14186018 100644 --- a/src/mxf_reader/EssenceReader.cpp +++ b/src/mxf_reader/EssenceReader.cpp @@ -529,7 +529,7 @@ uint32_t EssenceReader::ReadClipWrappedSamples(uint32_t num_samples) frame->Grow((uint32_t)size); uint32_t num_read = mFile->read(frame->GetBytesAvailable(), (uint32_t)size); current_file_position += num_read; - BMX_CHECK(num_read == size); + BMX_CHECK_NOLOG(num_read == size); size -= mImageEndOffset; if (mImageStartOffset > 0) { @@ -638,7 +638,7 @@ uint32_t EssenceReader::ReadFrameWrappedSamples(uint32_t num_samples) if (!mParseOnly) { uint32_t num_read = mFile->read(frame->GetBytesAvailable(), (uint32_t)len); - BMX_CHECK(num_read == len); + BMX_CHECK_NOLOG(num_read == len); } else { mFile->skip(len); } diff --git a/test/growing_file/growing_file.md5 b/test/growing_file/growing_file.md5 index 4db7843c..7006bd33 100644 --- a/test/growing_file/growing_file.md5 +++ b/test/growing_file/growing_file.md5 @@ -1 +1 @@ -2c0703daa26c571738c6f313cfd2b054 \ No newline at end of file +aa99fd8e8e058b07af7db303dc58653c \ No newline at end of file