pyobjc
pyobjc copied to clipboard
metadata issue with AVCaptureStillImageOutput.captureStillImageAsynchronouslyFromConnection:completionHandler:
Describe the bug
When I use captureStillImageAsynchronouslyFromConnection:completionHandler on an instance of AVCaptureStillImageOutput I get the following error:
TypeError: Argument 3 is a block, but no signature available
Platform information
- Python version
3.9.13 - How was python installed (python.org, anaconda, homebrew, ...)
homebrew - macOS version
13.0 Beta (22A5342f)
To Reproduce
still_output = AVFoundation.AVCaptureStillImageOutput.new()
# ...
def on_complete(sample_buffer, err):
print("test")
still_output.captureStillImageAsynchronouslyFromConnection_completionHandler_(first_conn, on_complete)
Expected behavior callback to be executed with sample buffer
Additional context I looked into metadata a bit and did find something that might be useful. The following don't match whereas I have found that they match for other selectors:
# get metadata from class selector ("unbound")
print(AVFoundation.AVCaptureStillImageOutput.captureStillImageAsynchronouslyFromConnection_completionHandler_.__metadata__())
# get metadata from instance's selector
print(still_output.captureStillImageAsynchronouslyFromConnection_completionHandler_.__metadata__())
Here's the output for the above two prints:
# class selector:
{'retval': {'_template': True, 'type': b'v'}, 'arguments': ({'_template': True, 'type': b'@'}, {'_template': True, 'type': b':'}, {'_template': True, 'type': b'@'}, {'_template': True, 'type': b'@?', 'callable': {'retval': {'type': b'v'}, 'arguments': ({'type': b'^v', 'null_accepted': True}, {'type': b'^{opaqueCMSampleBuffer=}', 'null_accepted': True}, {'type': b'@'})}, 'callable_retained': True}), 'classmethod': False, 'hidden': False}
# instance selector:
{'retval': {'_template': True, 'type': b'v'}, 'arguments': ({'_template': True, 'type': b'@'}, {'_template': True, 'type': b':'}, {'_template': True, 'type': b'@'}, {'_template': True, 'type': b'@?'}), 'classmethod': False, 'hidden': False}
I also found overrides for this selector's metadata in the pyobjc AVFoundation module: https://github.com/ronaldoussoren/pyobjc/blob/5bc7a29ce8e31fd858c1f1b2796f051a0470d24c/pyobjc-framework-AVFoundation/Lib/AVFoundation/_metadata.py#L3356-L3375
I wonder if objc.registerMetaDataForSelector isn't updating the metadata everywhere that's needed? It seems to alter the class selector's metadata but not the instance selector's which I assume is what's used. IIUC register performs some sort of merge logic.. is there a way I can formulate a call to change the metadata that's used to see if that fixes the error I get?
I am not versed in how to go about patching the metadata for this to attempt to fix it... it just seems like somehow the callback's type definition is missing and needs added. But, it only appears missing on the instance selector (the class selector appears correct though I don't know if that's even used).
Thanks in advance!
Ok so I did some digging and it seems that instances of AVCaptureStillImageOutput were instances of AVCaptureStillImageOutput_Tundra at runtime so I used the metadata "fix" to that _Tundra class too. Hence the divergence in metadata between class selector and instance selector...
https://github.com/ronaldoussoren/pyobjc/blob/5bc7a29ce8e31fd858c1f1b2796f051a0470d24c/pyobjc-framework-AVFoundation/Lib/AVFoundation/_metadata.py#L3356-L3374
change
b"AVCaptureStillImageOutput",tob"AVCaptureStillImageOutput_Tundra",I added this metadata fix to my own codebase (not pyobjc repo) NOTE:r=objc.registerMetaDataForSelector
And, now things work! My instance's selector is fixed. And, my callback is invoked with a CMSampleBuffer.
Not sure what the _Tundra classes are in AVFoundation nor what to do to fix this officially, nor if this is a real fix... just wanted to leave a note that I accomplished what I wanted to do (fix metadata).
TLDR, fix AVCaptureStillImageOutput_Tundra metadata:
objc.registerMetaDataForSelector(
b"AVCaptureStillImageOutput_Tundra",
b"captureStillImageAsynchronouslyFromConnection:completionHandler:",
{
"arguments": {
3: {
"callable": {
"retval": {"type": b"v"},
"arguments": {
0: {"type": b"^v"},
1: {"type": b"^{opaqueCMSampleBuffer=}"},
2: {"type": b"@"},
},
},
"type": "@?",
}
}
},
)
Verify the change applies successfully by inspecting metadata before and after calling registerMetaDataForSelector:
print(AVCaptureStillImageOutput_Tundra.captureStillImageAsynchronouslyFromConnection_completionHandler_.metadata())
I assume metadata fixes would need applied for all AVFoundation types that have _Tundra types at runtime... I can help make that change. Before that change it would be prudent to know why these _Tundra types exist. And it probably would make sense to conditionally apply metadata fixes (only when the types exist).
Interesting...
The ObjC metadata system assumes that the documented classes are the base classes that introduce particular methods, and that's not true here. Worse yet, the various "Tundra" classes aren't even subclasses of the documented classes. That breaks the API contract of those documented classes, but I'm afraid filing an issue about his in Feedback Assistant would be a wast of time for this.
I'll update the metadata for this by tweaking some of the scripts I use for generating the _metadata modules.
Thanks for the insight and help.
The changeset I just pushed will fix the issue in the 9.0 release (which will be released just before macOS 13 is released).
There will be a separate changeset for 8.x later today (if all goes to plan).
Just tested the repo changes, works great! Thanks
Just curious, I see classclones used.. where is the metadata compiler code for that? Is that private?
Just tested the repo changes, works great! Thanks
Just curious, I see
classclonesused.. where is the metadata compiler code for that? Is that private?
That's private at this point. I started a major cleanup in the public repository, but that's making less progress than I'd like. I'm therefore still using a private copy of that code base.
BTW. Current plan is to push out a 8.5.x release over the weekend with a fix for this (and some other changes). The fix in that branch is slightly different and updates the generated metadata file (which should be fine because the 8.5 branch won't get updated metadata anyway).