Message ID | 20190317150553.GA13110@akuma.local |
---|---|
State | New |
Headers | show |
Alexander Strasser (12019-03-17): > I had found that when capturing video for some hours from > USB Camera-B4.09.24.1 (Manufacturer: OmniVision Technologies, Inc.), > sometimes when invoking the ioctl DQBUF, the returned buffer is not > filled with the size we expect for the raw video frame. Which seems like a kernel bug, does it not? > To avoid this, return AVERROR(EAGAIN) instead. Returning EAGAIN when not in non-blocking mode is invalid. FFERROR_REDO would be the correct code in that case. Regards,
On 2019-03-17 18:25 +0100, Nicolas George wrote: > Alexander Strasser (12019-03-17): > > I had found that when capturing video for some hours from > > USB Camera-B4.09.24.1 (Manufacturer: OmniVision Technologies, Inc.), > > sometimes when invoking the ioctl DQBUF, the returned buffer is not > > filled with the size we expect for the raw video frame. > > Which seems like a kernel bug, does it not? Seems like a kernel bug, yes. Probably driver specific. Though I am not 100% sure it is strictly a bug. Might be that this is the best a driver for a particular hardware can do. In any case at least 2 different and probably more devices exhibited the described behaviour, which was never a permanent failure. I suspect some drivers will always exhibit this behavior sometimes. That's why I think we should handle this particular case more graceful. > > To avoid this, return AVERROR(EAGAIN) instead. > > Returning EAGAIN when not in non-blocking mode is invalid. FFERROR_REDO > would be the correct code in that case. Maybe using EAGAIN wasn't a good choice :( Using FFERROR_REDO sounds promising. I will try that. I tested the EAGAIN version and it worked. I also tested returning a zero-sized packet, like in the case where V4L flags the data as corrupt, that worked too. See commit 28f20d2ff487aa589643d8f70eaf614b78839685 Do you think the zero-sized packet would be better than returning FFERROR_REDO? Thanks for your comments! Alexander
Alexander Strasser (12019-03-18): > I tested the EAGAIN version and it worked. I also tested returning a ffmpeg.c uses the non-blocking mode. > zero-sized packet, like in the case where V4L flags the data as corrupt, > that worked too. See commit 28f20d2ff487aa589643d8f70eaf614b78839685 > > Do you think the zero-sized packet would be better than returning > FFERROR_REDO? I think it depends on what happens exactly with that frame? What is the partial packet returned? Is there a timestamp? Etc. Regards,
Hi Nicolas! On 2019-03-18 00:24 +0100, Nicolas George wrote: > Alexander Strasser (12019-03-18): > > I tested the EAGAIN version and it worked. I also tested returning a > > ffmpeg.c uses the non-blocking mode. That would explain it. I now tested, the FFERROR_REDO approach, and I think it works fine. As I don't have it available anymore, I can't test with the device that gave me the errors. So I modified the code to create the error condition. Using FFERROR_REDO would work for blocking mode as well as non-blocking, right? It handles the error on a lower level inside the libs and doesn't bubble up to the lib user AFAICT. > > zero-sized packet, like in the case where V4L flags the data as corrupt, > > that worked too. See commit 28f20d2ff487aa589643d8f70eaf614b78839685 > > > > Do you think the zero-sized packet would be better than returning > > FFERROR_REDO? > > I think it depends on what happens exactly with that frame? What is the > partial packet returned? Is there a timestamp? Etc. As mentioned above I can't dump more data to get a clue. I guess the frame was just truncated and the timestamps were correct. As we wouldn't pass on frame data to the user anyway, I would actually prefer the FFERROR_REDO version. Alexander
On 2019-03-18 23:26 +0100, Alexander Strasser wrote: > On 2019-03-18 00:24 +0100, Nicolas George wrote: > > Alexander Strasser (12019-03-18): > > > I tested the EAGAIN version and it worked. I also tested returning a > > > > ffmpeg.c uses the non-blocking mode. > > That would explain it. I now tested, the FFERROR_REDO approach, > and I think it works fine. As I don't have it available anymore, > I can't test with the device that gave me the errors. So I modified > the code to create the error condition. > > Using FFERROR_REDO would work for blocking mode as well as non-blocking, > right? > > It handles the error on a lower level inside the libs and doesn't > bubble up to the lib user AFAICT. > > > > > zero-sized packet, like in the case where V4L flags the data as corrupt, > > > that worked too. See commit 28f20d2ff487aa589643d8f70eaf614b78839685 > > > > > > Do you think the zero-sized packet would be better than returning > > > FFERROR_REDO? > > > > I think it depends on what happens exactly with that frame? What is the > > partial packet returned? Is there a timestamp? Etc. > > As mentioned above I can't dump more data to get a clue. I guess > the frame was just truncated and the timestamps were correct. > > As we wouldn't pass on frame data to the user anyway, I would actually > prefer the FFERROR_REDO version. I sent a new patch changing the returned error code to FFERROR_REDO. This patch can be considered rejected. Alexander
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 1b9c6e7..894692e 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -542,7 +542,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) "Dequeued v4l2 buffer contains %d bytes, but %d were expected. Flags: 0x%08X.\n", buf.bytesused, s->frame_size, buf.flags); enqueue_buffer(s, &buf); - return AVERROR_INVALIDDATA; + return AVERROR(EAGAIN); } }