Uploading images to the ATEM Switcher
TerryHewitt opened this issue · 7 comments
I have an ATEM Mini and I would like to populate the 20 still images buffer with images.
I can't see a function to upload the image. Have I missed it?
If I haven't I'm happy to have a go and add it to the library.
Best wishes
Terry
Hi Terry,
I've trying to implement it because of a previous request I've received... with no luck 😢
I tried to use libqatemcontrol as a reference but the switcher I have at hand responds with messages that not fit into libqatemcontrol
's message definitions.
It would be very nice from you to submit a pull request if you can do something about it.
Thanks!!
Thanks for the reply.
Yes, happy to have a go.
Would you also be happy sharing your 'attempted' code - to get me started?
Best wishes
Terry
Thanks a lot for the help, Terry!
I've just created a new branch for the issue: 20-uploading-images-to-the-atem-switcher and pushed the work in progress commits I had.
Basically, I was trying to emulate the libqatemcontrol library. The reason for choosing this one is that in the unofficial reverse engineered BMD protocol PyATEMMax
is based on, Kasper Skårhøj himself recommends it for uploading clips and stills.
You will find this code is not yet ready to be merged into master
, even if it worked:
- It has a lot of debug messages (look for
[DBG]
tags in log messages). - It has commented code from other libraries inserted as reference when coding.
If you succeed in making this work, we'll do a little cleanup before merging.
List of changes
I'll go through the list of changes to explain what I changed in each commit:
a765ac0 - Scraped new command IDs from wireshark-atem-dissector / libqatemcontrol
In this commit I could get a few unknown command names from libqatemcontrol and wireshark-atem-dissector.
PyATEMMax/ATEMProtocol.py
No useful code added, just nice descriptions for commands that won't be processed (because their message structure is unknown/undocumented).
8ef62a6 - File transfer WIP
In this commit I tried to implement the client/switcher commands that I could see libqatemcontrol
using for its file transfers.
Inside libqatemcontrol
:
- qatemconnection.cpp contains the code generating the command packets.
- qatemuploader.cpp is an example which supposedly uploads images to an ATEM switcher (didn't compile/try it myself).
As an example, to see the payload structure for the FTSU
(Data Transfer Request) command I found a requestData()
method in QAtemConnection
which filled the command fields, revealing the packet structure (see requestData() code).
PyATEMMax/ATEMProtocol.py
Moved the following commands from the not implemented to the implemented section:
LKST
: Lock StatePLCK
: Acquire Media LockLKOB
: Lock ObtainedLOCK
: Set Lock StateFTDE
: Data Transfer ErrorFTUA
: Data Transfer AckRXMS
: HyperDeck Settings Get
PyATEMMax/ATEMCommandHandlers.py
Implemented the parsing of the switcher side commands (notifications to the client):
LKST
: Lock StateLKOB
: Lock ObtainedFTDE
: Data Transfer ErrorFTUA
: Data Transfer AckRXMS
: HyperDeck Settings Get
PyATEMMax/ATEMSetterMethods.py
Implemented the construction of the client side commands (requests to the switcher):
LOCK
: Set Lock StatePLCK
: Acquire Media LockFTSU
: Data Transfer Request (ooops! fixed in 67bf8ba)FTSD
: Data Transfer to Switcher (ooops! fixed in 67bf8ba)
65a6318 - TEMPORARY: use events.py to test
In this commit I tried to follow the qatemuploader
example using the new commands (sadly, with no luck).
I'm using the events.py
library example as a temporary placeholder for the test code, it will be restored to its original state before merging.
examples/events.py
- Activated
DEBUG
log level both for the library and the socket communication, to get as much log info as possible. - Printed some values received from the switcher as soon the connection is established.
- Tried to initiate a data transfer.
- Trouble started here... explained below.
67bf8ba - Fix names of FTSD/FTSU
It seems I forgot removing the Not implemented
text from FTSU
/FTSD
and I found out while writing this text. This commit fixes that :)
0b28078 - Add tmp-dev-utils (TEMPORARY)
In this commit I upload the utilities I'm using to study the communications with the switcher (see below).
The problem
In the events.py
example, I first try a sendAcquireMediaLock()
with:
storeId
:0
index
:2
.
After that, I should wait for a LKOB
or LKST
but I'm getting away with a time.sleep(1)
because I can see hex logs ;)
Then, I do a sendInitDownloadToSwitcherRequest()
with:
transferId
:0
storeId
:0
index
:2
data_size
:100
After that the rest of code is commented, I suppose because the response from the switcher was not the expected at this point. Honestly... I tried this about 6 months ago and some details got lost in the way.
The debug tools
For all these tests, the stdout
hex dump offered by the DEBUG
logging activated in 65a6318
was not enough. I soon found myself pausing the console output to wrap my head around a stream of hex representations of messages to understand what was happening, and you know that's not good for human brains :)
So, my first attempt was to create a switcher-spy
, some kind of proxy with the ability to capture the traffic between a client and a switcher and save it to a log file.
The idea was to use it to record the conversation between the official ATEM client software and the switcher when an image was uploaded, so I could inspect those huge hex streams or even create a log reader to make it a bit easier.
The result are huge jsonl
files (see jsonlines.org) with never-ending lines of brain-killing hex values. A log-reader
was mandatory.
I would have loved to reuse the parser from the library, but... when starting the project I decided to follow the code structure of the original library to make the porting process easier. A refactor is an option I've been evaluating but I don't have that kind of time right now, so I kind of reprogrammed the ATEM message parsing in the log-reader
.
Both utilities are now uploaded to the repo in a tmp-dev-utils
folder that we'll remove before merging (the idea is to release them after that refactor I talked about).
The end
... and I think that's it !
Sorry for the loooooong answer, but I didn't want to leave anything behind, as you're being so kind to offer your help.
Thanks again, and please let me know if you have any doubts.
Hi Terry, thanks for the update!!
BTW, my name is Tony :)