-
Notifications
You must be signed in to change notification settings - Fork 1.7k
image_fx won't empty buffers in non-tunnelled mode #213
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
Comments
From openmax guy: We set the component up in stripe mode, with 1080p frame size at 16 rows per buffer. We send a single output buffer without making sure that nFilledLen=nFlags=0. We then send a single input buffer marked with ENDOFFRAME and waits for the input buffer to be returned (I assume the call to waitForEmpty does this). There does seem to be a problem, but I've got two questions first: • Does the component work correctly when we send full frames rather than stripes? If neither of these work, there there is a more obvious bug to fix first. |
As far as I can see full frame mode does not work either. I actually use the component in full frame mode in my usecase, but can't get that to work. No matter how/when I set the ENDOFFRAME flag. |
Anything I can do to assist you further? Provide more testcases or something like that? |
I'm a little confused by this comment, btw: "We set the component up in stripe mode, with 1080p frame size at 16 rows per buffer.". The example code I posted sends a full frame and flags it with ENDOFFRAME. nSliceHeight is set to a multiple of 16 to match the requirements as stated in the documentation. |
The nSliceHeight determines the size of each buffer output. |
@popcornmix This is exactly what I do in my example:
So the example should be in full frame mode. Just one more note: I just noticed that for empty buffers (nFilledLen==0) the EmptyBufferDone callback is executed. |
Any news on this? Sorry for bugging :) |
I've had a look at this now, sorry for the delay. The problem is not waiting for the state transition to executing to complete before providing the output port with a buffer. This means the call to FillThisBuffer is failing with an OMX_ErrorIncorrectStateOperation, since you're not allowed to provide buffers in the idle state. If you put a waitFor(OMX_StateExecuting) before the call to FillThisBuffer, then your buffer gets accepted. There isn't another call to FillThisBuffer in the for loop, so we then get stuck at the second buffer. You'll need to add code to wait for the FillBufferDone callback to be called, in the same way we've got waitForEmpty. FYI the way I debugged this problem was to add a function to use the core function OMX_GetDebugInformation:
I put a call to this function at the point where the client was getting stuck, this then shows the current state of the IL components and ports. It's in csv format, so not the easiest to manually parse on the screen, but says:
This told me to look at the way we were supplying output buffers. Given that state transitions are asynchronous, the problem was easy to spot. Hope this helps. |
Thanks for your hints, actually they helped to fix the test case, which is good. The bad thing is that the actual code I initially spotted the issue with (image_fx deinterlace module for vlc, see https://github.com/julianscheel/vlc-omx/blob/master/modules/codec/omxil/deinterlace.c) did not suffer this issue. |
Looking at deinterlace.c, do calls to OMX_EmptyThisBuffer/OMX_FillThisBuffer return success? |
Oh, this was a good note. I wonder why I did not check for omx error there in the first place. I get indeed an error, stating that the state is not correct:
But I wonder a bit why this error occurs as the image_fx component is in OMX_StateExecuting according to the debug information? You have any hint on this? |
Looking at the (GPU) code, that error is generated by one of: |
Hm, looking at the debug information:
Column "State" says: OMX_StateExecuting
Column "State" (the 2nd one) says: Enabled for both ports
Wouldn't this be only the case after calling
Column "Pending state" is empty. Am I missing something? |
Got some progress. Actually I garbled pInput/OutputPortPrivate, which was the reason for the Fill/EmptyThisBuffer calls to fail. But unfortunately I still don't get any callbacks. Debug information looks like this:
Any more hints what might go wrong? |
Ok, I just figured out the left over difference between my testcase and the VLC code has been the selected image filter. In the testcase I had selected ColourSwap, while in the VLC code I had the DeinterlaceAdvanced selected. If I choose ColourSwap in VLC the code runs fine and passes the data. Although it does not seem to actually swap the color. |
There is something a bit ugly when using the deinterlace effect. It needs to acquire three consecutive video frames for processing. This means the processing pipeline requires extra buffers to be available or it stalls. See: Now, if you are not tunneling to video_decode you'll need a different approach. Possibly increasing the number of input buffers to image_fx will have the same effect. |
Thanks for that hint. This got us a little further. We finally get events fired as expected. But unfortunately the output picture is always just a plain green buffer. So it seems the image_fx is only clearing the buffer, but not filling it. |
Could you reproduce the problem? |
I can run the test app. It would be good if it continuously submitted frames, as the deinterlace algorithm uses three frames of input to produce an output frame, so I'm not sure it can work with a single frame of input. |
We extended the test-app with commit ba61b08 to feed 3 buffers into the filter. This lets it return one buffer (FillBufferDone is called once and we dump the output to /tmp/output.yuv). |
I just pushed a little change, with which the sample program renders 5 frames. So when the program finishes you will have the output of the 5th frame in /tmp/output.yuv and can view it with |
Okay, I've spent a while on this. There were a couple of trivial things that were not initialised in the non-tunnelled case which stopped the input buffer being processed. rpi-update to get that fix. However the fixes had no effect on your test code, so I've been debugging that.
should start from 0. With these fixes, I now get a plausible output buffer. |
Thanks for your work. This is definitely a step forward, as we get a picture out now. But it still does not seem to be deinterlaced. Is there some additional enable command that would be required? As the single-frame sample does not really allow to see whether deinterlacing works we also tested with other filters like Blur or ColourSwap. None of these filters does actually seem to affect the output picture. The second issue we see is about timestamps. As the DeInterlace filter doubles the framerate I would assume that it interpolates timestamps for the added frames? Putting in frames with pts-delta of 40ms (25fps) I would expect the outcoming frames to have a pts-delta of 20ms (25fps). But we see mostly values around 40ms, like 39, 38, 41, etc. Is this intended? Would we have to take care of interpolating the correct timestamps? |
@dennishamester deinterlace component estimates frame_interval from (IIR) average of difference of consecutive timestamps. |
@julianscheel Are you expecting TFF/BFF flags to be constant or varying with each frame? |
@popcornmix
Where nParams[0] would be OMX_CONFIG_INTERLACETYPE.eMode, which we set to 3 for top field first interleaved. |
That would have worked a week ago.... In your non-tuneled case the missing frame flags are treated as "full frame" so deinterlace is skipped. |
Is it possible to set the per frame flag in non-tunnelled mode? That would be fine as well, as we have that information per frame. |
From my understanding of the code I think not (I'll find out). |
Hm, it seems it's not trying to load the omxil plugin at all. You have the |
My cmd: and |
Hm, the plugins seem to be all available.
Is it stalled at that point? Because that is the part where it should find and open the omx module. |
Are you running a raspbian image? I can try to setup a raspbian tomorrow and test/fix the binaries on it. I guess that will be easier than sorting it out via chat :) |
Yes I'm running raspbian. |
Alright, let me prepare this for you tomorrow morning. |
I just tested the vlc in the tarball on a clean raspbian and everything worked. I had to install ffmpeg and libdvbpsi. I also updated the firmware and set the gpu_mem to 128. |
@popcornmix |
Yes, I've got 256M gpu_mem, and that is when the paste stops. |
Ok, we will test with the next branch tomorrow. Besides the next firmware you run a stock raspbian? We could also provide a full sd card image if this helps? |
I develop from an nfs rootfs that started out as a clone of an older raspbian image. But as it has existed for many months, there is always a chance that something that has been installed is conflicting. I can install a new raspbian sdcard image and that may well let me run vlc. |
Ok, that sounds like a good chance that a fresh sd card image will work for you. Especially as a fresh image worked for us. After installing ffmpeg, libdvbpsi and running rpi-update. |
We're currently trying to use video_scheduler without a tunnel to video_renderer for debugging purposes. I'd like to see exactly when the scheduler outputs images. But I'm having problems setting this up properly. Even when the video_renderer is in state Executing, I get an ErrorIncorrectStateOperation when trying to call EmptyThisBuffer on it. |
You can get logging from openmax (http://www.raspberrypi.org/phpBB3/viewtopic.php?f=67&t=23185&p=232643#p232643) which almost certainly contains scheduled timestamps. |
Okay, I've had another look, and my problem was missing libdvbpsi (sudo apt-get install libdvbpsi-dev fixed it). Poking around, all the timestamps produced by image_fx component are zero, because EmptyThisBuffer seems to be called with pBuffer->nTimeStamp=0. Are you setting the timestamp on frames submitted? |
Thanks for helping, we just stumbled into the same. After fixing this, we finally saw fluid playback. Now we're onto our next problem.. the teardown in Close does not always work and leaks memory. Anyways, thanks again for your help. |
We changed our code to use tunnels between image_fx, video_scheduler, a clock and iv_renderer. Looking at the video_render lines, it seems the omxplayer uses 5 different buffers, but vlc uses only 3. Does this have anything to do with setting OMX_IndexParamBrcmExtraBuffers for the decoder? Do you see anything else in the vlc log that could cause a slight delay in the frame output? |
OMX_IndexParamBrcmExtraBuffers will cause extra buffers to be added to the decode pool. The parameters to that logging message are "free_slot, img, timestamp, flags". The free_slot==0 you are getting suggests only one frame is ever queued to be rendered, whereas omxplayer has a few frames queued to be rendered. That sounds like the problem. |
The OMX_IndexParamBrcmExtraBuffers does not make much sense in our use case, I think. As you say it only affects the decoder pool, but not the pool which is used in our tunnel. So now we are stumbling into the next issue. For 720p50 streams we need deinterlace to be disabled, as they are progressive already. Our first approach was setting OMX_InterlaceProgressive on the OMX_ImageFilterDeInterlaceAdvanced. This badly fails, because the Filter still seems to double frames, which makes 100fps output, which probably is just too much for the Pi. I see that in omxplayer you just unplug image_fx from the tunnel. Unfortunately this seems hardly possible for us, because we need to allocate the buffers for our picture pool on the first element in the tunnel, which is image_fx in deinterlace scenario and would be video_scheduler if no deinterlace is done. So we would have to teardown the tunnel and reallocate all buffers if a progressive/interlaced change occurs. This does not sound like a good approach after all. |
image_fx is a component that copies images (as the usual case is to have a non-none effect). Tearing down and creating a tunnel should only take a fraction of a second, so doing that whilst running seems like an option (omxplayer does this to audio pipeline when audio parameters like number of channels changes). |
We are following your advice and create image_fx only when it is necessary. But now we must operate the scheduler in non-tunneled mode (on the input side), which doesn't work as expected. All components transition to executing properly, but no images get output. In the debug log we see many lines like this: 115829.695: video_render:7:RIL:GetParameter(2000001) Is it possible to use the scheduler in non-tunneled mode? Are there any special parameters we need to set? Currently we only set the video format params. Edit: It seems images don't even reach the renderer. I can see: |
I added some more details to my last comment. |
Just recognized, that we haven't updated this issue lately. Actually image_fx with FilterNone works just fine for 720p channels. We just needed to reduce the virtual delay our scheduler clocks sees, to reduce the number of queued frames in the scheduler. When image_fx doubles frames we run with 160ms scheduling delay now, when it does not (ImageFilterNone) we use 80ms scheduling delay. |
See: raspberrypi#213 Userland: Rebuild with latest raspicam See: raspberrypi/userland#99
See: raspberrypi#213 userland: raspicam: Added a signal mode to allow initiation of captures from another process See: raspberrypi/userland#103 userland: raspicam: Refactored raspivid to allow user to pause and restart captures See: raspberrypi/userland#104
I think we can close this ticket. Things work as good as they probably can in non-tunneled omx mode as of now. |
See: raspberrypi#213 Userland: Rebuild with latest raspicam See: raspberrypi/userland#99
See: raspberrypi#213 userland: raspicam: Added a signal mode to allow initiation of captures from another process See: raspberrypi/userland#103 userland: raspicam: Refactored raspivid to allow user to pause and restart captures See: raspberrypi/userland#104
See: raspberrypi/firmware#213 userland: raspicam: Added a signal mode to allow initiation of captures from another process See: raspberrypi/userland#103 userland: raspicam: Refactored raspivid to allow user to pause and restart captures See: raspberrypi/userland#104 kernel: bump to 3.10.16
When the image_fx component is used in non-tunnelled mode, either with pre-allocated buffers through OMX_UseBuffer or with self-allocated ones through OMX_AllocateBuffer, it does not fire EmptyBufferDone events.
I made up a simple test-case, that can be found here: https://github.com/julianscheel/omx-test
It can be easily compiled on Raspberry or Cross-Compiled from any other system, without any dependencies but the rpi-firmware libs and headers.
There are three examples included:
Call the examples with the input file as parameter:
test-video_render works flawless, but test-image_fx simply never receives a EmptyBufferDone callback. In contrast to the image_fx documentation I have to set the full image parameters for the output port as well, otherwise it fails with a BadParameter error.
The overall target would be using image_fx as deinterlacing filter in VLC. The implementation we did there suffers the same behaviour as this sample code.
The text was updated successfully, but these errors were encountered: