-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RaspiVid: motion vector synchronization is awry #210
Comments
Must admit I'm not 100% sure why you are getting the results you have... I did specifically push out a frame of 0 motion vectors for any I-Frames (i.e. Frame 1) but Frame 2 should give you the vector between frame 1 and frame 2 |
MVs are after the encoded data as video_encode appears to have been set to enforce that ordering (output_type only gets set to EV_OUTPUT_SIDEINFO after the first non-header bytes packet). That's probably the behaviour needed for eede. It could be reversed as EEDE is not officially supported. I think the example is a bad one. The pen coming into frame will NOT produce sensible motion vectors as there in no sensible block that is black to use for predicting those macroblocks. So I think this is actually the correct behaviour, other than it being nice if the MVs were before the encoded data. |
Perhaps this is down to me misunderstanding how the sum of differences image is arrived at (I do accept that the displacement vectors will be nonsense), but surely the difference image between video frames 3 and 4 (no pen -> pen) should not be completely smooth, as in the contrast stretched plot of MV frame 4 below? A related observation is that if I capture scene A, stop the recording, then point the camera at scene B (different) and do a second capture, MV buffer 2 from the second capture contains differences related to the scene A capture, with no scene B details appearing until MV buffer 3. |
@gsh Back to you as you may remember more of how the CME operates. Your code does all look sane on first glance - if I can then I'll try running it up with a debugger to see if there is something wrong in the sequencing. |
Yes, the CME works by doing SADs (sum of absolute differences) at every position within its search area then it returns the lowest vector as long as the SAD is less than some threshold, otherwise it just returns zero (a zero vector encodes to a small bit stream so it's just trying to punish larger vectors) So the difference between two images may be a full set of vectors of zeros because it couldn't find a suitable match in the previous image for the macroblock (which if the previous image is all the same then you'd expect a zero vector to be as good as any other vector) Gordon |
Right, but clearly in the most recent image the blocks occupied by the pen (which is essentially NW to SE diagonal across the frame) do not have zero values, they have intensities very similar to their neighbours in non-pen areas, as if it were encoding the difference of two frames neither of which have the pen. |
I want to confirm the issue. I have modified raspistill to use the still_port and could change the position of an object in one image. Additionally the the second motion buffer seems wrong to me. Could an old, not yet released buffer from the first frame creates this additional buffer? For reference the recorded data: |
I've found something that looks a little fishy in the code and I think would cause 1 frame of latency. Email discussion is ongoing between Dom, Gordon, and myself as the solution isn't immediately obvious without crippling performance. I can't remember (may have never known) sufficient details of the H264 hardware block to say for certain how it is meant to work around this bit. |
@ethanol100: could you post your test app somewhere? I have a potential fix, but currently no easy way of testing. |
I modified raspivid not raspistill... |
Thank you. I'll try it out as soon as I get a chance (possibly tomorrow morning). |
Looks like we have a solution. The original code was reading the CME output memory without having waited for it to complete, hence got the results for the previous frame. The synchronisation required for H264 encode is done with a hardware interlock on the results. Thanks again @ethanol100 for the test case - saved me a lot of time. Although I do see a changing in FOV for each of the captures - is that expected? I'm guessing switching between sensor modes (probably the 1080P cropped and 5MPix modes), but didn't stop to investigate. |
kernel: gpio: Only clear the currently occurring interrupt. Avoids losing interrupts See: raspberrypi/linux#760 kernel: bcm2708: armctrl: add space to allocate irq descriptors Drivers that act as interrupt controllers need to allocate irq descriptors. This adds room for that. firmware: Inline motion vectors - wait for CME to complete first See: raspberrypi/userland#210
Firmware has been updated. Please run rpi-update and test again. |
kernel: gpio: Only clear the currently occurring interrupt. Avoids losing interrupts See: raspberrypi/linux#760 kernel: bcm2708: armctrl: add space to allocate irq descriptors Drivers that act as interrupt controllers need to allocate irq descriptors. This adds room for that. firmware: Inline motion vectors - wait for CME to complete first See: raspberrypi/userland#210
This fixed the issue for me. Thanks for the quick fix and for the fast firmware update. |
@malc0 okay for you? |
Yes, both of my tests pass well. Thanks for taking the time to look in to (and fix) this. |
Thanks 6by9! |
kernel: gpio: Only clear the currently occurring interrupt. Avoids losing interrupts See: raspberrypi/linux#760 kernel: bcm2708: armctrl: add space to allocate irq descriptors Drivers that act as interrupt controllers need to allocate irq descriptors. This adds room for that. firmware: Inline motion vectors - wait for CME to complete first See: raspberrypi/userland#210
I think motion vectors is completely "unsynchronized"
|
@konstantins-tracxpoint Please open a new issue (referencing this one) with as much detail as possible. You also reference a test app that no one else knows anything about - more information please. |
It seems the motion vectors always arrive a frame late relative to the video, which is odd considering they ought to be available before the fully encoded video frame is.
The below image shows the frames from a short recording made using raspivid -ss 5000 -fps 20 -t 700 -o moo.h264 -x moo.imv, while the bottom image shows plots of the corresponding SAD motion vector coefficients (files available at http://sb476.user.srcf.net/late_mvs/moo.h264 and http://sb476.user.srcf.net/late_mvs/moo.imv ).
In the recording I waved a pen in front of the camera, seen in frame 4 of the recording, but not apparent until frame 5 (and residually 6) of the motion vectors.
I had added printf("timedelta %lld pts %lld flags %x\n", vcos_getmicrosecs64()/1000-base_time, buffer->pts, buffer->flags); near the top of encoder_buffer_callback(), which after some formatting and annotation of frames (F) versus motion vectors (MV) gives:
Two things are apparent: MV buffers have no timestamp, but they always arrive immediately following the video buffer. It can be seen that MV 5 arrives 49 ms after F 4 (with MV 4 and F 5 intervening), when inspection of the images above suggest they ought to arrive together, or even with the motion vectors preceding the encoded video.
While attaching correct timestamps to MV buffers would help make this clear, it seems there is some strange delay going on in the buffers' delivery.
The text was updated successfully, but these errors were encountered: