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

copy_to produces an empty file when resolution is specified #302

Closed
ghunti opened this Issue Jul 6, 2016 · 14 comments

Comments

Projects
None yet
4 participants
@ghunti

ghunti commented Jul 6, 2016

Hi.
I'm having a strange issue with copy_to where I end up with an empty file in disk.
I've used the example provided in http://picamera.readthedocs.io/en/release-1.11/recipes1.html#recording-to-a-circular-stream but specified seconds=5 in the copy_to method and defined the camera resolution camera.resolution = (1920, 1080) and framerate camera.framerate = 30
With this setup the file written to disk is always empty.
If I comment the camera.resolution definition than everything seems to work again

I'm using picamera 1.11 with a raspberrypi 3 and camera v2

Thanks, and keep up the great job

@ghunti

This comment has been minimized.

ghunti commented Jul 7, 2016

Some updates on this.
Today I tested everything again, and I don't get the 0 byte file anymore (or at least not every time).
I did a bit of dig through picamera code, and assembled this test file (https://gist.github.com/ghunti/58372b01650916f539d133a96a35efe8)

What I'm seeing in my machine is that if I use 1080p resolution many of the frame timestamps are giant negative numbers.
This turns the last variable into a giant negative number because the first frames have this problem, so I end up with the full video length instead of a 5 second video.
Using other resolutions like 720p fixes all this, there are no more big negative timestamps and the file is 5 second long.

I'm not a python programmer, so apologies for any obvious mistake on my gist

@6by9

This comment has been minimized.

6by9 commented Jul 7, 2016

Is it always the same negative number?

@ghunti

This comment has been minimized.

ghunti commented Jul 7, 2016

Hi @6by9 indeed it is. It's -9223372036854775808. It seems that this is the maximum lower integer represented by python

@6by9

This comment has been minimized.

6by9 commented Jul 7, 2016

Thought it might have been
https://github.com/raspberrypi/userland/blob/master/interface/mmal/mmal_types.h#L88
#define MMAL_TIME_UNKNOWN (INT64_C(1)<<63) /**< Special value signalling that time is not known */
which when treated as a signed 64bit value comes back as -9223372036854775808.

Next question is why has it given up and got TIME_UNKNOWN, and that needs a bit more investigation.

@ghunti

This comment has been minimized.

ghunti commented Jul 7, 2016

Nice! Any ideia of anything I can debug?
Currently I'm using 720p so everything works ..

@6by9

This comment has been minimized.

6by9 commented Jul 7, 2016

Ah, "many of the frames are giant negative numbers". That makes sense.

The output port of the encoder has fixed size buffers allocated. If the encoded frame is bigger than that size it is split across multiple buffers. The first will have the correct timestamp and I'd expect MMAL_BUFFER_HEADER_FLAG_FRAME_START set in the flags field. All subsequent buffers will have the timestamp as TIME_UNKNOWN, and the last buffer of the encoded frame will have MMAL_BUFFER_HEADER_FLAG_FRAME_END set in the flags.
(The logic on the timestamps being that if it were something like unencoded audio, then the data does have a timestamp, but it is not the same as the first buffer in the frame, so better not to declare one. That then just rolls over to all formats).

The PiCamera buffer handling needs to be a bit smarter in this case, or increase the buffer size allocated (I believe at the moment it just takes buffer_size_recommended value, which is likely to be 80kB).

@6by9

This comment has been minimized.

6by9 commented Jul 7, 2016

https://github.com/waveform80/picamera/blob/master/picamera/mmalobj.py#L760
self._port[0].buffer_size = self._port[0].buffer_size_recommended
wants to be larger for >720P H264. Potentially for 720P too as there is no simple formula for the encoded frame size in H264. If things fall badly you can get >512kB for one frame!

Or you fix it in your handling. I'm really not a Python person, but the logic change wants to be along the lines of

        if frame.timestamp is not None and (frame.flags & MMAL_BUFFER_HEADER_FLAG_FRAME_START):
            print('Frame timestamp: {}'.format(frame.timestamp))
            if last is None:
                last = frame.timestamp
            elif last - frame.timestamp >= seconds:
                print('Elapsed: {}'.format(last - frame.timestamp))
                break
@ghunti

This comment has been minimized.

ghunti commented Jul 8, 2016

Thanks @6by9 I think there were a lot of useful findings in our comments, but I don't think there's much I can do right now, since my knowledge on all this is week :-p Let's see if someone more knowledgeable has some insight

@6by9

This comment has been minimized.

6by9 commented Jul 8, 2016

@waveform80 may help out, but this is a bug in your code in find_seconds.

You need to handle that timestamps will be MMAL_TIME_UNKNOWN on split frames, either by just ignoring frames with that timestamp, or by looking at the flags field and ignoring frames which haven't got the MMAL_BUFFER_HEADER_FLAG_FRAME_START bit set.

@ghunti

This comment has been minimized.

ghunti commented Jul 8, 2016

Yes, the bug is in find_seconds, but the _find_seconds is actually from this repository: https://github.com/waveform80/picamera/blob/master/picamera/streams.py#L690

I just copy+pasted so I could test on my own script ;)

@waveform80

This comment has been minimized.

Owner

waveform80 commented Jul 8, 2016

This does sound like a bug in both the buffer handling, and possibly copy_to as well (or more likely the PiVideoEncoder._callback_write method which handles re-writing things like MMAL_TIME_UNKNOWN to None ... or is meant to anyway). Unfortunately I'm rather busy for the next couple of weeks, so it'll take at least that long for me to get to - sorry!

@ghunti

This comment has been minimized.

ghunti commented Jul 8, 2016

Hi @waveform80 no problem, I understand! I would contribute, but I don't feel very comfortable with none of this.
Thanks for all the hard work you've put into the project.

@helmutka

This comment has been minimized.

helmutka commented Sep 28, 2016

This seems to be the same issue as #319.

@helmutka

This comment has been minimized.

helmutka commented Nov 27, 2016

Is there anything new with this issue?
I would like to use "copy_to" to get an accurate portion out of the ring buffer and not the complete buffer content. But with 1080p resolution it's not possible..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment