Yeah, it took me a while to reason about what expects channels-first/channels-last. I eventually got this working by copying the c++ code from the pytorch torchvision utils file and modifying it to be the way I expected (by reducing the halving of the vertical dimension to  only once, and then adding a halving of the horizontal dimension)
I can isolate the problem away from any sort of ordering of RGB channel order or even reading the RGB output. I think that the read access pattern for the U/V buffer seems off.
Here’s the code from the pytorch repo: pytorch/pytorch_vision_jni.cpp at 104b2c610b464d205e867dd136973c8bd1913ba8 · pytorch/pytorch · GitHub 2. I just added two lines to set 0s in the U/V buffer to indices as they’re being read: activity.kt · GitHub
On the android side, I’m just calling the function on an image. I don’t even try to use its output: activity.kt · GitHub
This image is what I get on my phone (Pixel 3XL)DSC015926000×3376 2.11 MB . Only half the screen turns green, which is what you expect if u and v are 0. The rest of the image seems untouched, so I don’t even think the function is reading all the U/V buffer. This behavior matches what I expect if indeed the vertical dimension is being halved twice as I think the current code in the repo is doing.