Hi, patch attached. Giliard wrote:
Dear developer,
Recently I added a extension in the FFmpeg for grab the screen content of devices which use framebuffer ( see http://www.directfb.org/ ). I implemented this as a framebuffer device demuxer in the directory "libavdevice". I needed modify the files: libavdevice/alldevices.c, libavdevice/Makefile and configure. All similar to x11grab.
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ? Thanks a lot. -- Baptiste COUDURIER GnuPG Key Id: 0x5C1ABAAA Key fingerprint 8D77134D20CC9220201FC5DB0AC9325C5C1ABAAA FFmpeg maintainer http://www.ffmpeg.org
On Sat, May 23, 2009 at 09:32:13AM -0300, Giliard wrote:
patch attached.
Please don't top-post. I could mention a lot of things, but they would just be a repetition of http://www.ffmpeg.org/general.html#SEC23 So please read that, make the necessary changes and resend your patch. Diego
On date Saturday 2009-05-23 09:32:13 -0300, Giliard encoded:
Hi,
patch attached.
Giliard wrote:
Dear developer,
Recently I added a extension in the FFmpeg for grab the screen content of devices which use framebuffer ( see http://www.directfb.org/ ). I implemented this as a framebuffer device demuxer in the directory "libavdevice". I needed modify the files: libavdevice/alldevices.c, libavdevice/Makefile and configure. All similar to x11grab.
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ?
Patch picked up and cleaned. BTW, I still can't find a sane way to use it, ffplay /dev/fb0 -f framebuffer only shows random stuff. Regards. -- FFmpeg = Fundamental and Frenzy Maxi Pitiful Ermetic Goblin
Hi, Stefano Sabatini wrote: [...]
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ?
Patch picked up and cleaned.
BTW, I still can't find a sane way to use it, ffplay /dev/fb0 -f framebuffer only shows random stuff.
I tried it, and ffmpeg -y -f framebuffer -r 25 -i /dev/fb0 test.avi almost works. By "almost" I mean that the video seems to be correctly captured, but the frame rate is wrong (I get 4fps). From a quick look at the patch, the code implementing the timing seems to be overly complex (and looks wrong - but I did not completely check). Anyway, this seems to be the cause for the wrong frame rate I obtain. Moreover, I believe that support for the NONBLOCK flag should be implemented before the patch is ready for svn. Finally, a warning: are your sure about the license? The code claims to be LGPL, but seems to be based on GPLed code. Luca
On date Monday 2010-02-22 12:10:59 +0100, Luca Abeni encoded:
Hi,
Stefano Sabatini wrote: [...]
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ?
Patch picked up and cleaned.
BTW, I still can't find a sane way to use it, ffplay /dev/fb0 -f framebuffer only shows random stuff.
I tried it, and ffmpeg -y -f framebuffer -r 25 -i /dev/fb0 test.avi almost works. By "almost" I mean that the video seems to be correctly captured, but the frame rate is wrong (I get 4fps).
From a quick look at the patch, the code implementing the timing seems to be overly complex (and looks wrong - but I did not completely check). Anyway, this seems to be the cause for the wrong frame rate I obtain. Moreover, I believe that support for the NONBLOCK flag should be implemented before the patch is ready for svn.
I vaguely remember the discussion about the NONBLOCK flag when the jackdev input was added, but no more than that. Can you provide some pointers to the discussion?
Finally, a warning: are your sure about the license? The code claims to be LGPL, but seems to be based on GPLed code.
fbgrab.c is GPLed, at a quick glance doesn't seem they're sharing a significant part of code, while the framebuffer_read_packet() code mostly comes from x11grab.c. Regards. -- FFmpeg = Fast and Faithful Meaningless Purposeless Embarassing Gadget
Stefano Sabatini wrote: [...] >> From a quick look at the patch, the code implementing >> the timing seems to be overly complex (and looks wrong >> - but I did not completely check). Anyway, this seems >> to be the cause for the wrong frame rate I obtain. >> Moreover, I believe that support for the NONBLOCK flag >> should be implemented before the patch is ready for svn. > > I vaguely remember the discussion about the NONBLOCK flag when the > jackdev input was added, but no more than that. Can you provide some > pointers to the discussion? I have no pointers to the discussion, but basically every input device should support the AVFMT_FLAG_NONBLOCK flag (yes, I know there are some input devices that do not support it, but this is because they are old input devices that have not been updated yet; new code should support AVFMT_FLAG_NONBLOCK). There was some discussion about supporting it for output devices, but I do not remember the conclusion. Anyway, for input devices, it is pretty simple: if AVFMT_FLAG_NONBLOCK is set, the input device should never block (but return AVERROR(EAGAIN) if no data is available). You can look at v4l2.c, alsa input, or vfwcap.c for examples. >> Finally, a warning: are your sure about the license? >> The code claims to be LGPL, but seems to be based on >> GPLed code. > > fbgrab.c is GPLed, at a quick glance doesn't seem they're sharing a > significant part of code, while the framebuffer_read_packet() code > mostly comes from x11grab.c. Exactly. The potential problem is that the comments say: * This file contains code from fbgrab.c: (which is release under GPL, as far as I can see) [...] * This file contains code from the x11grab.c: (which is GPLed too, I think). [...] * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. [...] * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software Which looks like a contraddiction (contains code from GPLed, but is released under LGPL). I did not check which part of the comment is wrong, but I think that something has to be fixed, there :) Luca
On date Monday 2010-02-22 13:18:27 +0100, Luca Abeni encoded: > Stefano Sabatini wrote: > [...] > >>From a quick look at the patch, the code implementing > >>the timing seems to be overly complex (and looks wrong > >>- but I did not completely check). Anyway, this seems > >>to be the cause for the wrong frame rate I obtain. > >>Moreover, I believe that support for the NONBLOCK flag > >>should be implemented before the patch is ready for svn. > > > >I vaguely remember the discussion about the NONBLOCK flag when the > >jackdev input was added, but no more than that. Can you provide some > >pointers to the discussion? > > I have no pointers to the discussion, but basically every input > device should support the AVFMT_FLAG_NONBLOCK flag (yes, I know > there are some input devices that do not support it, but this > is because they are old input devices that have not been updated > yet; new code should support AVFMT_FLAG_NONBLOCK). > There was some discussion about supporting it for output > devices, but I do not remember the conclusion. > Anyway, for input devices, it is pretty simple: if > AVFMT_FLAG_NONBLOCK is set, the input device should never block > (but return AVERROR(EAGAIN) if no data is available). > You can look at v4l2.c, alsa input, or vfwcap.c for examples. Thanks this clarifies. > >>Finally, a warning: are your sure about the license? > >>The code claims to be LGPL, but seems to be based on > >>GPLed code. > > > >fbgrab.c is GPLed, at a quick glance doesn't seem they're sharing a > >significant part of code, while the framebuffer_read_packet() code > >mostly comes from x11grab.c. > Exactly. The potential problem is that the comments say: > * This file contains code from fbgrab.c: > (which is release under GPL, as far as I can see) > [...] > * This file contains code from the x11grab.c: > (which is GPLed too, I think). > [...] > * FFmpeg is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > * License as published by the Free Software Foundation; either > * version 2.1 of the License, or (at your option) any later version. > [...] > * You should have received a copy of the GNU Lesser General Public > * License along with FFmpeg; if not, write to the Free Software > Which looks like a contraddiction (contains code from GPLed, but > is released under LGPL). > > I did not check which part of the comment is wrong, but I > think that something has to be fixed, there :) I removed the attributions which are IMO wrong, as I can't see much similarity between fbgrab.c and the new code. As for what regards x11grab.c, the part in read_header() which computes the timestamp looks just wrong or at least badly obfuscated, I'm trying to understand it in the meaningwhile if you have some insight on it please share :). BTW there is some particular reason for which both in v4l.c and v4l2.c we open the fd using O_RDWR, rather than just O_RDONLY? Patch attached is clearly yet missing the non-blocking/EAGAIN management. Regards. -- FFmpeg = Fundamental Free Merciful Pitiless Erotic Gnome
Hi, Stefano Sabatini wrote: [...]
* You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software Which looks like a contraddiction (contains code from GPLed, but is released under LGPL).
I did not check which part of the comment is wrong, but I think that something has to be fixed, there :)
I removed the attributions which are IMO wrong, as I can't see much similarity between fbgrab.c and the new code.
As for what regards x11grab.c, the part in read_header() which computes the timestamp looks just wrong or at least badly obfuscated, I'm trying to understand it in the meaningwhile if you have some insight on it please share :).
Looks like the timing code confused me, but it is correct (the only questionable part is the "if (delay < INT64_C(-1000000) * av_q2d(fb_ctx->time_base)) ..."). The framerate problem I was seeing is due to ffmpeg consuming 100% of the CPU in "memcpy(pkt->data, fb_ctx->data, fb_ctx->frame_size);" in frame_buffer_read_packet(). I do not know why this memcpy() is so slow... If I try ffmpeg -re -s 1280x1024 -y -r 25 -pix_fmt bgra -f rawvideo -i /dev/zero test.nut ffmpeg does not consume 100% of the CPU. And the input is Stream #0.0: Video: rawvideo, bgra, 1280x1024, 25 tbr, 25 tbn, 25 tbc If I try ffmpeg -y -r 25 -f framebuffer -i /dev/fb0 test.nut ffmpeg consumes 100% of the CPU in the memcpy() mentioned above, and the input is Stream #0.0: Video: rawvideo, bgra, 1280x1024, 1048576 kb/s, 25 tbr, 1000k tbn, 25 tbc So, I do not know where the overhead is coming from (the two commands mentioned above should do about the same thing...). I guess that implementing 0-copy input (as in v4l2.c) would be a possible solution to this problem.
BTW there is some particular reason for which both in v4l.c and v4l2.c we open the fd using O_RDWR, rather than just O_RDONLY? I do not know about v4l.c; for v4l2.c, this is just what the video4linux2 video capture example code did when I wrote the input. I suspect O_RDWR is required for performing some of the v4l2 ioctl()s.
Luca
On date Wednesday 2010-02-24 10:29:51 +0100, Luca Abeni encoded:
Hi,
Stefano Sabatini wrote: [...]
* You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software Which looks like a contraddiction (contains code from GPLed, but is released under LGPL).
I did not check which part of the comment is wrong, but I think that something has to be fixed, there :)
I removed the attributions which are IMO wrong, as I can't see much similarity between fbgrab.c and the new code.
As for what regards x11grab.c, the part in read_header() which computes the timestamp looks just wrong or at least badly obfuscated, I'm trying to understand it in the meaningwhile if you have some insight on it please share :).
Looks like the timing code confused me, but it is correct (the only questionable part is the "if (delay < INT64_C(-1000000) * av_q2d(fb_ctx->time_base)) ...").
The framerate problem I was seeing is due to ffmpeg consuming 100% of the CPU in "memcpy(pkt->data, fb_ctx->data, fb_ctx->frame_size);" in frame_buffer_read_packet(). I do not know why this memcpy() is so slow... If I try ffmpeg -re -s 1280x1024 -y -r 25 -pix_fmt bgra -f rawvideo -i /dev/zero test.nut ffmpeg does not consume 100% of the CPU. And the input is Stream #0.0: Video: rawvideo, bgra, 1280x1024, 25 tbr, 25 tbn, 25 tbc If I try ffmpeg -y -r 25 -f framebuffer -i /dev/fb0 test.nut ffmpeg consumes 100% of the CPU in the memcpy() mentioned above, and the input is Stream #0.0: Video: rawvideo, bgra, 1280x1024, 1048576 kb/s, 25 tbr, 1000k tbn, 25 tbc So, I do not know where the overhead is coming from (the two commands mentioned above should do about the same thing...).
I guess that implementing 0-copy input (as in v4l2.c) would be a possible solution to this problem.
BTW there is some particular reason for which both in v4l.c and v4l2.c we open the fd using O_RDWR, rather than just O_RDONLY? I do not know about v4l.c; for v4l2.c, this is just what the video4linux2 video capture example code did when I wrote the input. I suspect O_RDWR is required for performing some of the v4l2 ioctl()s.
Updated with many fixes, in particular the output packet was misaligned so the image resulted corrupted (weird that I hadn't the problem the last time I tried it...). Not yet for commit, I want to clean it up still a bit (and maybe add some more features), review is welcome of course. Regards. -- FFmpeg = Fanciful and Fundamentalist Mastodontic Puristic Elitarian Guru
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
Not yet for commit, I want to clean it up still a bit (and maybe add some more features), review is welcome of course.
--- a/configure +++ b/configure @@ -2850,6 +2851,7 @@ fi
check_header linux/videodev.h check_header linux/videodev2.h +check_header linux/fb.h check_header sys/videoio.h
alphabetical order
--- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -59,6 +59,16 @@ BSD video input device.
Linux DV 1394 input device.
+ at section framebuffer + +Linux frame buffer input device.
framebuffer
+For example, to record from the frame buffer device /dev/fb0 with
ditto
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
+#define DEBUG + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <time.h> +#include <linux/fb.h> +#include "libavutil/mem.h"
extra good karma for an empty line between local and system headers
+#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" +#define _LINUX_TIME_H 1
Where does this #define have an effect if you place it after #includes?
+av_cold static int frame_buffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + struct fb_var_screeninfo fb_varinfo; + + memset(&fb_varinfo, 0, sizeof(struct fb_var_screeninfo));
Is the nulling necessary? Simpler should be struct fb_var_screeninfo fb_varinfo = { 0 };
+ if (ioctl(fb_ctx->fd, FBIOGET_VSCREENINFO, &fb_varinfo) < 0){ + + if (ioctl(fb_ctx->fd, FBIOGET_FSCREENINFO, &fb_fixinfo) < 0){
) {
+ fb_ctx->frame_size = fb_varinfo.xres * fb_varinfo.yres * ((bits_per_pixel+7)>>3); + fb_ctx->linesize = fb_varinfo.xres * ((bits_per_pixel+7)>>3); + fb_ctx->frame_linesize = fb_fixinfo.line_length; + fb_ctx->time_base = ap->time_base; + fb_ctx->time_frame = av_gettime() / av_q2d(ap->time_base); /* timestamp in time_base unit */ + fb_ctx->data = mmap(NULL, fb_fixinfo.line_length * fb_varinfo.yres, PROT_READ, MAP_SHARED, fb_ctx->fd, 0);
Vertical alignment and spaces around operators could make this more readable.
+AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux Frame Buffer"),
framebuffer Diego
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
Not yet for commit, I want to clean it up still a bit (and maybe add some more features), review is welcome of course.
--- a/configure +++ b/configure @@ -2850,6 +2851,7 @@ fi
check_header linux/videodev.h check_header linux/videodev2.h +check_header linux/fb.h check_header sys/videoio.h
alphabetical order
--- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -59,6 +59,16 @@ BSD video input device.
Linux DV 1394 input device.
+ at section framebuffer + +Linux frame buffer input device.
framebuffer
+For example, to record from the frame buffer device /dev/fb0 with
ditto
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this. BTW fbgrab.c is bugged.
+#define DEBUG + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <time.h> +#include <linux/fb.h> +#include "libavutil/mem.h"
extra good karma for an empty line between local and system headers
+#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" +#define _LINUX_TIME_H 1
Where does this #define have an effect if you place it after #includes?
Looks useless, removed.
+av_cold static int frame_buffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + struct fb_var_screeninfo fb_varinfo; + + memset(&fb_varinfo, 0, sizeof(struct fb_var_screeninfo));
Is the nulling necessary? Simpler should be
Good catch, removed.
struct fb_var_screeninfo fb_varinfo = { 0 };
+ if (ioctl(fb_ctx->fd, FBIOGET_VSCREENINFO, &fb_varinfo) < 0){ + + if (ioctl(fb_ctx->fd, FBIOGET_FSCREENINFO, &fb_fixinfo) < 0){
) {
+ fb_ctx->frame_size = fb_varinfo.xres * fb_varinfo.yres * ((bits_per_pixel+7)>>3); + fb_ctx->linesize = fb_varinfo.xres * ((bits_per_pixel+7)>>3); + fb_ctx->frame_linesize = fb_fixinfo.line_length; + fb_ctx->time_base = ap->time_base; + fb_ctx->time_frame = av_gettime() / av_q2d(ap->time_base); /* timestamp in time_base unit */ + fb_ctx->data = mmap(NULL, fb_fixinfo.line_length * fb_varinfo.yres, PROT_READ, MAP_SHARED, fb_ctx->fd, 0);
Vertical alignment and spaces around operators could make this more readable.
+AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux Frame Buffer"),
framebuffer
All remaining nits fixed. Luca A., can you have a look at it? -- FFmpeg = Fierce Fiendish Mastodontic Prodigious Ecumenical Gadget
On date Wednesday 2011-01-26 23:18:38 +0100, Stefano Sabatini encoded:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
Not yet for commit, I want to clean it up still a bit (and maybe add some more features), review is welcome of course.
--- a/configure +++ b/configure @@ -2850,6 +2851,7 @@ fi
check_header linux/videodev.h check_header linux/videodev2.h +check_header linux/fb.h check_header sys/videoio.h
alphabetical order
--- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -59,6 +59,16 @@ BSD video input device.
Linux DV 1394 input device.
+ at section framebuffer + +Linux frame buffer input device.
framebuffer
+For example, to record from the frame buffer device /dev/fb0 with
ditto
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
BTW fbgrab.c is bugged.
+#define DEBUG + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <time.h> +#include <linux/fb.h> +#include "libavutil/mem.h"
extra good karma for an empty line between local and system headers
+#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" +#define _LINUX_TIME_H 1
Where does this #define have an effect if you place it after #includes?
Looks useless, removed.
+av_cold static int frame_buffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + struct fb_var_screeninfo fb_varinfo; + + memset(&fb_varinfo, 0, sizeof(struct fb_var_screeninfo));
Is the nulling necessary? Simpler should be
Good catch, removed.
struct fb_var_screeninfo fb_varinfo = { 0 };
+ if (ioctl(fb_ctx->fd, FBIOGET_VSCREENINFO, &fb_varinfo) < 0){ + + if (ioctl(fb_ctx->fd, FBIOGET_FSCREENINFO, &fb_fixinfo) < 0){
) {
+ fb_ctx->frame_size = fb_varinfo.xres * fb_varinfo.yres * ((bits_per_pixel+7)>>3); + fb_ctx->linesize = fb_varinfo.xres * ((bits_per_pixel+7)>>3); + fb_ctx->frame_linesize = fb_fixinfo.line_length; + fb_ctx->time_base = ap->time_base; + fb_ctx->time_frame = av_gettime() / av_q2d(ap->time_base); /* timestamp in time_base unit */ + fb_ctx->data = mmap(NULL, fb_fixinfo.line_length * fb_varinfo.yres, PROT_READ, MAP_SHARED, fb_ctx->fd, 0);
Vertical alignment and spaces around operators could make this more readable.
+AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux Frame Buffer"),
framebuffer
All remaining nits fixed.
Luca A., can you have a look at it? [...] + fb->data = mmap(NULL, fb_fixinfo.line_length * fb_varinfo.yres, + PROT_READ, MAP_SHARED, fb->fd, 0); + if (!fb->data) {
Autofix: if ((int)fb->data == -1) ... Updated. -- FFmpeg = Fast & Funny Meaningless Prodigious Elastic Geek
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,216 @@ + +/** + * Initialize the fb grab device demuxer (public device demuxer API). + */ +av_cold static int frame_buffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
nit: You could rename all those "frame_buffer_" functions to "framebuffer_".
+ fb->frame_linesize = fb_varinfo.xres * ((bits_per_pixel + 7)>>3);
nit: 7)>>3 ---> 7) >> 3 Diego
On date Wednesday 2011-01-26 23:56:05 +0100, Diego Biurrun encoded:
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
I believe the original contributor used the fbgrab.c code as template to see how to use the device, for example to see which ioctls to call and how to use them. Apart from that, there is not much more in common. Anyway I'll try to contact Gunnar and ask if he has problems with relicensing, hoping he's still around and fine. In the meaningwhile we can adopt gpl if you insist. [...] -- FFmpeg = Furious and Fostering Mystic Ponderous Erratic Gnome
On Thu, Jan 27, 2011 at 12:03:43AM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 23:56:05 +0100, Diego Biurrun encoded:
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
I believe the original contributor used the fbgrab.c code as template to see how to use the device, for example to see which ioctls to call and how to use them. Apart from that, there is not much more in common. Anyway I'll try to contact Gunnar and ask if he has problems with relicensing, hoping he's still around and fine.
In the meaningwhile we can adopt gpl if you insist.
I don't insist. In this case the relationship does indeed appear to be very far. But please reword your "based on" to "inspired by" or "some ideas from" or similar. Your wording gave me the wrong impression, it can give others a wrong impression as well. Diego
On date Thursday 2011-01-27 22:50:10 +0100, Diego Biurrun encoded:
On Thu, Jan 27, 2011 at 12:03:43AM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 23:56:05 +0100, Diego Biurrun encoded:
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
I believe the original contributor used the fbgrab.c code as template to see how to use the device, for example to see which ioctls to call and how to use them. Apart from that, there is not much more in common. Anyway I'll try to contact Gunnar and ask if he has problems with relicensing, hoping he's still around and fine.
In the meaningwhile we can adopt gpl if you insist.
I don't insist. In this case the relationship does indeed appear to be very far. But please reword your "based on" to "inspired by" or "some ideas from" or similar. Your wording gave me the wrong impression, it can give others a wrong impression as well.
Just received a mail from Gunnar, he's OK with the relicensing, the mail should be queued for moderation since he's not subscribed, Giliard still didn't reply. -- FFmpeg = Fancy Fanciful Magical Powerful Easy Guru
On date Thursday 2011-01-27 22:54:31 +0100, Stefano Sabatini encoded:
On date Thursday 2011-01-27 22:50:10 +0100, Diego Biurrun encoded:
On Thu, Jan 27, 2011 at 12:03:43AM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 23:56:05 +0100, Diego Biurrun encoded:
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote: > > --- /dev/null > +++ b/libavdevice/framebuffer.c > @@ -0,0 +1,220 @@ > + > +/** > + * @file > + * Linux Frame Buffer input device
framebuffer
> + * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
I believe the original contributor used the fbgrab.c code as template to see how to use the device, for example to see which ioctls to call and how to use them. Apart from that, there is not much more in common. Anyway I'll try to contact Gunnar and ask if he has problems with relicensing, hoping he's still around and fine.
In the meaningwhile we can adopt gpl if you insist.
I don't insist. In this case the relationship does indeed appear to be very far. But please reword your "based on" to "inspired by" or "some ideas from" or similar. Your wording gave me the wrong impression, it can give others a wrong impression as well.
Just received a mail from Gunnar, he's OK with the relicensing, the mail should be queued for moderation since he's not subscribed, Giliard still didn't reply.
s/based on/inspired by/. Thanks to Gunnar for replying. -- FFmpeg = Fundamental and Free Multimedia Pitiful Enlightening Gem
Sorry to chip in so late, but here are some comments on this, mostly minor. Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
From 9059a39f16131efc768d59784bd0179a2dfce69d Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <stefano.sabatini-lala at poste.it> Date: Tue, 25 Jan 2011 19:40:29 +0100 Subject: [PATCH] Add Linux framebuffer device.
Based on a patch by Giliard B. de Freitas /com/gmail/giliarde.
See thread: Subject: [FFmpeg-devel] Fwd: framebuffer device demuxer Date: Sat, 23 May 2009 09:32:13 -0300 --- Changelog | 1 + configure | 2 + doc/indevs.texi | 18 ++++ libavdevice/Makefile | 1 + libavdevice/alldevices.c | 1 + libavdevice/framebuffer.c | 216 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 239 insertions(+), 0 deletions(-) create mode 100644 libavdevice/framebuffer.c
diff --git a/Changelog b/Changelog index 8b7efb6..1c9166e 100644 --- a/Changelog +++ b/Changelog @@ -74,6 +74,7 @@ version <next>: - Lagarith decoder - ffmpeg -copytb option added - IVF muxer added +- Linux framebuffer input device added
version 0.6: diff --git a/configure b/configure index 001f00a..e75ad41 100755 --- a/configure +++ b/configure @@ -1387,6 +1387,7 @@ alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" alsa_outdev_deps="alsa_asoundlib_h" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" dv1394_indev_deps="dv1394 dv_demuxer" +framebuffer_indev_deps="linux_fb_h" jack_indev_deps="jack_jack_h" libdc1394_indev_deps="libdc1394" oss_indev_deps_any="soundcard_h sys_soundcard_h" @@ -2848,6 +2849,7 @@ if enabled network; then fi fi
+check_header linux/fb.h check_header linux/videodev.h check_header linux/videodev2.h check_header sys/videoio.h diff --git a/doc/indevs.texi b/doc/indevs.texi index 8e862ff..e9b1bea 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -59,6 +59,24 @@ BSD video input device.
Linux DV 1394 input device.
+ at section framebuffer + +Linux framebuffer input device. + +The name of the framebuffer device to read is a file device node, +usually @file{/dev/fb0}. + +For example, to record from the framebuffer device /dev/fb0 with + at file{ffmpeg}: + at example +ffmpeg -f framebuffer -r 10 -i /dev/fb0 out.avi + at end example + +You can take a single screenshot image with the command: + at example +ffmpeg -f framebuffer -vframes 1 -r 1 -i /dev/fb0 screenshot.jpeg + at end example + @section jack
JACK input device.
I think "framebuffer" is a bit too generic a name. After all, anything with a display of any kind has a framebuffer. The Linux framebuffer device generally goes by the name "fbdev", so perhaps that would be a better name.
diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 1c0630b..f5afeb2 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -14,6 +14,7 @@ OBJS-$(CONFIG_ALSA_OUTDEV) += alsa-audio-common.o \ alsa-audio-enc.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o +OBJS-$(CONFIG_FRAMEBUFFER_INDEV) += framebuffer.o OBJS-$(CONFIG_JACK_INDEV) += jack_audio.o OBJS-$(CONFIG_OSS_INDEV) += oss_audio.o OBJS-$(CONFIG_OSS_OUTDEV) += oss_audio.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index de3bc82..4e79467 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -42,6 +42,7 @@ void avdevice_register_all(void) REGISTER_INOUTDEV (ALSA, alsa); REGISTER_INDEV (BKTR, bktr); REGISTER_INDEV (DV1394, dv1394); + REGISTER_INDEV (FRAMEBUFFER, framebuffer); REGISTER_INDEV (JACK, jack); REGISTER_INOUTDEV (OSS, oss); REGISTER_INDEV (V4L2, v4l2); diff --git a/libavdevice/framebuffer.c b/libavdevice/framebuffer.c new file mode 100644 index 0000000..65ebe5c --- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2010 Stefano Sabatini + * Copyright (c) 2009 Giliard B. de Freitas <giliarde at gmail.com> + * Copyright (C) 2002 Gunnar Monell <gmo at linux.nu> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Linux framebuffer input device, + * inspired by code from fbgrab.c by Gunnar Monell. + */ + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <time.h> +#include <linux/fb.h> + +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" + +typedef struct { + int frame_size; ///< size in bytes of a grabbed frame + AVRational time_base; ///< time base + int64_t time_frame; ///< current time + + int frame_linesize; ///< linesize of the output frame + int linesize; ///< linesize of the read framebuffer + int height; ///< height of the grab frame + int width; ///< width of the grab frame + int fd; ///< framebuffer device file descriptor + + uint8_t *data; ///< image data +} FrameBufferContext; + +/** + * Initialize the framebuffer input device. + */ +av_cold static int framebuffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + FrameBufferContext *fb = avctx->priv_data; + struct fb_var_screeninfo fb_varinfo; + struct fb_fix_screeninfo fb_fixinfo; + AVStream *st = NULL; + enum PixelFormat pix_fmt; + int ret, bits_per_pixel, flags = O_RDONLY; + + if (!(st = av_new_stream(avctx, 0))) + return AVERROR(ENOMEM); + + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + flags |= O_NONBLOCK; + + if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s'.\n", avctx->filename); + goto fail;
You could return directly here and drop the check before close().
+ } + + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb_varinfo) < 0) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + goto fail; + } + + if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb_fixinfo) < 0) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + goto fail; + } + + if (ap->time_base.den <= 0) { + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Invalid time base %d/%d\n", ap->time_base.num, ap->time_base.den); + goto fail; + } + + av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in microseconds */ + + fb->width = fb_varinfo.xres; + fb->height = fb_varinfo.yres; + bits_per_pixel = fb_varinfo.bits_per_pixel; + + switch (bits_per_pixel) { + case 8: pix_fmt = PIX_FMT_PAL8 ; break; + case 15: pix_fmt = PIX_FMT_BGR555; break; + case 16: pix_fmt = PIX_FMT_RGB565; break; + case 24: pix_fmt = PIX_FMT_RGB24 ; break; + case 32: pix_fmt = PIX_FMT_RGB32 ; break; + default: + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Image with bits per pixel depth %d not supported.\n", + bits_per_pixel); + goto fail; + }
These are not the only formats possible. You cannot use bits per pixel exclusively to determine the format.
+ fb->frame_linesize = fb_varinfo.xres * ((bits_per_pixel + 7) >> 3); + fb->frame_size = fb->frame_linesize * fb_varinfo.yres; + fb->linesize = fb_fixinfo.line_length; + fb->time_base = ap->time_base; + fb->time_frame = av_gettime() / av_q2d(ap->time_base); + fb->data = mmap(NULL, fb_fixinfo.line_length * fb_varinfo.yres, + PROT_READ, MAP_SHARED, fb->fd, 0); + if (fb->data == MAP_FAILED) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Error in mmap(): %s\n", strerror(errno)); + goto fail; + } + + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = CODEC_ID_RAWVIDEO; + st->codec->width = fb->width; + st->codec->height = fb->height; + st->codec->pix_fmt = pix_fmt; + st->codec->time_base = ap->time_base; + st->codec->bit_rate = fb->frame_size / av_q2d(ap->time_base) * 8; + + av_log(avctx, AV_LOG_INFO, "w:%d h:%d bpp:%d pixfmt:%s tb:%d/%d bit_rate:%d\n", + fb->width, fb->height, bits_per_pixel, + av_pix_fmt_descriptors[pix_fmt].name, ap->time_base.num, ap->time_base.den, + st->codec->bit_rate); + return 0; + +fail: + if (fb->fd >= 0) + close(fb->fd); + return ret; +} + +/** + * Grab a frame from the frame buffer device. + * + * @param pkt packet holding the grabbed frame + * @return frame size in bytes + */ +static int framebuffer_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + FrameBufferContext *fb = avctx->priv_data; + int64_t curtime, delay; + struct timespec ts; + int i, ret; + uint8_t *pin, *pout; + + /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = curtime - fb->time_frame * av_q2d(fb->time_base); + if (delay >= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + }
Using e.g. sem_timedwait(), which takes an absolute timeout, might give better accuracy here, at least on the off-chance that the process is descheduled between the av_gettime() and nanosleep() calls.
+ if ((ret = av_new_packet(pkt, fb->frame_size)) < 0) + return ret; + + pkt->pts = curtime; + pin = fb->data; + pout = pkt->data; + for (i = 0; i < fb->height; i++) { + memcpy(pout, pin, fb->frame_linesize); + pin += fb->linesize; + pout += fb->frame_linesize; + } + + return fb->frame_size; +} + +/** + * Close framebuffer input device. + * + * @return a negative value in case of errors, 0 otherwise
This comment is a lie. The function always returns 0. Not that much could go wrong...
+ */ +av_cold static int framebuffer_read_close(AVFormatContext *avctx) +{ + FrameBufferContext *fb = avctx->priv_data; + + munmap(fb->data, fb->frame_size); + close(fb->fd); + + return 0; +} + +AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), + .priv_data_size = sizeof(FrameBufferContext), + .read_header = framebuffer_read_header, + .read_packet = framebuffer_read_packet, + .read_close = framebuffer_read_close, + .flags = AVFMT_NOFILE, +};
Is AVFMT_NOFILE really correct here? I'm not sure what its semantics are supposed to be. -- M?ns Rullg?rd mans at mansr.com
On date Friday 2011-01-28 01:10:46 +0000, M?ns Rullg?rd encoded:
Sorry to chip in so late, but here are some comments on this, mostly minor.
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
From 9059a39f16131efc768d59784bd0179a2dfce69d Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <stefano.sabatini-lala at poste.it> Date: Tue, 25 Jan 2011 19:40:29 +0100 Subject: [PATCH] Add Linux framebuffer device.
Based on a patch by Giliard B. de Freitas /com/gmail/giliarde.
See thread: Subject: [FFmpeg-devel] Fwd: framebuffer device demuxer Date: Sat, 23 May 2009 09:32:13 -0300 --- Changelog | 1 + configure | 2 + doc/indevs.texi | 18 ++++ libavdevice/Makefile | 1 + libavdevice/alldevices.c | 1 + libavdevice/framebuffer.c | 216 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 239 insertions(+), 0 deletions(-) create mode 100644 libavdevice/framebuffer.c [...] + at section framebuffer + +Linux framebuffer input device. + +The name of the framebuffer device to read is a file device node, +usually @file{/dev/fb0}. + +For example, to record from the framebuffer device /dev/fb0 with + at file{ffmpeg}: + at example +ffmpeg -f framebuffer -r 10 -i /dev/fb0 out.avi + at end example + +You can take a single screenshot image with the command: + at example +ffmpeg -f framebuffer -vframes 1 -r 1 -i /dev/fb0 screenshot.jpeg + at end example + @section jack
JACK input device.
I think "framebuffer" is a bit too generic a name. After all, anything with a display of any kind has a framebuffer. The Linux framebuffer device generally goes by the name "fbdev", so perhaps that would be a better name.
Replaced with linuxfb, this should be more explicative of the fact that it is a linux thing, this should prevent having users ask "I'm on windows, why can't I find the fbdev device?". [...]
+/** + * Initialize the framebuffer input device. + */ +av_cold static int framebuffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + FrameBufferContext *fb = avctx->priv_data; + struct fb_var_screeninfo fb_varinfo; + struct fb_fix_screeninfo fb_fixinfo; + AVStream *st = NULL; + enum PixelFormat pix_fmt; + int ret, bits_per_pixel, flags = O_RDONLY; + + if (!(st = av_new_stream(avctx, 0))) + return AVERROR(ENOMEM); + + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + flags |= O_NONBLOCK; + + if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s'.\n", avctx->filename); + goto fail;
You could return directly here and drop the check before close().
Done. [...]
+ fb->width = fb_varinfo.xres; + fb->height = fb_varinfo.yres; + bits_per_pixel = fb_varinfo.bits_per_pixel; + + switch (bits_per_pixel) { + case 8: pix_fmt = PIX_FMT_PAL8 ; break; + case 15: pix_fmt = PIX_FMT_BGR555; break; + case 16: pix_fmt = PIX_FMT_RGB565; break; + case 24: pix_fmt = PIX_FMT_RGB24 ; break; + case 32: pix_fmt = PIX_FMT_RGB32 ; break; + default: + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Image with bits per pixel depth %d not supported.\n", + bits_per_pixel); + goto fail; + }
These are not the only formats possible. You cannot use bits per pixel exclusively to determine the format.
Yes indeed. I'm using a far more robust solution now, yet incomplete, also I have to see how to handle pal formats. [...]
+static int framebuffer_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + FrameBufferContext *fb = avctx->priv_data; + int64_t curtime, delay; + struct timespec ts; + int i, ret; + uint8_t *pin, *pout; + + /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = curtime - fb->time_frame * av_q2d(fb->time_base); + if (delay >= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + }
Using e.g. sem_timedwait(), which takes an absolute timeout, might give better accuracy here, at least on the off-chance that the process is descheduled between the av_gettime() and nanosleep() calls.
I confess that I have not much experience with this, attaching this change as a second patch for easier review.
+ if ((ret = av_new_packet(pkt, fb->frame_size)) < 0) + return ret; + + pkt->pts = curtime; + pin = fb->data; + pout = pkt->data; + for (i = 0; i < fb->height; i++) { + memcpy(pout, pin, fb->frame_linesize); + pin += fb->linesize; + pout += fb->frame_linesize; + } + + return fb->frame_size; +} + +/** + * Close framebuffer input device. + * + * @return a negative value in case of errors, 0 otherwise
This comment is a lie. The function always returns 0. Not that much could go wrong...
I removed all the internal documentation, since it looked redundant (and internal documentation tends to get outdated very easily). [...]
+AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), + .priv_data_size = sizeof(FrameBufferContext), + .read_header = framebuffer_read_header, + .read_packet = framebuffer_read_packet, + .read_close = framebuffer_read_close, + .flags = AVFMT_NOFILE, +};
Is AVFMT_NOFILE really correct here? I'm not sure what its semantics are supposed to be.
It's not explained in the docs, but AVFMT_NOFILE is used for all the input and output device (possibly is what distinguishes a device from a muxer/demuxer). And I'm still observing the 100% CPU problem noted by Luca A. in this thread, a 0-memcpy solution is possible but it requires some change to the framework (as the written packet contains aligned data, which is not supported ATM). -- FFmpeg = Frenzy Fancy Minimal Powerful Extensive Generator
On date Friday 2011-01-28 15:36:03 +0100, Stefano Sabatini encoded: [...]
And I'm still observing the 100% CPU problem noted by Luca A. in this thread, a 0-memcpy solution is possible but it requires some change to the framework (as the written packet contains aligned data, which is not supported ATM).
In other words, which is the best way to pass linesize information to the rawvideo decoder? -- FFmpeg = Foolish & Frightening Mind-dumbing Pitiless Extended Guru
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
On date Friday 2011-01-28 01:10:46 +0000, M?ns Rullg?rd encoded:
I think "framebuffer" is a bit too generic a name. After all, anything with a display of any kind has a framebuffer. The Linux framebuffer device generally goes by the name "fbdev", so perhaps that would be a better name.
Replaced with linuxfb, this should be more explicative of the fact that it is a linux thing, this should prevent having users ask "I'm on windows, why can't I find the fbdev device?".
Works for me.
+ if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s'.\n", avctx->filename); + goto fail;
You could return directly here and drop the check before close().
Done.
Not exactly...
+ fb->width = fb_varinfo.xres; + fb->height = fb_varinfo.yres; + bits_per_pixel = fb_varinfo.bits_per_pixel; + + switch (bits_per_pixel) { + case 8: pix_fmt = PIX_FMT_PAL8 ; break; + case 15: pix_fmt = PIX_FMT_BGR555; break; + case 16: pix_fmt = PIX_FMT_RGB565; break; + case 24: pix_fmt = PIX_FMT_RGB24 ; break; + case 32: pix_fmt = PIX_FMT_RGB32 ; break; + default: + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Image with bits per pixel depth %d not supported.\n", + bits_per_pixel); + goto fail; + }
These are not the only formats possible. You cannot use bits per pixel exclusively to determine the format.
Yes indeed. I'm using a far more robust solution now, yet incomplete, also I have to see how to handle pal formats.
There is also the issue of driver-specific formats, but let's ignore those for now.
+AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), + .priv_data_size = sizeof(FrameBufferContext), + .read_header = framebuffer_read_header, + .read_packet = framebuffer_read_packet, + .read_close = framebuffer_read_close, + .flags = AVFMT_NOFILE, +};
Is AVFMT_NOFILE really correct here? I'm not sure what its semantics are supposed to be.
It's not explained in the docs, but AVFMT_NOFILE is used for all the input and output device (possibly is what distinguishes a device from a muxer/demuxer).
OK, that's a reasonable explanation. Perhaps it should be documented somewhere.
And I'm still observing the 100% CPU problem noted by Luca A. in this thread,
That needs to be resolved, obviously.
a 0-memcpy solution is possible but it requires some change to the framework (as the written packet contains aligned data, which is not supported ATM).
I don't think a zero-copy is a good idea here. The framebuffer is likely to be updated while encoding is in progress.
@@ -2863,6 +2864,33 @@ fi
texi2html -version > /dev/null 2>&1 && enable texi2html || disable texi2html
+if enabled network; then + check_type "sys/types.h sys/socket.h" socklen_t + check_type netdb.h "struct addrinfo" + check_type netinet/in.h "struct ipv6_mreq" -D_DARWIN_C_SOURCE + check_type netinet/in.h "struct sockaddr_in6" + check_type "sys/types.h sys/socket.h" "struct sockaddr_storage" + check_struct "sys/types.h sys/socket.h" "struct sockaddr" sa_len + # Prefer arpa/inet.h over winsock2 + if check_header arpa/inet.h ; then + check_func closesocket + elif check_header winsock2.h ; then + check_func_headers winsock2.h closesocket -lws2 && \ + network_extralibs="-lws2" || \ + { check_func_headers winsock2.h closesocket -lws2_32 && \ + network_extralibs="-lws2_32"; } + check_type ws2tcpip.h socklen_t + check_type ws2tcpip.h "struct addrinfo" + check_type ws2tcpip.h "struct ipv6_mreq" + check_type ws2tcpip.h "struct sockaddr_in6" + check_type ws2tcpip.h "struct sockaddr_storage" + check_struct winsock2.h "struct sockaddr" sa_len + else + disable network + fi +fi
Bad merge? This chunk was moved up a while ago.
+check_header linux/fb.h check_header linux/videodev.h check_header linux/videodev2.h check_header sys/videoio.h
[...]
diff --git a/libavdevice/linuxfb.c b/libavdevice/linuxfb.c new file mode 100644 index 0000000..e174edf --- /dev/null +++ b/libavdevice/linuxfb.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2010 Stefano Sabatini + * Copyright (c) 2009 Giliard B. de Freitas <giliarde at gmail.com> + * Copyright (C) 2002 Gunnar Monell <gmo at linux.nu> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Linux framebuffer input device, + * inspired by code from fbgrab.c by Gunnar Monell. + */ + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <time.h> +#include <linux/fb.h> + +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" + +struct rgb_pixfmt_map_entry { + int bits_per_pixel; + int red_offset, green_offset, blue_offset, alpha_offset; + enum PixelFormat pixfmt; +}; + +static struct rgb_pixfmt_map_entry rgb_pixfmt_map[] = { + // bpp, r_offset, g_offset, b_offset, a_offset, pixfmt + { 32, 0, 8, 16, 24, PIX_FMT_RGBA }, + { 32, 16, 8, 0, 24, PIX_FMT_BGRA }, + { 32, 8, 16, 24, 0, PIX_FMT_ARGB }, + { 32, 3, 2, 8, 0, PIX_FMT_ABGR }, + { 24, 0, 8, 16, 0, PIX_FMT_RGB24 }, + { 24, 16, 8, 0, 0, PIX_FMT_BGR24 }, +}; + +static enum PixelFormat get_pixfmt_from_fb_varinfo(struct fb_var_screeninfo varinfo)
Please change the argument to a pointer.
+{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(rgb_pixfmt_map); i++) { + struct rgb_pixfmt_map_entry entry = rgb_pixfmt_map[i];
Please use a pointer here.
+ if (entry.bits_per_pixel == varinfo.bits_per_pixel && + entry.red_offset == varinfo.red.offset && + entry.green_offset == varinfo.green.offset && + entry.blue_offset == varinfo.blue.offset) + return entry.pixfmt; + } + + return PIX_FMT_NONE; +} + +typedef struct { + int frame_size; ///< size in bytes of a grabbed frame + AVRational time_base; ///< time base + int64_t time_frame; ///< current time + + int frame_linesize; ///< linesize of the output frame + int linesize; ///< linesize of the read framebuffer + int height; ///< height of the grab frame + int width; ///< width of the grab frame + int fd; ///< framebuffer device file descriptor + + uint8_t *data; ///< framebuffer data + uint8_t *visible_data; ///< framebuffer visible data +} FrameBufferContext; + +av_cold static int linuxfb_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + FrameBufferContext *fb = avctx->priv_data; + struct fb_var_screeninfo fb_varinfo; + struct fb_fix_screeninfo fb_fixinfo; + AVStream *st = NULL; + enum PixelFormat pix_fmt; + int ret, bytes_per_pixel, flags = O_RDONLY; + + if (!(st = av_new_stream(avctx, 0))) + return AVERROR(ENOMEM); + + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + flags |= O_NONBLOCK; + + if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s': %s\n", + avctx->filename, strerror(ret)); + close(fb->fd);
Err... that should be "return ret", not close().
+ } + + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb_varinfo) < 0) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + goto fail; + } + + if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb_fixinfo) < 0) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + goto fail; + } + + if (ap->time_base.den <= 0) { + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Invalid time base %d/%d\n", ap->time_base.num, ap->time_base.den); + goto fail; + } + + av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in microseconds */ + + fb->width = fb_varinfo.xres; + fb->height = fb_varinfo.yres; + + pix_fmt = get_pixfmt_from_fb_varinfo(fb_varinfo); + if (pix_fmt == PIX_FMT_NONE) { + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Image with bits per pixel depth %d not supported.\n", + fb_varinfo.bits_per_pixel);
This error message doesn't quite match the error condition. I'd go with something like "Framebuffer pixel format not supported".
+ goto fail; + } + + bytes_per_pixel = (fb_varinfo.bits_per_pixel + 7) >> 3; + fb->frame_linesize = fb_varinfo.xres * bytes_per_pixel; + fb->frame_size = fb->frame_linesize * fb_varinfo.yres; + fb->linesize = fb_fixinfo.line_length; + fb->time_base = ap->time_base; + fb->time_frame = av_gettime() / av_q2d(ap->time_base);
Don't initialise time_frame to current time. There could be any delay between init and first capture. Set it to something invalid instead, and check it in read_packet().
+ fb->data = mmap(NULL, fb_fixinfo.line_length * (fb_varinfo.yres + fb_varinfo.yoffset), + PROT_READ, MAP_SHARED, fb->fd, 0); + fb->visible_data = fb->data + + (fb_varinfo.xoffset + fb_varinfo.xres_virtual * fb_varinfo.yoffset) * bytes_per_pixel;
This can change at any time if an application reconfigures the framebuffer. I'm not sure, but I think this also happens automatically when the text console scrolls.
+ if (fb->data == MAP_FAILED) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Error in mmap(): %s\n", strerror(errno)); + goto fail; + } + + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = CODEC_ID_RAWVIDEO; + st->codec->width = fb->width; + st->codec->height = fb->height; + st->codec->pix_fmt = pix_fmt; + st->codec->time_base = ap->time_base; + st->codec->bit_rate = fb->frame_size / av_q2d(ap->time_base) * 8; + + av_log(avctx, AV_LOG_INFO, "w:%d h:%d bpp:%d pixfmt:%s tb:%d/%d bit_rate:%d\n", + fb->width, fb->height, fb_varinfo.bits_per_pixel, + av_pix_fmt_descriptors[pix_fmt].name, ap->time_base.num, ap->time_base.den, + st->codec->bit_rate); + return 0; + +fail: + if (fb->fd >= 0) + close(fb->fd);
Fix the open() check above and remove this if().
+ return ret; +} + +static int linuxfb_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + FrameBufferContext *fb = avctx->priv_data; + int64_t curtime, delay; + struct timespec ts; + int i, ret; + uint8_t *pin, *pout; + + /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = curtime - fb->time_frame * av_q2d(fb->time_base); + if (delay >= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL);
This is asking for a negative delay. That's probably the cause of the CPU hogging.
+ } + + if ((ret = av_new_packet(pkt, fb->frame_size)) < 0) + return ret; + + pkt->pts = curtime; + pin = fb->visible_data; + pout = pkt->data; + + for (i = 0; i < fb->height; i++) { + memcpy(pout, pin, fb->frame_linesize); + pin += fb->linesize; + pout += fb->frame_linesize; + } + + return fb->frame_size; +} + +av_cold static int linuxfb_read_close(AVFormatContext *avctx) +{ + FrameBufferContext *fb = avctx->priv_data; + + munmap(fb->data, fb->frame_size); + close(fb->fd); + + return 0; +} + +AVInputFormat ff_linuxfb_demuxer = { + .name = "linuxfb", + .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), + .priv_data_size = sizeof(FrameBufferContext), + .read_header = linuxfb_read_header, + .read_packet = linuxfb_read_packet, + .read_close = linuxfb_read_close, + .flags = AVFMT_NOFILE, +}; -- 1.7.2.3
-- M?ns Rullg?rd mans at mansr.com
On date Friday 2011-01-28 16:32:38 +0000, M?ns Rullg?rd encoded:
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
On date Friday 2011-01-28 01:10:46 +0000, M?ns Rullg?rd encoded:
I think "framebuffer" is a bit too generic a name. After all, anything with a display of any kind has a framebuffer. The Linux framebuffer device generally goes by the name "fbdev", so perhaps that would be a better name.
Replaced with linuxfb, this should be more explicative of the fact that it is a linux thing, this should prevent having users ask "I'm on windows, why can't I find the fbdev device?".
Works for me.
+ if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s'.\n", avctx->filename); + goto fail;
You could return directly here and drop the check before close().
Done.
Not exactly...
+ fb->width = fb_varinfo.xres; + fb->height = fb_varinfo.yres; + bits_per_pixel = fb_varinfo.bits_per_pixel; + + switch (bits_per_pixel) { + case 8: pix_fmt = PIX_FMT_PAL8 ; break; + case 15: pix_fmt = PIX_FMT_BGR555; break; + case 16: pix_fmt = PIX_FMT_RGB565; break; + case 24: pix_fmt = PIX_FMT_RGB24 ; break; + case 32: pix_fmt = PIX_FMT_RGB32 ; break; + default: + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Image with bits per pixel depth %d not supported.\n", + bits_per_pixel); + goto fail; + }
These are not the only formats possible. You cannot use bits per pixel exclusively to determine the format.
Yes indeed. I'm using a far more robust solution now, yet incomplete, also I have to see how to handle pal formats.
There is also the issue of driver-specific formats, but let's ignore those for now.
I'm aware that the handling is not complete. I'll let to the other developers to decide if this should block commit (as for me I'd prefer to commit now and complete later).
+AVInputFormat framebuffer_demuxer = { + .name = "framebuffer", + .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), + .priv_data_size = sizeof(FrameBufferContext), + .read_header = framebuffer_read_header, + .read_packet = framebuffer_read_packet, + .read_close = framebuffer_read_close, + .flags = AVFMT_NOFILE, +};
Is AVFMT_NOFILE really correct here? I'm not sure what its semantics are supposed to be.
It's not explained in the docs, but AVFMT_NOFILE is used for all the input and output device (possibly is what distinguishes a device from a muxer/demuxer).
OK, that's a reasonable explanation. Perhaps it should be documented somewhere.
And I'm still observing the 100% CPU problem noted by Luca A. in this thread,
That needs to be resolved, obviously.
a 0-memcpy solution is possible but it requires some change to the framework (as the written packet contains aligned data, which is not supported ATM).
I don't think a zero-copy is a good idea here. The framebuffer is likely to be updated while encoding is in progress.
Yes.
@@ -2863,6 +2864,33 @@ fi
texi2html -version > /dev/null 2>&1 && enable texi2html || disable texi2html
+if enabled network; then + check_type "sys/types.h sys/socket.h" socklen_t + check_type netdb.h "struct addrinfo" + check_type netinet/in.h "struct ipv6_mreq" -D_DARWIN_C_SOURCE + check_type netinet/in.h "struct sockaddr_in6" + check_type "sys/types.h sys/socket.h" "struct sockaddr_storage" + check_struct "sys/types.h sys/socket.h" "struct sockaddr" sa_len + # Prefer arpa/inet.h over winsock2 + if check_header arpa/inet.h ; then + check_func closesocket + elif check_header winsock2.h ; then + check_func_headers winsock2.h closesocket -lws2 && \ + network_extralibs="-lws2" || \ + { check_func_headers winsock2.h closesocket -lws2_32 && \ + network_extralibs="-lws2_32"; } + check_type ws2tcpip.h socklen_t + check_type ws2tcpip.h "struct addrinfo" + check_type ws2tcpip.h "struct ipv6_mreq" + check_type ws2tcpip.h "struct sockaddr_in6" + check_type ws2tcpip.h "struct sockaddr_storage" + check_struct winsock2.h "struct sockaddr" sa_len + else + disable network + fi +fi
Bad merge? This chunk was moved up a while ago.
Uh, yes after the last rebase. [...]
+av_cold static int linuxfb_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + FrameBufferContext *fb = avctx->priv_data; + struct fb_var_screeninfo fb_varinfo; + struct fb_fix_screeninfo fb_fixinfo; + AVStream *st = NULL; + enum PixelFormat pix_fmt; + int ret, bytes_per_pixel, flags = O_RDONLY; + + if (!(st = av_new_stream(avctx, 0))) + return AVERROR(ENOMEM); + + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + flags |= O_NONBLOCK; + + if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s': %s\n", + avctx->filename, strerror(ret)); + close(fb->fd);
Err... that should be "return ret", not close().
Doh!.. fixed. [...]
+ pix_fmt = get_pixfmt_from_fb_varinfo(fb_varinfo); + if (pix_fmt == PIX_FMT_NONE) { + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Image with bits per pixel depth %d not supported.\n", + fb_varinfo.bits_per_pixel);
This error message doesn't quite match the error condition. I'd go with something like "Framebuffer pixel format not supported".
Fixed, I forgot to update after the last change.
+ goto fail; + } + + bytes_per_pixel = (fb_varinfo.bits_per_pixel + 7) >> 3; + fb->frame_linesize = fb_varinfo.xres * bytes_per_pixel; + fb->frame_size = fb->frame_linesize * fb_varinfo.yres; + fb->linesize = fb_fixinfo.line_length; + fb->time_base = ap->time_base; + fb->time_frame = av_gettime() / av_q2d(ap->time_base);
Don't initialise time_frame to current time. There could be any delay between init and first capture. Set it to something invalid instead, and check it in read_packet().
Good idea.
+ fb->data = mmap(NULL, fb_fixinfo.line_length * (fb_varinfo.yres + fb_varinfo.yoffset), + PROT_READ, MAP_SHARED, fb->fd, 0); + fb->visible_data = fb->data + + (fb_varinfo.xoffset + fb_varinfo.xres_virtual * fb_varinfo.yoffset) * bytes_per_pixel;
This can change at any time if an application reconfigures the framebuffer. I'm not sure, but I think this also happens automatically when the text console scrolls.
Uhm OK, I start to understand the difference between fixinfo and varinfo. [...]
+static int linuxfb_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + FrameBufferContext *fb = avctx->priv_data; + int64_t curtime, delay; + struct timespec ts; + int i, ret; + uint8_t *pin, *pout; + + /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = curtime - fb->time_frame * av_q2d(fb->time_base); + if (delay >= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL);
This is asking for a negative delay. That's probably the cause of the CPU hogging.
There was a mess with the timestamps, now it should be fixed. As for the CPU usage, it doesn't depend at all from the timestamps or from the memcpy, simply seems that with big images ffplay/ffmpeg get much slower: [linuxfb @ 0xa40cdb0] w:1366 h:768 bpp:32 pixfmt:bgra tb:1/25 bit_rate:839270400 I replaced the framebuffer->pkt memcpy with a dummy->pkt memcpy getting the same values. Updated patch, not all the comments addressed (especially for the varinfo/fixinfo stuff) so not yet ready for commit. -- FFmpeg = Freak & Fantastic Monstrous Powered Elitarian God
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
Updated patch, not all the comments addressed (especially for the varinfo/fixinfo stuff) so not yet ready for commit.
I'll look at this later. -- M?ns Rullg?rd mans at mansr.com
On Fri, Jan 28, 2011 at 11:28:43PM +0100, Stefano Sabatini wrote:
Updated patch, not all the comments addressed (especially for the varinfo/fixinfo stuff) so not yet ready for commit.
--- a/configure +++ b/configure @@ -1395,6 +1395,7 @@ alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp" alsa_outdev_deps="alsa_asoundlib_h" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" dv1394_indev_deps="dv1394 dv_demuxer" +linuxfb_indev_deps="linux_fb_h" jack_indev_deps="jack_jack_h" libdc1394_indev_deps="libdc1394" oss_indev_deps_any="soundcard_h sys_soundcard_h"
order
--- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -112,6 +112,30 @@ For more information read:
IIDC1394 input device, based on libdc1394 and libraw1394.
+ at section linuxfb + +Linux framebuffer input device. + +The name of the framebuffer device to read is a file device node, +usually @file{/dev/fb0}.
This is a little too quick. IMO the first paragraph of such a description should serve to tell a completely clueless reader what this linuxfb thing is all about. Such a reader would not yet know from the first sentence that this linuxfb thing reads from file nodes.
+For more detailed information related to the Linux framebuffer device +read the file kernel/Documentation/fb/framebuffer.txt included in +Linux.
The "Documentation" directory resides at the top level of the Linux sources, not below "kernel".
--- /dev/null +++ b/libavdevice/linuxfb.c @@ -0,0 +1,240 @@ + +av_cold static int linuxfb_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
nit: Here and in other places some lines could easily be shortened.
+ /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = fb->time_frame - curtime; +#ifdef DEBUG + av_log(avctx, AV_LOG_DEBUG, + "time_frame:%"PRId64" curtime:%"PRId64" delay:%"PRId64"\n", + fb->time_frame, curtime, delay); +#endif
dprintf Diego
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
diff --git a/libavdevice/linuxfb.c b/libavdevice/linuxfb.c new file mode 100644 index 0000000..71fa653 --- /dev/null +++ b/libavdevice/linuxfb.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2010 Stefano Sabatini + * Copyright (c) 2009 Giliard B. de Freitas <giliarde at gmail.com> + * Copyright (C) 2002 Gunnar Monell <gmo at linux.nu> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Linux framebuffer input device, + * inspired by code from fbgrab.c by Gunnar Monell. + */ + +/* #define DEBUG */ + +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <time.h> +#include <linux/fb.h> + +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" + +struct rgb_pixfmt_map_entry { + int bits_per_pixel; + int red_offset, green_offset, blue_offset, alpha_offset; + enum PixelFormat pixfmt; +}; + +static struct rgb_pixfmt_map_entry rgb_pixfmt_map[] = { + // bpp, r_offset, g_offset, b_offset, a_offset, pixfmt + { 32, 0, 8, 16, 24, PIX_FMT_RGBA }, + { 32, 16, 8, 0, 24, PIX_FMT_BGRA }, + { 32, 8, 16, 24, 0, PIX_FMT_ARGB }, + { 32, 3, 2, 8, 0, PIX_FMT_ABGR }, + { 24, 0, 8, 16, 0, PIX_FMT_RGB24 }, + { 24, 16, 8, 0, 0, PIX_FMT_BGR24 }, +}; + +static enum PixelFormat get_pixfmt_from_fb_varinfo(struct fb_var_screeninfo *varinfo) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(rgb_pixfmt_map); i++) { + struct rgb_pixfmt_map_entry *entry = &rgb_pixfmt_map[i]; + if (entry->bits_per_pixel == varinfo->bits_per_pixel && + entry->red_offset == varinfo->red.offset && + entry->green_offset == varinfo->green.offset && + entry->blue_offset == varinfo->blue.offset) + return entry->pixfmt; + } + + return PIX_FMT_NONE; +} + +typedef struct { + int frame_size; ///< size in bytes of a grabbed frame + AVRational time_base; ///< time base + int64_t time_frame; ///< time for the next frame to output (in 1/1000000 units) + + int frame_linesize; ///< linesize of the output frame + int linesize; ///< linesize of the read framebuffer + int height; ///< height of the grab frame + int width; ///< width of the grab frame + int fd; ///< framebuffer device file descriptor + + uint8_t *data; ///< framebuffer data + uint8_t *visible_data; ///< framebuffer visible data +} FrameBufferContext; + +av_cold static int linuxfb_read_header(AVFormatContext *avctx, AVFormatParameters *ap) +{ + FrameBufferContext *fb = avctx->priv_data; + struct fb_var_screeninfo fb_varinfo; + struct fb_fix_screeninfo fb_fixinfo; + AVStream *st = NULL; + enum PixelFormat pix_fmt; + int ret, bytes_per_pixel, flags = O_RDONLY; + + if (!(st = av_new_stream(avctx, 0))) + return AVERROR(ENOMEM); + av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in microseconds */ + + if (ap->time_base.den <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid time base %d/%d\n", ap->time_base.num, ap->time_base.den); + return AVERROR(EINVAL); + } + + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + flags |= O_NONBLOCK;
Come to think of it, O_NONBLOCK doesn't make sense on fbdev. AFAICT it is ignored by the drivers.
+ if ((fb->fd = open(avctx->filename, flags)) == -1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Could not open framebuffer device '%s': %s\n", + avctx->filename, strerror(ret)); + return ret; + } + + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb_varinfo) < 0) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + goto fail; + } + + if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb_fixinfo) < 0) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + goto fail; + } + + fb->width = fb_varinfo.xres; + fb->height = fb_varinfo.yres; + + pix_fmt = get_pixfmt_from_fb_varinfo(&fb_varinfo); + if (pix_fmt == PIX_FMT_NONE) { + ret = AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format not supported.\n"); + goto fail; + } + + bytes_per_pixel = (fb_varinfo.bits_per_pixel + 7) >> 3; + fb->frame_linesize = fb_varinfo.xres * bytes_per_pixel; + fb->frame_size = fb->frame_linesize * fb_varinfo.yres; + fb->linesize = fb_fixinfo.line_length; + fb->time_base = ap->time_base; + fb->time_frame = AV_NOPTS_VALUE; + fb->data = mmap(NULL, fb_fixinfo.line_length * (fb_varinfo.yoffset + fb_varinfo.yres), + PROT_READ, MAP_SHARED, fb->fd, 0); + if (fb->data == MAP_FAILED) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Error in mmap(): %s\n", strerror(errno)); + goto fail; + } + + fb->visible_data = fb->data + + (fb_varinfo.xoffset + fb_fixinfo.line_length * fb_varinfo.yoffset) * bytes_per_pixel;
You should mmap the entire framebuffer memory (as and query the current display offset in read_packet(). Yes, I know you said it wasn't ready.
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = CODEC_ID_RAWVIDEO; + st->codec->width = fb->width; + st->codec->height = fb->height; + st->codec->pix_fmt = pix_fmt; + st->codec->time_base = ap->time_base; + st->codec->bit_rate = fb->frame_size / av_q2d(ap->time_base) * 8; + + av_log(avctx, AV_LOG_INFO, "w:%d h:%d bpp:%d pixfmt:%s tb:%d/%d bit_rate:%d\n", + fb->width, fb->height, fb_varinfo.bits_per_pixel, + av_pix_fmt_descriptors[pix_fmt].name, ap->time_base.num, ap->time_base.den, + st->codec->bit_rate); + return 0; + +fail: + close(fb->fd); + return ret; +} + +static int linuxfb_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + FrameBufferContext *fb = avctx->priv_data; + int64_t curtime, delay; + struct timespec ts; + int i, ret; + uint8_t *pin, *pout; + + if (fb->time_frame == AV_NOPTS_VALUE) + fb->time_frame = av_gettime(); + + /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = fb->time_frame - curtime; +#ifdef DEBUG + av_log(avctx, AV_LOG_DEBUG, + "time_frame:%"PRId64" curtime:%"PRId64" delay:%"PRId64"\n", + fb->time_frame, curtime, delay); +#endif
av_dlog()
+ if (delay <= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + }
This loop is weird. The correct way is something like this: ts = delay; /* details omitted */ while (nanosleep(&ts, &ts) && errno == EINTR);
+ if ((ret = av_new_packet(pkt, fb->frame_size)) < 0) + return ret; + + pkt->pts = curtime; + pin = fb->visible_data; + pout = pkt->data; + + for (i = 0; i < fb->height; i++) { + memcpy(pout, pin, fb->frame_linesize); + pin += fb->linesize; + pout += fb->frame_linesize; + } + + return fb->frame_size; +} + +av_cold static int linuxfb_read_close(AVFormatContext *avctx) +{ + FrameBufferContext *fb = avctx->priv_data; + + munmap(fb->data, fb->frame_size); + close(fb->fd); + + return 0; +} + +AVInputFormat ff_linuxfb_demuxer = { + .name = "linuxfb", + .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), + .priv_data_size = sizeof(FrameBufferContext), + .read_header = linuxfb_read_header, + .read_packet = linuxfb_read_packet, + .read_close = linuxfb_read_close, + .flags = AVFMT_NOFILE, +}; -- 1.7.2.3
-- M?ns Rullg?rd mans at mansr.com
Updated work in progress. On date Sunday 2011-01-30 16:36:38 +0000, M?ns Rullg?rd encoded:
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes: [...]
+ if (avctx->flags & AVFMT_FLAG_NONBLOCK) + flags |= O_NONBLOCK;
Come to think of it, O_NONBLOCK doesn't make sense on fbdev. AFAICT it is ignored by the drivers.
I suppose you checked the sources. Anyway I suppose it's safe to set it anyway. [...]
+ fb->data = mmap(NULL, fb_fixinfo.line_length * (fb_varinfo.yoffset + fb_varinfo.yres), + PROT_READ, MAP_SHARED, fb->fd, 0); + if (fb->data == MAP_FAILED) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Error in mmap(): %s\n", strerror(errno)); + goto fail; + } + + fb->visible_data = fb->data + + (fb_varinfo.xoffset + fb_fixinfo.line_length * fb_varinfo.yoffset) * bytes_per_pixel;
You should mmap the entire framebuffer memory (as and query the current display offset in read_packet(). Yes, I know you said it wasn't ready.
Done this way. Data is mapped with: fbdev->data = mmap(NULL, fbdev->fixinfo.smem_len, PROT_READ, MAP_SHARED, fbdev->fd, 0); and visible data position updated in read_packet. I'm supposing the resolution doesn't change while grabbing. On the other hand I can't really understand the meaning of fbdev->varinfo.xres_virtual against fixinfo.line_length (fbdev docs suck and the various implementations I checked are inconsistent). What I'm doing for computing the visible data: pin = fbdev->data + fbdev->bytes_per_pixel * (fbdev->varinfo.xoffset + fbdev->varinfo.yoffset * fbdev->varinfo.xres_virtual); which is possibly wrong. [...]
+static int linuxfb_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + FrameBufferContext *fb = avctx->priv_data; + int64_t curtime, delay; + struct timespec ts; + int i, ret; + uint8_t *pin, *pout; + + if (fb->time_frame == AV_NOPTS_VALUE) + fb->time_frame = av_gettime(); + + /* wait based on the frame rate */ + while (1) { + curtime = av_gettime(); + delay = fb->time_frame - curtime; +#ifdef DEBUG + av_log(avctx, AV_LOG_DEBUG, + "time_frame:%"PRId64" curtime:%"PRId64" delay:%"PRId64"\n", + fb->time_frame, curtime, delay); +#endif
av_dlog()
Fixed.
+ if (delay <= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + }
This loop is weird. The correct way is something like this:
ts = delay; /* details omitted */ while (nanosleep(&ts, &ts) && errno == EINTR);
I kept the same logic for now. Other minor fixes: name changed again, linuxfb -> fbdev (fbdev is the official name), some documentation update. -- FFmpeg = Frenzy and Faithless Moronic Portable Evil Geisha
On Thu, Feb 10, 2011 at 01:19:53PM +0100, Stefano Sabatini wrote:
Updated work in progress.
Docs and build system look fine.
--- /dev/null +++ b/libavdevice/fbdev.c @@ -0,0 +1,252 @@ +av_cold static int fbdev_read_header(AVFormatContext *avctx, + AVFormatParameters *ap)
nit: indent Diego
On date Thursday 2011-02-10 13:19:53 +0100, Stefano Sabatini encoded:
Updated work in progress.
On date Sunday 2011-01-30 16:36:38 +0000, M?ns Rullg?rd encoded: [...]
You should mmap the entire framebuffer memory (as and query the current display offset in read_packet(). Yes, I know you said it wasn't ready.
Done this way.
Data is mapped with: fbdev->data = mmap(NULL, fbdev->fixinfo.smem_len, PROT_READ, MAP_SHARED, fbdev->fd, 0);
and visible data position updated in read_packet.
I'm supposing the resolution doesn't change while grabbing.
On the other hand I can't really understand the meaning of fbdev->varinfo.xres_virtual against fixinfo.line_length (fbdev docs suck and the various implementations I checked are inconsistent).
What I'm doing for computing the visible data: pin = fbdev->data + fbdev->bytes_per_pixel * (fbdev->varinfo.xoffset + fbdev->varinfo.yoffset * fbdev->varinfo.xres_virtual);
which is possibly wrong.
This post clarified the thing a bit: http://old.nabble.com/Xorg-on-m68k-td15555517i20.html That is from what I can see: fixinfo.line_length = bytes_per_pixel * varinfo.xres_virtual + padding padding is usually 0 so usually it is: fixinfo.line_length = bytes_per_pixel * varinfo.xres_virtual but it's safer to use line_length [...]
+ if (delay <= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + }
This loop is weird. The correct way is something like this:
ts = delay; /* details omitted */ while (nanosleep(&ts, &ts) && errno == EINTR);
I kept the same logic for now.
Other minor fixes: name changed again, linuxfb -> fbdev (fbdev is the official name), some documentation update.
Updated (ready for commit from my point of view). -- FFmpeg = Faithful & Fundamental Magical Pitiless Earthshaking Gadget
On Mon, Mar 07, 2011 at 06:54:52PM +0100, Stefano Sabatini wrote:
On date Thursday 2011-02-10 13:19:53 +0100, Stefano Sabatini encoded:
Updated work in progress.
On date Sunday 2011-01-30 16:36:38 +0000, M?ns Rullg?rd encoded: [...]
You should mmap the entire framebuffer memory (as and query the current display offset in read_packet(). Yes, I know you said it wasn't ready.
Done this way.
Data is mapped with: fbdev->data = mmap(NULL, fbdev->fixinfo.smem_len, PROT_READ, MAP_SHARED, fbdev->fd, 0);
and visible data position updated in read_packet.
I'm supposing the resolution doesn't change while grabbing.
On the other hand I can't really understand the meaning of fbdev->varinfo.xres_virtual against fixinfo.line_length (fbdev docs suck and the various implementations I checked are inconsistent).
What I'm doing for computing the visible data: pin = fbdev->data + fbdev->bytes_per_pixel * (fbdev->varinfo.xoffset + fbdev->varinfo.yoffset * fbdev->varinfo.xres_virtual);
which is possibly wrong.
This post clarified the thing a bit: http://old.nabble.com/Xorg-on-m68k-td15555517i20.html
That is from what I can see: fixinfo.line_length = bytes_per_pixel * varinfo.xres_virtual + padding
padding is usually 0 so usually it is: fixinfo.line_length = bytes_per_pixel * varinfo.xres_virtual
but it's safer to use line_length
[...]
+ if (delay <= 0) { + fb->time_frame += INT64_C(1000000) * av_q2d(fb->time_base); + break; + } + if (avctx->flags & AVFMT_FLAG_NONBLOCK) + return AVERROR(EAGAIN); + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + nanosleep(&ts, NULL); + }
This loop is weird. The correct way is something like this:
ts = delay; /* details omitted */ while (nanosleep(&ts, &ts) && errno == EINTR);
I kept the same logic for now.
Other minor fixes: name changed again, linuxfb -> fbdev (fbdev is the official name), some documentation update.
Updated (ready for commit from my point of view).
ok here too, ill push it later if you dont. also you could add support for returning the buffer without memcpy and this will need some kind of thread support to work reliable [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Let us carefully observe those good qualities wherein our enemies excel us and endeavor to excel them, by avoiding what is faulty, and imitating what is excellent in them. -- Plutarch
Le septidi 17 vent?se, an CCXIX, Stefano Sabatini a ?crit?:
while (nanosleep(&ts, &ts) && errno == EINTR);
+ while (nanosleep(&ts, &ts) == EINTR);
I think you made a mistake while writing the loop: nanosleep does not return the error status directly but through errno. Regards, -- Nicolas George
On date Saturday 2011-03-12 14:15:49 +0100, Nicolas George encoded:
Le septidi 17 vent?se, an CCXIX, Stefano Sabatini a ?crit?:
while (nanosleep(&ts, &ts) && errno == EINTR);
+ while (nanosleep(&ts, &ts) == EINTR);
I think you made a mistake while writing the loop: nanosleep does not return the error status directly but through errno.
Check updated. -- FFmpeg = Fiendish & Furious Mortal Pacific Extroverse Gangster
On Sat, Mar 12, 2011 at 03:28:07PM +0100, Stefano Sabatini wrote:
On date Saturday 2011-03-12 14:15:49 +0100, Nicolas George encoded:
Le septidi 17 vent?se, an CCXIX, Stefano Sabatini a ?crit?:
while (nanosleep(&ts, &ts) && errno == EINTR);
+ while (nanosleep(&ts, &ts) == EINTR);
I think you made a mistake while writing the loop: nanosleep does not return the error status directly but through errno.
Check updated. -- FFmpeg = Fiendish & Furious Mortal Pacific Extroverse Gangster
fbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 9f283621b311df17db7cb89a584e4d0c8c17863d 0002-fbdev-fix-check-on-nanosleep-return-vale.patch From 70baeb2f456523812a4b1393fd04b836f69a7dc4 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <stefano.sabatini-lala at poste.it> Date: Sat, 12 Mar 2011 14:46:16 +0100 Subject: [PATCH] fbdev: fix check on nanosleep return vale
applied [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Many things microsoft did are stupid, but not doing something just because microsoft did it is even more stupid. If everything ms did were stupid they would be bankrupt already.
On date Wednesday 2011-01-26 23:56:05 +0100, Diego Biurrun encoded:
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,220 @@ + +/** + * @file + * Linux Frame Buffer input device
framebuffer
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
--- /dev/null +++ b/libavdevice/framebuffer.c @@ -0,0 +1,216 @@ + +/** + * Initialize the fb grab device demuxer (public device demuxer API). + */ +av_cold static int frame_buffer_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
nit: You could rename all those "frame_buffer_" functions to "framebuffer_".
+ fb->frame_linesize = fb_varinfo.xres * ((bits_per_pixel + 7)>>3);
nit: 7)>>3 ---> 7) >> 3
All nits fixed. -- FFmpeg = Frightening & Fanciful Maxi Perennial Elitist Goblin
Stefano Sabatini <stefano.sabatini-lala <at> poste.it> writes:
On date Wednesday 2011-01-26 23:56:05 +0100, Diego Biurrun encoded:
On Wed, Jan 26, 2011 at 11:18:38PM +0100, Stefano Sabatini wrote:
On date Wednesday 2011-01-26 10:55:56 +0100, Diego Biurrun encoded:
On Tue, Jan 25, 2011 at 11:47:35PM +0100, Stefano Sabatini wrote:
+ * Based on code from fbgrab.c by Gunnar Monell.
What license was that code?
GPL, I concluded that there is not enough code in common to impose the use of GPL, though I have no problem at re-licensing the file under GPL if someone insists on this.
Your "based on" wording suggests more than that. This is dangerous territory, which parts are based on what? If you want to be absolutely sure, you could ask Gunnar to allow you to use his code under LGPL.
I got the following polite request from Stefano Sabatini: "I'm an FFmpeg developer and I picked an old patch on ffmpeg-devel by Giliard, check this thread: http://thread.gmane.org/gmane.comp.video.ffmpeg.devel/91238 The patch implements an input device for the Linux framebuffer. The patch by Giliard was presumably based on the fbgrab.c code and was using the GPL license, as fbgrab.c itself. I ask you if you have problems at allowing the derivative code to be licensed as LGPL rather than GPL. We believe there is not much code in common, and we prefer to adopt LGPL in favor of GPL for simplifying the licensing conditions of use of FFmpeg. Please reply to me, or even better on ffmpeg-devel if that's not too demanding for you. Best regards, thanks so far for the contribution." My answer: I have no problem with you relicensing this code under LGPL. But I truly suggest that someone tries to readjust the settings for http://post.gmane.org, I tried to write this as a one-liner, but it just continued on complaining about the ratio new/old, so I had to write this as an essay. Anyways keep up the good work. /Gunnar Monell
On 05/23/2009 02:32 PM, Giliard wrote:
Hi,
patch attached.
Giliard wrote:
Dear developer,
Recently I added a extension in the FFmpeg for grab the screen content of devices which use framebuffer ( see http://www.directfb.org/ ). I implemented this as a framebuffer device demuxer in the directory "libavdevice". I needed modify the files: libavdevice/alldevices.c, libavdevice/Makefile and configure. All similar to x11grab.
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ?
Git-friendly patch attached so patchwork will catch it up. -Vitor
On Sun, Jan 23, 2011 at 04:34:26PM +0100, Vitor Sessak wrote:
Git-friendly patch attached so patchwork will catch it up.
--- a/configure +++ b/configure @@ -813,6 +814,7 @@ CONFIG_LIST=" static swscale_alpha x11grab + fbgrab zlib "
alphabetical order
@@ -1137,6 +1139,8 @@ vfwcap_demuxer_deps="capCreateCaptureWindow" vfwcap_demuxer_extralibs="-lvfw32" x11_grab_device_demuxer_deps="x11grab XShmCreateImage" x11_grab_device_demuxer_extralibs="-lX11 -lXext" +fb_grab_device_demuxer_deps="fbgrab" +fb_grab_device_demuxer_extralibs="-lz"
alphabetical order
--- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -19,6 +19,7 @@ OBJS-$(CONFIG_V4L2_DEMUXER) += v4l2.o OBJS-$(CONFIG_V4L_DEMUXER) += v4l.o OBJS-$(CONFIG_VFWCAP_DEMUXER) += vfwcap.o OBJS-$(CONFIG_X11_GRAB_DEVICE_DEMUXER) += x11grab.o +OBJS-$(CONFIG_FB_GRAB_DEVICE_DEMUXER) += fbgrab.o
alphabetical order
--- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -54,6 +54,7 @@ void avdevice_register_all(void) REGISTER_DEMUXER (V4L, v4l); REGISTER_DEMUXER (VFWCAP, vfwcap); REGISTER_DEMUXER (X11_GRAB_DEVICE, x11_grab_device); + REGISTER_DEMUXER (FB_GRAB_DEVICE, fb_grab_device);
alphabetical order
--- /dev/null +++ b/libavdevice/fbgrab.c @@ -0,0 +1,238 @@ +/* + * fbgrab - framebuffer video grab interface + * + * (C) Giliard B. de Freitas <giliarde at gmail.com> 2009 + * + * This file contains code from fbgrab.c: + * Copyright (C) 2002 Gunnar Monell <gmo at linux.nu> 2002 + * + * This file contains code from the x11grab.c: + * Copyright (C) 2006 Clemens Fruhwirth <clemens at endorphin.org> + * Edouard Gomez <ed.gomez at free.fr> + * + * fbgrab is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * fbgrab is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with fbgrab; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */
Hmm, GPL code. We'd need to decide what to do about this.
+/** + * @file fbgrab.c
Drop the filename.
On Sun, Jan 23, 2011 at 04:34:26PM +0100, Vitor Sessak wrote:
Git-friendly patch attached so patchwork will catch it up.
missing changelog and docs update, version bump Diego
On date Sunday 2011-01-23 16:34:26 +0100, Vitor Sessak encoded:
On 05/23/2009 02:32 PM, Giliard wrote:
Hi,
patch attached.
Giliard wrote:
Dear developer,
Recently I added a extension in the FFmpeg for grab the screen content of devices which use framebuffer ( see http://www.directfb.org/ ). I implemented this as a framebuffer device demuxer in the directory "libavdevice". I needed modify the files: libavdevice/alldevices.c, libavdevice/Makefile and configure. All similar to x11grab.
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ?
Git-friendly patch attached so patchwork will catch it up.
On the same thread (check gmane) you can see some patches from me based on this one. -- FFmpeg = Fostering & Freak Minimalistic Ponderous Ermetic Gadget
On Sun, Jan 23, 2011 at 09:08:30PM +0100, Stefano Sabatini wrote:
On date Sunday 2011-01-23 16:34:26 +0100, Vitor Sessak encoded:
On 05/23/2009 02:32 PM, Giliard wrote:
Hi,
patch attached.
Giliard wrote:
Dear developer,
Recently I added a extension in the FFmpeg for grab the screen content of devices which use framebuffer ( see http://www.directfb.org/ ). I implemented this as a framebuffer device demuxer in the directory "libavdevice". I needed modify the files: libavdevice/alldevices.c, libavdevice/Makefile and configure. All similar to x11grab.
If you has interest for included in the FFmpeg source code official, the attachment contain the files modified and implemented.
First, thanks a lot for your work. Would it be possible for you to send a patch ? (diff -wup) of your tree and send it attached in ffmpeg-devel mailing list ?
Git-friendly patch attached so patchwork will catch it up.
On the same thread (check gmane) you can see some patches from me based on this one.
Can someone post the latest patch, if what was posted is not the latest? [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB The greatest way to live with honor in this world is to be what we pretend to be. -- Socrates
participants (9)
-
diego@biurrun.de -
giliarde@gmail.com -
gmo@linux.nu -
lucabe72@email.it -
mans@mansr.com -
michaelni@gmx.at -
nicolas.george@normalesup.org -
stefano.sabatini-lala@poste.it -
vitor1001@gmail.com