Code that detects if there's gyro data needs updating.
latenitefilms opened this issue · 16 comments
Looking at this code:
if path.ends_with(".gyroflow") {
if let Ok(data) = std::fs::read_to_string(&path) {
if !data.contains("\"raw_imu\": null") || !data.contains("\"quaternions\": null") {
instance_data.param_project_data.set_value(data.clone())?;
} else {
if let Some((_, stab)) = instance_data.gyrodata.peek_lru() {
if let Ok(data) = stab.export_gyroflow_data(false, false, "{}") {
instance_data.param_project_data.set_value(data)?;
}
}
}
} else {
instance_data.param_project_data.set_value("".to_string())?;
}
} else {
if let Some((_, stab)) = instance_data.gyrodata.peek_lru() {
if let Ok(data) = stab.export_gyroflow_data(false, false, "{}") {
instance_data.param_project_data.set_value(data)?;
}
}
}
Currently it's reading the Gyroflow Project JSON as a string, and checking for raw_imu
and quaternions
strings - however, in the current Gyroflow Project JSON, gyro_source
> file_metadata
is stored as a blob of data - so you'll never find the raw_imu
and quaternions
strings.
This should be updated to read the raw_imu
and quaternions
data from the file_metadata
contents.
However, I'm currently using this code in Gyroflow Toolbox:
//---------------------------------------------------------
// Does the Gyroflow Project contain Stabilisation Data?
// Returns "YES" or a failure string.
//---------------------------------------------------------
#[no_mangle]
pub extern "C" fn doesGyroflowProjectContainStabilisationData(
gyroflow_project_data: *const c_char,
) -> *const c_char {
//---------------------------------------------------------
// Convert the Gyroflow Project data to a `&str`:
//---------------------------------------------------------
let gyroflow_project_data_pointer = unsafe { CStr::from_ptr(gyroflow_project_data) };
let gyroflow_project_data_string = gyroflow_project_data_pointer.to_string_lossy();
let stab = StabilizationManager::default();
//---------------------------------------------------------
// Import the `gyroflow_project_data_string`:
//---------------------------------------------------------
let blocking = true;
let cancel_flag = Arc::new(AtomicBool::new(false));
let mut is_preset = false;
match stab.import_gyroflow_data(
gyroflow_project_data_string.as_bytes(),
blocking,
None,
|_|(),
cancel_flag,
&mut is_preset
) {
Ok(_) => {
//---------------------------------------------------------
// Check if gyroflow project contains stabilization data:
//---------------------------------------------------------
let has_motion = {
let gyro = stab.gyro.read();
!gyro.file_metadata.raw_imu.is_empty() || !gyro.file_metadata.quaternions.is_empty()
};
//---------------------------------------------------------
// Return the result as a string:
//---------------------------------------------------------
let result_string = if has_motion {
"YES"
} else {
"NO"
};
let result = CString::new(result_string).unwrap();
return result.into_raw()
},
Err(e) => {
//---------------------------------------------------------
// An error has occurred:
//---------------------------------------------------------
log::error!("[Gyroflow Toolbox Rust] Error importing gyroflow data: {:?}", e);
let error_msg = format!("{}", e);
let result = CString::new(error_msg).unwrap();
return result.into_raw()
},
}
}
...and it returns NO
for an R3D Gyroflow Project that is synced and working, so I think something is wrong in gyroflow_core
too?
I think the problem why my code fails sometimes is a sandbox issue. gyroflow_core
doesn't actually have read access to the R3D file which contains the gyro data, so the import_gyroflow_data
function in gyroflow_core
doesn't seem to just load the gyro data from the JSON in this case.
This shouldn't be a sandbox issue because there's a check if the file can actually be opened and read in this condition you linked
Ummm... well, then I'm not sure why import_gyroflow_data
isn't populating the file_metadata.raw_imu
and file_metadata.quaternions
values properly then.
I might see if there's a way I can just decompress the file_metadata
outside of gyroflow_core
so that I can better debug what's going on.
Note to self...
Interestingly... if I open up FCPX, and import the Gyroflow project, without granting Gyroflow Toolbox sandbox access to the R3D it works correctly. It still works correctly when I press Reload Gyroflow Project too.
std::fs::File::open(&gyro_path).is_err(): true
However, if I then delete the Gyroflow Toolbox effect, delete the Gyroflow project at the Finder level, then try and import the R3D file - I get errors.
So the problem isn't in the Gyroflow Project/JSON data itself, and it most likely not in how gyroflow_core
reads the data. It might be some kind of caching in StabilizationManager
?
Ok, I'm not sure why, but I can confirm... I can only get my code to work when gyroflow_core
DOESN'T have access to the R3D
file. If gyroflow_core
can't access the R3D
file (due to the macOS sandbox) then my doesGyroflowProjectContainStabilisationData()
check works as intended. However, if it does have sandbox access, then it will return NO
.
I do think there might be a logic error in is_compressed
in gyroflow_core
- i.e. I think this might be the opposite way around?
let is_compressed = obj.get("raw_imu").map(|x| x.is_string()).unwrap_or_default();
...and I also think there might be some logic error somewhere in here:
} else if gyro_path.exists() && blocking {
if let Err(e) = self.load_gyro_data(&util::path_to_str(&gyro_path), is_main_video, &Default::default(), progress_cb, cancel_flag) {
::log::warn!("Failed to load gyro data from {:?}: {:?}", gyro_path, e);
}
}
Note to self... turned out that the issue I was having with R3D files was due to sandbox permissions.
This has been resolved in: gyroflow/gyroflow@10c8853
However, the original issue - i.e. the OpenFX bug - still needs to be resolved.
Fixed in 33d71a8#diff-62a6c326342846993ba024144b4abbf39a3bf82efa6a748164b5062ab8254fc4R928
In GyroflowToolbox you can now use StabilizationManager::project_has_motion_data