From 8695f5d8c99952a89f59b314c58a5e0bbd8a6e6e Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Fri, 31 Jan 2003 14:06:03 +0000 Subject: - MAX_PREVIEW_SIZE = 4096 - new fb driver with zero copy CVS patchset: 4058 CVS date: 2003/01/31 14:06:03 --- src/demuxers/demux_asf.c | 4 +- src/demuxers/demux_elem.c | 5 +- src/demuxers/demux_mpeg.c | 4 +- src/demuxers/demux_mpgaudio.c | 4 +- src/demuxers/demux_ogg.c | 4 +- src/demuxers/demux_real.c | 37 +- src/demuxers/demux_ts.c | 4 +- src/input/input_gnome_vfs.c | 6 +- src/input/input_http.c | 5 +- src/input/input_mms.c | 6 +- src/input/input_net.c | 7 +- src/input/input_plugin.h | 5 +- src/input/input_pnm.c | 2 +- src/input/input_rtsp.c | 2 +- src/input/input_stdin_fifo.c | 8 +- src/input/librtsp/rtsp_session.c | 12 +- src/input/librtsp/rtsp_session.h | 4 +- src/input/mms.c | 12 +- src/input/mms.h | 4 +- src/input/mmsh.c | 12 +- src/input/mmsh.h | 4 +- src/input/pnm.c | 12 +- src/input/pnm.h | 4 +- src/video_out/video_out_fb.c | 1144 +++++++++++++++++++++++--------------- 24 files changed, 783 insertions(+), 528 deletions(-) (limited to 'src') diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index c476d71a2..39c11def4 100644 --- a/src/demuxers/demux_asf.c +++ b/src/demuxers/demux_asf.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_asf.c,v 1.104 2003/01/30 22:31:21 f1rmb Exp $ + * $Id: demux_asf.c,v 1.105 2003/01/31 14:06:03 miguelfreitas Exp $ * * demultiplexer for asf streams * @@ -1590,7 +1590,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, input_plugin_t *input) { demux_asf_t *this; - uint8_t buf[DEFRAG_BUFSIZE]; + uint8_t buf[MAX_PREVIEW_SIZE+1]; int len; switch (stream->content_detection_method) { diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index 12e43f44b..71dc918c6 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_elem.c,v 1.67 2003/01/04 14:48:11 miguelfreitas Exp $ + * $Id: demux_elem.c,v 1.68 2003/01/31 14:06:06 miguelfreitas Exp $ * * demultiplexer for elementary mpeg streams * @@ -43,6 +43,7 @@ */ #define NUM_PREVIEW_BUFFERS 50 +#define SCRATCH_SIZE ((MAX_PREVIEW_SIZE>4096)?MAX_PREVIEW_SIZE:4096) typedef struct { @@ -60,7 +61,7 @@ typedef struct { int blocksize; int status; - uint8_t scratch[4096]; + uint8_t scratch[SCRATCH_SIZE]; char last_mrl[1024]; } demux_mpeg_elem_t ; diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index dea0f3eca..61b8d5c01 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpeg.c,v 1.105 2003/01/16 22:25:53 miguelfreitas Exp $ + * $Id: demux_mpeg.c,v 1.106 2003/01/31 14:06:08 miguelfreitas Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -891,7 +891,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_CONTENT: { - uint8_t buf[4096]; + uint8_t buf[MAX_PREVIEW_SIZE]; off_t mdat_atom_offset = -1; int64_t mdat_atom_size = -1; unsigned int fourcc_tag; diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 6b006b880..e8dc93c72 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpgaudio.c,v 1.90 2003/01/26 15:58:36 tmmm Exp $ + * $Id: demux_mpgaudio.c,v 1.91 2003/01/31 14:06:09 miguelfreitas Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -337,7 +337,7 @@ static int demux_mpgaudio_get_status (demux_plugin_t *this_gen) { static uint32_t demux_mpgaudio_read_head(input_plugin_t *input) { - uint8_t buf[4096]; + uint8_t buf[MAX_PREVIEW_SIZE]; uint32_t head=0; int bs = 0; diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 153b73c7c..ca1322ab7 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ogg.c,v 1.63 2003/01/26 23:48:47 tmattern Exp $ + * $Id: demux_ogg.c,v 1.64 2003/01/31 14:06:09 miguelfreitas Exp $ * * demultiplexer for ogg streams * @@ -945,7 +945,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, case METHOD_BY_CONTENT: { - uint8_t buf[4096]; + uint8_t buf[MAX_PREVIEW_SIZE]; if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index ecdc4d883..fe9863d87 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -28,7 +28,7 @@ * * Based on FFmpeg's libav/rm.c. * - * $Id: demux_real.c,v 1.39 2003/01/29 18:53:56 miguelfreitas Exp $ + * $Id: demux_real.c,v 1.40 2003/01/31 14:06:10 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -645,8 +645,7 @@ static int demux_real_parse_references( demux_real_t *this) { ; j--; buf[j]='\0'; - printf("demux_real: ref=%s\n", &buf[i]); - + uevent.type = XINE_EVENT_MRL_REFERENCE; uevent.stream = this->stream; uevent.data_length = strlen(&buf[i])+sizeof(xine_mrl_reference_data_t); @@ -1128,13 +1127,13 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str input_plugin_t *input = (input_plugin_t *) input_gen; demux_real_t *this; + uint8_t buf[MAX_PREVIEW_SIZE+1]; + int len; switch (stream->content_detection_method) { case METHOD_BY_CONTENT: { - uint8_t buf[4096], len; - if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { input->seek(input, 0, SEEK_SET); @@ -1214,28 +1213,24 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str /* discover stream type */ - { - uint8_t buf[4096], len; - - this->reference_mode = 0; - if ((len = input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { - - input->seek(input, 0, SEEK_SET); + this->reference_mode = 0; + if ((len = input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { - if ( (len = input->read(input, buf, 1024)) > 0) { - if (real_check_stream_type(buf,len) == 2) - this->reference_mode = 1; - } + input->seek(input, 0, SEEK_SET); - } else if ((len = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW))) { - + if ( (len = input->read(input, buf, 1024)) > 0) { if (real_check_stream_type(buf,len) == 2) this->reference_mode = 1; } - - if(this->reference_mode) - printf("demux_real: reference stream detected\n"); + + } else if ((len = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW))) { + + if (real_check_stream_type(buf,len) == 2) + this->reference_mode = 1; } + + if(this->reference_mode) + printf("demux_real: reference stream detected\n"); this->demux_plugin.send_headers = demux_real_send_headers; diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 4e31e1c2b..a529df41e 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ts.c,v 1.77 2003/01/26 15:56:21 tmmm Exp $ + * $Id: demux_ts.c,v 1.78 2003/01/31 14:06:10 miguelfreitas Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -1826,7 +1826,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, switch (stream->content_detection_method) { case METHOD_BY_CONTENT: { - uint8_t buf[4096]; + uint8_t buf[MAX_PREVIEW_SIZE]; int got_sample; int i, j; int try_again, ts_detected; diff --git a/src/input/input_gnome_vfs.c b/src/input/input_gnome_vfs.c index ff45b2d4e..c46b86222 100644 --- a/src/input/input_gnome_vfs.c +++ b/src/input/input_gnome_vfs.c @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: input_gnome_vfs.c,v 1.2 2003/01/13 20:10:23 hadess Exp $ + * $Id: input_gnome_vfs.c,v 1.3 2003/01/31 14:06:12 miguelfreitas Exp $ */ @@ -37,8 +37,6 @@ #define D(x...) g_message (x) #define LOG -#define PREVIEW_SIZE 16384 - typedef struct { input_class_t input_class; xine_t *xine; @@ -56,7 +54,7 @@ typedef struct { GnomeVFSHandle *sub; /* Preview */ - char preview[PREVIEW_SIZE]; + char preview[MAX_PREVIEW_SIZE]; off_t preview_size; off_t preview_pos; } gnomevfs_input_t; diff --git a/src/input/input_http.c b/src/input/input_http.c index 102dd5e96..9b21dde3d 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -45,7 +45,6 @@ #define LOG */ -#define PREVIEW_SIZE 2200 #define BUFSIZE 1024 #define DEFAULT_HTTP_PORT 80 @@ -82,7 +81,7 @@ typedef struct { char *proxyhost; int proxyport; - char preview[PREVIEW_SIZE]; + char preview[MAX_PREVIEW_SIZE]; off_t preview_size; off_t preview_pos; @@ -888,7 +887,7 @@ static input_plugin_t *open_plugin (input_class_t *cls_gen, xine_stream_t *strea */ this->preview_size = http_plugin_read (&this->input_plugin, this->preview, - PREVIEW_SIZE); + MAX_PREVIEW_SIZE); this->preview_pos = 0; this->curpos = 0; diff --git a/src/input/input_mms.c b/src/input/input_mms.c index d40a564ec..07aa09b2f 100644 --- a/src/input/input_mms.c +++ b/src/input/input_mms.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: input_mms.c,v 1.34 2003/01/18 17:19:45 tmattern Exp $ + * $Id: input_mms.c,v 1.35 2003/01/31 14:06:13 miguelfreitas Exp $ * * mms input plugin based on work from major mms */ @@ -290,10 +290,10 @@ static int mms_plugin_get_optional_data (input_plugin_t *this_gen, case INPUT_OPTIONAL_DATA_PREVIEW: switch (this->protocol) { case PROTOCOL_MMST: - return mms_peek_header (this->mms, data); + return mms_peek_header (this->mms, data, MAX_PREVIEW_SIZE); break; case PROTOCOL_MMSH: - return mmsh_peek_header (this->mmsh, data); + return mmsh_peek_header (this->mmsh, data, MAX_PREVIEW_SIZE); break; } break; diff --git a/src/input/input_net.c b/src/input/input_net.c index 7e37b625a..a6c72f0dc 100644 --- a/src/input/input_net.c +++ b/src/input/input_net.c @@ -20,7 +20,7 @@ * Read from a tcp network stream over a lan (put a tweaked mp1e encoder the * other end and you can watch tv anywhere in the house ..) * - * $Id: input_net.c,v 1.41 2002/12/27 16:47:11 miguelfreitas Exp $ + * $Id: input_net.c,v 1.42 2003/01/31 14:06:13 miguelfreitas Exp $ * * how to set up mp1e for use with this plugin: * @@ -75,7 +75,6 @@ */ #define NET_BS_LEN 2324 -#define PREVIEW_SIZE 2200 #define BUFSIZE 1024 typedef struct { @@ -86,7 +85,7 @@ typedef struct { int fh; char *mrl; - char preview[PREVIEW_SIZE]; + char preview[MAX_PREVIEW_SIZE]; off_t preview_size; off_t preview_pos; @@ -361,7 +360,7 @@ static input_plugin_t *net_plugin_open (input_class_t *cls_gen, xine_stream_t *s this->preview_pos = 0; this->preview_size = 0; - this->preview_size = read (this->fh, this->preview, PREVIEW_SIZE); + this->preview_size = read (this->fh, this->preview, MAX_PREVIEW_SIZE); this->preview_pos = 0; this->curpos = 0; diff --git a/src/input/input_plugin.h b/src/input/input_plugin.h index 2bd26461b..d66b97939 100644 --- a/src/input/input_plugin.h +++ b/src/input/input_plugin.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: input_plugin.h,v 1.43 2002/12/29 16:48:35 mroi Exp $ + * $Id: input_plugin.h,v 1.44 2003/01/31 14:06:15 miguelfreitas Exp $ */ #ifndef HAVE_INPUT_PLUGIN_H @@ -232,6 +232,8 @@ struct input_plugin_s { * they can handle the stream or not. the preview data must * be buffered and delivered again through subsequent * read() calls. + * caller must provide a buffer allocated with at least + * MAX_PREVIEW_SIZE bytes. */ #define INPUT_CAP_PREVIEW 0x00000040 @@ -256,6 +258,7 @@ struct input_plugin_s { #define INPUT_OPTIONAL_DATA_PREVIEW 7 #define MAX_MRL_ENTRIES 255 +#define MAX_PREVIEW_SIZE 4096 /* Types of mrls returned by get_dir() */ #define mrl_unknown (0 << 0) diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c index 3d75c0ac9..ce62a81d8 100644 --- a/src/input/input_pnm.c +++ b/src/input/input_pnm.c @@ -200,7 +200,7 @@ static int pnm_plugin_get_optional_data (input_plugin_t *this_gen, switch (data_type) { case INPUT_OPTIONAL_DATA_PREVIEW: - return pnm_peek_header(this->pnm, data); + return pnm_peek_header(this->pnm, data, MAX_PREVIEW_SIZE); break; } diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c index cf5ecab57..dff1aa851 100644 --- a/src/input/input_rtsp.c +++ b/src/input/input_rtsp.c @@ -205,7 +205,7 @@ static int rtsp_plugin_get_optional_data (input_plugin_t *this_gen, switch (data_type) { case INPUT_OPTIONAL_DATA_PREVIEW: - return rtsp_session_peek_header(this->rtsp, data); + return rtsp_session_peek_header(this->rtsp, data, MAX_PREVIEW_SIZE); break; } diff --git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c index d25aba0fe..21dca4bcc 100644 --- a/src/input/input_stdin_fifo.c +++ b/src/input/input_stdin_fifo.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: input_stdin_fifo.c,v 1.41 2003/01/17 17:50:20 mroi Exp $ + * $Id: input_stdin_fifo.c,v 1.42 2003/01/31 14:06:16 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -41,8 +41,6 @@ #define LOG */ -#define PREVIEW_SIZE 2200 - #define DEFAULT_LOW_WATER_MARK 1 #define DEFAULT_HIGH_WATER_MARK 5 @@ -55,7 +53,7 @@ typedef struct { char *mrl; off_t curpos; - char preview[PREVIEW_SIZE]; + char preview[MAX_PREVIEW_SIZE]; off_t preview_size; off_t preview_pos; @@ -337,7 +335,7 @@ static input_plugin_t *open_plugin (input_class_t *cls_gen, xine_stream_t *strea */ this->preview_size = stdin_plugin_read (&this->input_plugin, this->preview, - PREVIEW_SIZE); + MAX_PREVIEW_SIZE); this->preview_pos = 0; return &this->input_plugin; diff --git a/src/input/librtsp/rtsp_session.c b/src/input/librtsp/rtsp_session.c index 145cfe00d..a6d5ab1d6 100644 --- a/src/input/librtsp/rtsp_session.c +++ b/src/input/librtsp/rtsp_session.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: rtsp_session.c,v 1.7 2002/12/24 01:10:53 holstsn Exp $ + * $Id: rtsp_session.c,v 1.8 2003/01/31 14:06:17 miguelfreitas Exp $ * * high level interface to rtsp servers. */ @@ -168,10 +168,14 @@ int rtsp_session_read (rtsp_session_t *this, char *data, int len) { return len; } -int rtsp_session_peek_header(rtsp_session_t *this, char *buf) { +int rtsp_session_peek_header(rtsp_session_t *this, char *buf, int maxsize) { - memcpy(buf, this->header, this->header_len); - return this->header_len; + int len; + + len = (this->header_len < maxsize) ? this->header_len : maxsize; + + memcpy(buf, this->header, len); + return len; } void rtsp_session_end(rtsp_session_t *session) { diff --git a/src/input/librtsp/rtsp_session.h b/src/input/librtsp/rtsp_session.h index d3daa4286..c287118e3 100644 --- a/src/input/librtsp/rtsp_session.h +++ b/src/input/librtsp/rtsp_session.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: rtsp_session.h,v 1.3 2002/12/24 01:10:53 holstsn Exp $ + * $Id: rtsp_session.h,v 1.4 2003/01/31 14:06:18 miguelfreitas Exp $ * * high level interface to rtsp servers. */ @@ -31,7 +31,7 @@ rtsp_session_t *rtsp_session_start(char *mrl); int rtsp_session_read(rtsp_session_t *session, char *data, int len); -int rtsp_session_peek_header(rtsp_session_t *this, char *buf); +int rtsp_session_peek_header(rtsp_session_t *this, char *buf, int maxsize); void rtsp_session_end(rtsp_session_t *session); diff --git a/src/input/mms.c b/src/input/mms.c index 8afb68ac0..6b5545577 100644 --- a/src/input/mms.c +++ b/src/input/mms.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: mms.c,v 1.19 2003/01/25 15:00:07 tmattern Exp $ + * $Id: mms.c,v 1.20 2003/01/31 14:06:17 miguelfreitas Exp $ * * based on work from major mms * utility functions to handle communication with an mms server @@ -1133,10 +1133,14 @@ static int get_media_packet (mms_t *this) { return 1; } -int mms_peek_header (mms_t *this, char *data) { +int mms_peek_header (mms_t *this, char *data, int maxsize) { - memcpy (data, this->asf_header, this->asf_header_len); - return this->asf_header_len; + int len; + + len = (this->asf_header_len < maxsize) ? this->asf_header_len : maxsize; + + memcpy(data, this->asf_header, len); + return len; } int mms_read (mms_t *this, char *data, int len) { diff --git a/src/input/mms.h b/src/input/mms.h index 3bb3b2358..565b89b65 100644 --- a/src/input/mms.h +++ b/src/input/mms.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: mms.h,v 1.8 2002/12/13 08:56:53 f1rmb Exp $ + * $Id: mms.h,v 1.9 2003/01/31 14:06:17 miguelfreitas Exp $ * * libmms public header */ @@ -37,7 +37,7 @@ int mms_read (mms_t *this, char *data, int len); uint32_t mms_get_length (mms_t *this); void mms_close (mms_t *this); -int mms_peek_header (mms_t *this, char *data); +int mms_peek_header (mms_t *this, char *data, int maxsize); #endif diff --git a/src/input/mmsh.c b/src/input/mmsh.c index 1f909fd5c..db3a256c2 100644 --- a/src/input/mmsh.c +++ b/src/input/mmsh.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: mmsh.c,v 1.9 2003/01/25 15:00:10 tmattern Exp $ + * $Id: mmsh.c,v 1.10 2003/01/31 14:06:17 miguelfreitas Exp $ * * based on mms.c and specs from avifile * (http://avifile.sourceforge.net/asf-1.0.htm) @@ -1022,10 +1022,14 @@ static int get_media_packet (mmsh_t *this) { } } -int mmsh_peek_header (mmsh_t *this, char *data) { +int mmsh_peek_header (mmsh_t *this, char *data, int maxsize) { - memcpy (data, this->asf_header, this->asf_header_len); - return this->asf_header_len; + int len; + + len = (this->asf_header_len < maxsize) ? this->asf_header_len : maxsize; + + memcpy(data, this->asf_header, len); + return len; } int mmsh_read (mmsh_t *this, char *data, int len) { diff --git a/src/input/mmsh.h b/src/input/mmsh.h index 6005851a5..29ad2bf55 100644 --- a/src/input/mmsh.h +++ b/src/input/mmsh.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: mmsh.h,v 1.1 2003/01/13 01:11:57 tmattern Exp $ + * $Id: mmsh.h,v 1.2 2003/01/31 14:06:17 miguelfreitas Exp $ * * libmmsh public header */ @@ -37,6 +37,6 @@ int mmsh_read (mmsh_t *this, char *data, int len); uint32_t mmsh_get_length (mmsh_t *this); void mmsh_close (mmsh_t *this); -int mmsh_peek_header (mmsh_t *this, char *data); +int mmsh_peek_header (mmsh_t *this, char *data, int maxsize); #endif diff --git a/src/input/pnm.c b/src/input/pnm.c index eb1a1c47a..d0a9b0c9e 100644 --- a/src/input/pnm.c +++ b/src/input/pnm.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: pnm.c,v 1.10 2003/01/22 16:33:24 holstsn Exp $ + * $Id: pnm.c,v 1.11 2003/01/31 14:06:17 miguelfreitas Exp $ * * pnm protocol implementation * based upon code from joschka @@ -930,10 +930,14 @@ int pnm_read (pnm_t *this, char *data, int len) { return len; } -int pnm_peek_header (pnm_t *this, char *data) { +int pnm_peek_header (pnm_t *this, char *data, int maxsize) { - memcpy (data, this->header, this->header_len); - return this->header_len; + int len; + + len = (this->header_len < maxsize) ? this->header_len : maxsize; + + memcpy(data, this->header, len); + return len; } void pnm_close(pnm_t *p) { diff --git a/src/input/pnm.h b/src/input/pnm.h index a2fb68539..1d4c54698 100644 --- a/src/input/pnm.h +++ b/src/input/pnm.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: pnm.h,v 1.2 2002/12/12 22:08:15 holstsn Exp $ + * $Id: pnm.h,v 1.3 2003/01/31 14:06:17 miguelfreitas Exp $ * * pnm util functions header by joschka */ @@ -37,7 +37,7 @@ pnm_t* pnm_connect (const char *url); int pnm_read (pnm_t *this, char *data, int len); void pnm_close (pnm_t *this); -int pnm_peek_header (pnm_t *this, char *data); +int pnm_peek_header (pnm_t *this, char *data, int maxsize); #endif diff --git a/src/video_out/video_out_fb.c b/src/video_out/video_out_fb.c index d654da14c..8bbb2319e 100644 --- a/src/video_out/video_out_fb.c +++ b/src/video_out/video_out_fb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2002 the xine project + * Copyright (C) 2000-2002 the xine project and Fredrik Noring * * This file is part of xine, a free video player. * @@ -17,10 +17,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_fb.c,v 1.21 2002/12/21 12:56:49 miguelfreitas Exp $ + * $Id: video_out_fb.c,v 1.22 2003/01/31 14:06:18 miguelfreitas Exp $ * * video_out_fb.c, frame buffer xine driver by Miguel Freitas * + * Contributors: + * + * Fredrik Noring : Zero copy buffers and clean up. + * * based on xine's video_out_xshm.c... * ...based on mpeg2dec code from * Aaron Holtzman @@ -28,12 +32,17 @@ * ideas from ppmtofb - Display P?M graphics on framebuffer devices * by Geert Uytterhoeven and Chris Lawrence * - * note: you must use this driver with aaxine. xine-ui won't work because of - * the visual type (but this can be changed, see below) + * Note: Use this with fbxine. It may work with the regular xine too, + * provided the visual type is changed (see below). * * TODO: VT switching (configurable) */ +/* #define USE_X11_VISUAL */ + +#define RECOMMENDED_NUM_BUFFERS 5 +#define MAXIMUM_NUM_BUFFERS 25 + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -73,7 +82,8 @@ #define LOG -typedef struct fb_frame_s { +typedef struct fb_frame_s +{ vo_frame_t vo_frame; int format; @@ -83,25 +93,33 @@ typedef struct fb_frame_s { uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ - yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter for this frame */ uint8_t *rgb_dst; int yuv_stride; int stripe_height, stripe_inc; int bytes_per_line; - uint8_t *data; -} fb_frame_t; -typedef struct fb_driver_s { + uint8_t* video_mem; /* mmapped video memory */ + uint8_t* data; + int yoffset; + + struct fb_driver_s *this; +} fb_frame_t; +typedef struct fb_driver_s +{ vo_driver_t vo_driver; int fd; int mem_size; - uint8_t* video_mem; /* mmapped video memory */ + uint8_t* video_mem_base; /* mmapped video memory */ int depth, bpp, bytes_per_pixel; + int total_num_native_buffers; + int used_num_buffers; + int yuv2rgb_mode; int yuv2rgb_swap; int yuv2rgb_gamma; @@ -113,470 +131,623 @@ typedef struct fb_driver_s { /* size / aspect ratio calculations */ vo_scale_t sc; - int fb_linelength; + int fb_bytes_per_line; + fb_frame_t *cur_frame, *old_frame; + + struct fb_var_screeninfo fb_var; + struct fb_fix_screeninfo fb_fix; + + int use_zero_copy; } fb_driver_t; -typedef struct { +typedef struct +{ video_driver_class_t driver_class; - config_values_t *config; } fb_class_t; - -/* - * and now, the driver functions - */ - -static uint32_t fb_get_capabilities (vo_driver_t *this_gen) { - return VO_CAP_COPIES_IMAGE | VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_BRIGHTNESS; +static uint32_t fb_get_capabilities(vo_driver_t *this_gen) +{ + return VO_CAP_COPIES_IMAGE | + VO_CAP_YV12 | + VO_CAP_YUY2 | + VO_CAP_BRIGHTNESS; } -static void fb_frame_copy (vo_frame_t *vo_img, uint8_t **src) { - fb_frame_t *frame = (fb_frame_t *) vo_img ; +static void fb_frame_copy(vo_frame_t *vo_img, uint8_t **src) +{ + fb_frame_t *frame = (fb_frame_t *)vo_img ; vo_img->copy_called = 1; - - if (frame->format == XINE_IMGFMT_YV12) { - frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, + if(frame->format == XINE_IMGFMT_YV12) + frame->yuv2rgb->yuv2rgb_fun(frame->yuv2rgb, frame->rgb_dst, src[0], src[1], src[2]); - } else { - - frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, - src[0]); - - } - + else + frame->yuv2rgb->yuy22rgb_fun(frame->yuv2rgb, + frame->rgb_dst, src[0]); frame->rgb_dst += frame->stripe_inc; } -static void fb_frame_field (vo_frame_t *vo_img, int which_field) { - - fb_frame_t *frame = (fb_frame_t *) vo_img ; +static void fb_frame_field(vo_frame_t *vo_img, int which_field) +{ + fb_frame_t *frame = (fb_frame_t *)vo_img ; - switch (which_field) { + switch(which_field) + { case VO_TOP_FIELD: - frame->rgb_dst = (uint8_t *)frame->data; - frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line; + frame->rgb_dst = frame->data; + frame->stripe_inc = 2*frame->stripe_height * + frame->bytes_per_line; break; + case VO_BOTTOM_FIELD: - frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ; - frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line; + frame->rgb_dst = frame->data + + frame->bytes_per_line ; + frame->stripe_inc = 2*frame->stripe_height * + frame->bytes_per_line; break; + case VO_BOTH_FIELDS: - frame->rgb_dst = (uint8_t *)frame->data; + frame->rgb_dst = frame->data; break; } } -static void fb_frame_dispose (vo_frame_t *vo_img) { - - fb_frame_t *frame = (fb_frame_t *) vo_img ; +static void fb_frame_dispose(vo_frame_t *vo_img) +{ + fb_frame_t *frame = (fb_frame_t *)vo_img; - if (frame->data) { + if(!frame->this->use_zero_copy) free(frame->data); - } - - free (frame); + free(frame); } +static vo_frame_t *fb_alloc_frame(vo_driver_t *this_gen) +{ + fb_driver_t *this = (fb_driver_t *)this_gen; + fb_frame_t *frame; -static vo_frame_t *fb_alloc_frame (vo_driver_t *this_gen) { - fb_driver_t *this = (fb_driver_t *) this_gen; - fb_frame_t *frame ; + if(this->use_zero_copy && + this->total_num_native_buffers <= this->used_num_buffers) + return 0; - frame = (fb_frame_t *) malloc (sizeof (fb_frame_t)); - if (frame==NULL) { - printf ("fb_alloc_frame: out of memory\n"); - return NULL; + frame = (fb_frame_t *)malloc(sizeof(fb_frame_t)); + if(!frame) + { + fprintf(stderr, "fb_alloc_frame: Out of memory.\n"); + return 0; } - memset (frame, 0, sizeof(fb_frame_t)); - memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t)); + memset(frame, 0, sizeof(fb_frame_t)); + memcpy(&frame->sc, &this->sc, sizeof(vo_scale_t)); - pthread_mutex_init (&frame->vo_frame.mutex, NULL); - - /* - * supply required functions - */ + pthread_mutex_init(&frame->vo_frame.mutex, NULL); + /* supply required functions */ frame->vo_frame.copy = fb_frame_copy; frame->vo_frame.field = fb_frame_field; frame->vo_frame.dispose = fb_frame_dispose; frame->vo_frame.driver = this_gen; - /* - * colorspace converter for this frame - */ - - frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); + frame->this = this; - return (vo_frame_t *) frame; -} - + /* colorspace converter for this frame */ + frame->yuv2rgb = + this->yuv2rgb_factory->create_converter(this->yuv2rgb_factory); + + if(this->use_zero_copy) + { + frame->yoffset = this->used_num_buffers * this->fb_var.yres; + frame->video_mem = this->video_mem_base + + this->used_num_buffers * this->fb_var.yres * + this->fb_bytes_per_line; + + memset(frame->video_mem, 0, + this->fb_var.yres * this->fb_bytes_per_line); + } + else + frame->video_mem = this->video_mem_base; -static void fb_compute_ideal_size (fb_driver_t *this, fb_frame_t *frame) { + this->used_num_buffers++; - vo_scale_compute_ideal_size( &frame->sc ); + return (vo_frame_t *)frame; } -static void fb_compute_rgb_size (fb_driver_t *this, fb_frame_t *frame) { +static void fb_compute_ideal_size(fb_driver_t *this, fb_frame_t *frame) +{ + vo_scale_compute_ideal_size(&frame->sc); +} - vo_scale_compute_output_size( &frame->sc ); +static void fb_compute_rgb_size(fb_driver_t *this, fb_frame_t *frame) +{ + vo_scale_compute_output_size(&frame->sc); /* avoid problems in yuv2rgb */ - if (frame->sc.output_height < ((frame->sc.delivered_height + 15) >> 4)) - frame->sc.output_height = ((frame->sc.delivered_height + 15) >> 4); + if(frame->sc.output_height < (frame->sc.delivered_height+15) >> 4) + frame->sc.output_height = (frame->sc.delivered_height+15) >> 4; + if (frame->sc.output_width < 8) frame->sc.output_width = 8; - if (frame->sc.output_width & 1) /* yuv2rgb_mlib needs an even YUV2 width */ - frame->sc.output_width++; + /* yuv2rgb_mlib needs an even YUV2 width */ + if (frame->sc.output_width & 1) + frame->sc.output_width++; #ifdef LOG printf("video_out_fb: frame source %d x %d => screen output %d x %d%s\n", frame->sc.delivered_width, frame->sc.delivered_height, frame->sc.output_width, frame->sc.output_height, - ( frame->sc.delivered_width != frame->sc.output_width - || frame->sc.delivered_height != frame->sc.output_height - ? ", software scaling" - : "" ) - ); + (frame->sc.delivered_width != frame->sc.output_width || + frame->sc.delivered_height != frame->sc.output_height ? + ", software scaling" : "")); #endif } -static void fb_update_frame_format (vo_driver_t *this_gen, - vo_frame_t *frame_gen, - uint32_t width, uint32_t height, - int ratio_code, int format, int flags) { - - fb_driver_t *this = (fb_driver_t *) this_gen; - fb_frame_t *frame = (fb_frame_t *) frame_gen; - - flags &= VO_BOTH_FIELDS; - - /* find out if we need to adapt this frame */ - - if ((width != frame->sc.delivered_width) - || (height != frame->sc.delivered_height) - || (ratio_code != frame->sc.delivered_ratio_code) - || (flags != frame->flags) - || (format != frame->format) - || (this->sc.user_ratio != frame->sc.user_ratio)) { - -#ifdef LOG - printf ("video_out_fb: frame format (from decoder) has changed => adapt\n"); -#endif - - frame->sc.delivered_width = width; - frame->sc.delivered_height = height; - frame->sc.delivered_ratio_code = ratio_code; - frame->flags = flags; - frame->format = format; - frame->sc.user_ratio = this->sc.user_ratio; +static void setup_colorspace_converter(fb_frame_t *frame, int flags) +{ + switch(flags) + { + case VO_TOP_FIELD: + case VO_BOTTOM_FIELD: + frame->yuv2rgb-> + configure(frame->yuv2rgb, + frame->sc.delivered_width, + 16, + 2 * frame->vo_frame.pitches[0], + 2 * frame->vo_frame.pitches[1], + frame->sc.output_width, + frame->stripe_height, + frame->bytes_per_line * 2); + frame->yuv_stride = frame->bytes_per_line * 2; + break; - fb_compute_ideal_size (this, frame); - fb_compute_rgb_size (this, frame); + case VO_BOTH_FIELDS: + frame->yuv2rgb-> + configure(frame->yuv2rgb, + frame->sc.delivered_width, + 16, + frame->vo_frame.pitches[0], + frame->vo_frame.pitches[1], + frame->sc.output_width, + frame->stripe_height, + frame->bytes_per_line); + frame->yuv_stride = frame->bytes_per_line; + break; + } +} +static void reset_dest_pointers(fb_frame_t *frame, int flags) +{ + switch(flags) + { + case VO_TOP_FIELD: + frame->rgb_dst = frame->data; + frame->stripe_inc = 2 * frame->stripe_height * + frame->bytes_per_line; + break; - /* - printf ("video_out_fb: updating frame to %d x %d\n", - frame->output_width, frame->output_height); - */ + case VO_BOTTOM_FIELD: + frame->rgb_dst = frame->data + + frame->bytes_per_line ; + frame->stripe_inc = 2 * frame->stripe_height * + frame->bytes_per_line; + break; - /* - * (re-) allocate - */ + case VO_BOTH_FIELDS: + frame->rgb_dst = frame->data; + frame->stripe_inc = frame->stripe_height * + frame->bytes_per_line; + break; + } +} - if (frame->data) { - if( frame->chunk[0] ) { - free( frame->chunk[0] ); +static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, + uint32_t width, uint32_t height, int format) +{ + if(frame->chunk[0]) + { + free(frame->chunk[0]); frame->chunk[0] = NULL; - } - if( frame->chunk[1] ) { - free( frame->chunk[1] ); + } + if(frame->chunk[1]) + { + free(frame->chunk[1]); frame->chunk[1] = NULL; - } - if( frame->chunk[2] ) { - free( frame->chunk[2] ); + } + if(frame->chunk[2]) + { + free(frame->chunk[2]); frame->chunk[2] = NULL; - } + } - free (frame->data); - } - + if(this->use_zero_copy) + { + frame->data = frame->video_mem + + frame->sc.output_yoffset*this->fb_bytes_per_line+ + frame->sc.output_xoffset*this->bytes_per_pixel; + } + else + { + if(frame->data) + free(frame->data); + frame->data = xine_xmalloc(frame->sc.output_width * + frame->sc.output_height * + this->bytes_per_pixel); + } - frame->data = xine_xmalloc (frame->sc.output_width * frame->sc.output_height * - this->bytes_per_pixel ); - - if (format == XINE_IMGFMT_YV12) { + if(format == XINE_IMGFMT_YV12) + { frame->vo_frame.pitches[0] = 8*((width + 7) / 8); frame->vo_frame.pitches[1] = 8*((width + 15) / 16); frame->vo_frame.pitches[2] = 8*((width + 15) / 16); - frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, + + frame->vo_frame.base[0] = + xine_xmalloc_aligned(16, + frame->vo_frame.pitches[0] * + height, (void **)&frame->chunk[0]); - frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), + + frame->vo_frame.base[1] = + xine_xmalloc_aligned(16, + frame->vo_frame.pitches[1] * + ((height+1)/2), (void **)&frame->chunk[1]); - frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), + + frame->vo_frame.base[2] = + xine_xmalloc_aligned(16, + frame->vo_frame.pitches[2] * + ((height+1)/2), (void **)&frame->chunk[2]); - } else { - frame->vo_frame.pitches[0] = 8*((width + 3) / 4); - frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, + } + else + { + frame->vo_frame.pitches[0] = 8 * ((width + 3) / 4); + + frame->vo_frame.base[0] = + xine_xmalloc_aligned(16, + frame->vo_frame.pitches[0] * + height, (void **)&frame->chunk[0]); frame->chunk[1] = NULL; frame->chunk[2] = NULL; - } + } +} - frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height; - frame->bytes_per_line = frame->sc.output_width * this->bytes_per_pixel; +static void fb_update_frame_format(vo_driver_t *this_gen, + vo_frame_t *frame_gen, + uint32_t width, uint32_t height, + int ratio_code, int format, int flags) +{ + fb_driver_t *this = (fb_driver_t *)this_gen; + fb_frame_t *frame = (fb_frame_t *)frame_gen; - /* - * set up colorspace converter - */ + flags &= VO_BOTH_FIELDS; - switch (flags) { - case VO_TOP_FIELD: - case VO_BOTTOM_FIELD: - frame->yuv2rgb->configure (frame->yuv2rgb, - frame->sc.delivered_width, - 16, - 2*frame->vo_frame.pitches[0], - 2*frame->vo_frame.pitches[1], - frame->sc.output_width, - frame->stripe_height, - frame->bytes_per_line*2); - frame->yuv_stride = frame->bytes_per_line*2; - break; - case VO_BOTH_FIELDS: - frame->yuv2rgb->configure (frame->yuv2rgb, - frame->sc.delivered_width, - 16, - frame->vo_frame.pitches[0], - frame->vo_frame.pitches[1], - frame->sc.output_width, - frame->stripe_height, - frame->bytes_per_line); - frame->yuv_stride = frame->bytes_per_line; - break; - } - } + /* Find out if we need to adapt this frame. */ + if (width != frame->sc.delivered_width || + height != frame->sc.delivered_height || + ratio_code != frame->sc.delivered_ratio_code || + flags != frame->flags || + format != frame->format || + this->sc.user_ratio != frame->sc.user_ratio) + { +#ifdef LOG + printf("video_out_fb: frame format (from decoder) " + "has changed => adapt\n"); +#endif - /* - * reset dest pointers - */ + frame->sc.delivered_width = width; + frame->sc.delivered_height = height; + frame->sc.delivered_ratio_code = ratio_code; + frame->flags = flags; + frame->format = format; + frame->sc.user_ratio = this->sc.user_ratio; - if (frame->data) { - switch (flags) { - case VO_TOP_FIELD: - frame->rgb_dst = (uint8_t *)frame->data; - frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line; - break; - case VO_BOTTOM_FIELD: - frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ; - frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line; - break; - case VO_BOTH_FIELDS: - frame->rgb_dst = (uint8_t *)frame->data; - frame->stripe_inc = frame->stripe_height * frame->bytes_per_line; - break; - } + fb_compute_ideal_size(this, frame); + fb_compute_rgb_size(this, frame); + + frame_reallocate(this, frame, width, height, format); + + frame->stripe_height = 16 * frame->sc.output_height / + frame->sc.delivered_height; + if(this->use_zero_copy) + frame->bytes_per_line = this->fb_bytes_per_line; + else + frame->bytes_per_line = frame->sc.output_width * + this->bytes_per_pixel; + + setup_colorspace_converter(frame, flags); } + + reset_dest_pointers(frame, flags); } -static void fb_overlay_clut_yuv2rgb(fb_driver_t *this, vo_overlay_t *overlay, - fb_frame_t *frame) { +static void fb_overlay_clut_yuv2rgb(fb_driver_t *this, + vo_overlay_t *overlay, fb_frame_t *frame) +{ int i; - clut_t* clut = (clut_t*) overlay->color; - if (!overlay->rgb_clut) { - for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) { + clut_t* clut = (clut_t*)overlay->color; + + if(!overlay->rgb_clut) + { + for(i = 0; + i < sizeof(overlay->color)/sizeof(overlay->color[0]); + i++) + { *((uint32_t *)&clut[i]) = - frame->yuv2rgb->yuv2rgb_single_pixel_fun (frame->yuv2rgb, - clut[i].y, clut[i].cb, clut[i].cr); + frame->yuv2rgb-> + yuv2rgb_single_pixel_fun(frame->yuv2rgb, + clut[i].y, + clut[i].cb, + clut[i].cr); } overlay->rgb_clut++; } - if (!overlay->clip_rgb_clut) { + + if(!overlay->clip_rgb_clut) + { clut = (clut_t*) overlay->clip_color; - for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) { + + for(i = 0; + i < sizeof(overlay->color)/sizeof(overlay->color[0]); + i++) + { *((uint32_t *)&clut[i]) = - frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, - clut[i].y, clut[i].cb, clut[i].cr); + frame->yuv2rgb-> + yuv2rgb_single_pixel_fun(frame->yuv2rgb, + clut[i].y, + clut[i].cb, + clut[i].cr); } overlay->clip_rgb_clut++; } } -static void fb_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { - fb_driver_t *this = (fb_driver_t *) this_gen; - fb_frame_t *frame = (fb_frame_t *) frame_gen; +static void fb_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, + vo_overlay_t *overlay) +{ + fb_driver_t *this = (fb_driver_t *)this_gen; + fb_frame_t *frame = (fb_frame_t *)frame_gen; /* Alpha Blend here */ - if (overlay->rle) { - if( !overlay->rgb_clut || !overlay->clip_rgb_clut) + if(overlay->rle) + { + if(!overlay->rgb_clut || !overlay->clip_rgb_clut) fb_overlay_clut_yuv2rgb(this,overlay,frame); - switch(this->bpp) { + switch(this->bpp) + { case 16: - blend_rgb16( (uint8_t *)frame->data, overlay, - frame->sc.output_width, frame->sc.output_height, - frame->sc.delivered_width, frame->sc.delivered_height); + blend_rgb16(frame->data, + overlay, + frame->sc.output_width, + frame->sc.output_height, + frame->sc.delivered_width, + frame->sc.delivered_height); break; + case 24: - blend_rgb24( (uint8_t *)frame->data, overlay, - frame->sc.output_width, frame->sc.output_height, - frame->sc.delivered_width, frame->sc.delivered_height); + blend_rgb24(frame->data, + overlay, + frame->sc.output_width, + frame->sc.output_height, + frame->sc.delivered_width, + frame->sc.delivered_height); break; + case 32: - blend_rgb32( (uint8_t *)frame->data, overlay, - frame->sc.output_width, frame->sc.output_height, - frame->sc.delivered_width, frame->sc.delivered_height); - break; - default: - /* It should never get here */ + blend_rgb32(frame->data, + overlay, + frame->sc.output_width, + frame->sc.output_height, + frame->sc.delivered_width, + frame->sc.delivered_height); break; } } } -static int fb_redraw_needed (vo_driver_t *this_gen) { +static int fb_redraw_needed(vo_driver_t *this_gen) +{ return 0; } -static void fb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { - +static void fb_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) +{ fb_driver_t *this = (fb_driver_t *) this_gen; fb_frame_t *frame = (fb_frame_t *) frame_gen; - int y; uint8_t *dst, *src; + int y; - if ( (frame->sc.output_width != this->sc.output_width) - || (frame->sc.output_height != this->sc.output_height) ) { - + if(frame->sc.output_width != this->sc.output_width || + frame->sc.output_height != this->sc.output_height) + { this->sc.output_width = frame->sc.output_width; this->sc.output_height = frame->sc.output_height; - printf ("video_out_fb: gui size %d x %d, frame size %d x %d\n", + printf("video_out_fb: gui size %d x %d, frame size %d x %d\n", this->sc.gui_width, this->sc.gui_height, frame->sc.output_width, frame->sc.output_height); - memset(this->video_mem, 0, this->fb_linelength * this->sc.gui_height ); - + memset(frame->video_mem, 0, + this->fb_bytes_per_line * this->sc.gui_height); } - dst = this->video_mem + frame->sc.output_yoffset * this->fb_linelength + + if(this->use_zero_copy) + { + if(this->old_frame) + this->old_frame->vo_frame.displayed + (&this->old_frame->vo_frame); + this->old_frame = this->cur_frame; + this->cur_frame = frame; + + this->fb_var.yoffset = frame->yoffset; + if(ioctl(this->fd, FBIOPAN_DISPLAY, &this->fb_var) == -1) + perror("video_out_fb: ioctl FBIOPAN_DISPLAY failed"); + } + else + { + dst = frame->video_mem + + frame->sc.output_yoffset * this->fb_bytes_per_line + frame->sc.output_xoffset * this->bytes_per_pixel; - src = frame->data; + src = frame->data; - for( y = 0; y < frame->sc.output_height; y++ ) { - xine_fast_memcpy( dst, src, frame->bytes_per_line ); - src += frame->bytes_per_line; - dst += this->fb_linelength; - } + for(y = 0; y < frame->sc.output_height; y++) + { + xine_fast_memcpy(dst, src, frame->bytes_per_line); + src += frame->bytes_per_line; + dst += this->fb_bytes_per_line; + } - frame->vo_frame.displayed (&frame->vo_frame); + frame->vo_frame.displayed(&frame->vo_frame); + } } -static int fb_get_property (vo_driver_t *this_gen, int property) { +static int fb_get_property(vo_driver_t *this_gen, int property) +{ + fb_driver_t *this = (fb_driver_t *)this_gen; - fb_driver_t *this = (fb_driver_t *) this_gen; + switch(property) + { + case VO_PROP_ASPECT_RATIO: + return this->sc.user_ratio; - if ( property == VO_PROP_ASPECT_RATIO) { - return this->sc.user_ratio ; - } else if ( property == VO_PROP_BRIGHTNESS) { + case VO_PROP_BRIGHTNESS: return this->yuv2rgb_gamma; - } else { - printf ("video_out_fb: tried to get unsupported property %d\n", property); + + default: + printf("video_out_fb: tried to get unsupported " + "property %d\n", property); } return 0; } -static int fb_set_property (vo_driver_t *this_gen, - int property, int value) { - - fb_driver_t *this = (fb_driver_t *) this_gen; +static int fb_set_property(vo_driver_t *this_gen, int property, int value) +{ + fb_driver_t *this = (fb_driver_t *)this_gen; - if ( property == VO_PROP_ASPECT_RATIO) { - if (value>=NUM_ASPECT_RATIOS) + switch(property) + { + case VO_PROP_ASPECT_RATIO: + if(value>=NUM_ASPECT_RATIOS) value = ASPECT_AUTO; this->sc.user_ratio = value; printf("video_out_fb: aspect ratio changed to %s\n", vo_scale_aspect_ratio_name(value)); - } else if ( property == VO_PROP_BRIGHTNESS) { + break; + case VO_PROP_BRIGHTNESS: this->yuv2rgb_gamma = value; - this->yuv2rgb_factory->set_gamma (this->yuv2rgb_factory, value); - + this->yuv2rgb_factory-> + set_gamma(this->yuv2rgb_factory, value); printf("video_out_fb: gamma changed to %d\n",value); - } else { - printf ("video_out_fb: tried to set unsupported property %d\n", property); + break; + + default: + printf("video_out_fb: tried to set unsupported " + "property %d\n", property); } return value; } -static void fb_get_property_min_max (vo_driver_t *this_gen, - int property, int *min, int *max) { - +static void fb_get_property_min_max(vo_driver_t *this_gen, + int property, int *min, int *max) +{ /* fb_driver_t *this = (fb_driver_t *) this_gen; */ - if ( property == VO_PROP_BRIGHTNESS) { + + if(property == VO_PROP_BRIGHTNESS) + { *min = -100; *max = +100; - } else { + } + else + { *min = 0; *max = 0; } } - -static int fb_gui_data_exchange (vo_driver_t *this_gen, - int data_type, void *data) { - +static int fb_gui_data_exchange(vo_driver_t *this_gen, + int data_type, void *data) +{ return 0; } - -static void fb_dispose (vo_driver_t *this_gen) { - - fb_driver_t *this = (fb_driver_t *) this_gen; +static void fb_dispose(vo_driver_t *this_gen) +{ + fb_driver_t *this = (fb_driver_t *)this_gen; munmap(0, this->mem_size); - close(this->fd); } -static vo_driver_t *fb_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { +static int get_fb_var_screeninfo(int fd, struct fb_var_screeninfo *var) +{ + int i; - fb_class_t *class = (fb_class_t *) class_gen; - config_values_t *config = class->config; + if(ioctl(fd, FBIOGET_VSCREENINFO, var)) + { + perror("video_out_fb: ioctl FBIOGET_VSCREENINFO"); + return 0; + } - fb_driver_t *this; - int mode; - char *device_name; - static char devkey[] = "video.fb_device"; + var->xres_virtual = var->xres; + var->xoffset = 0; + var->yoffset = 0; + var->nonstd = 0; + var->vmode &= ~FB_VMODE_YWRAP; + + /* Maximize virtual yres to fit as many buffers as possible. */ + for(i = MAXIMUM_NUM_BUFFERS; i > 0; i--) + { + var->yres_virtual = i * var->yres; + if(ioctl(fd, FBIOPUT_VSCREENINFO, var) == -1) + continue; + break; + } - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; + /* Get proper value for maximized var->yres_virtual. */ + if(ioctl(fd, FBIOGET_VSCREENINFO, var) == -1) + { + perror("video_out_fb: ioctl FBIOGET_VSCREENINFO"); + return 0; + } - /* - * allocate plugin struct - */ + return 1; +} - this = malloc (sizeof (fb_driver_t)); +static int get_fb_fix_screeninfo(int fd, struct fb_fix_screeninfo *fix) +{ + if(ioctl(fd, FBIOGET_FSCREENINFO, fix)) + { + perror("video_out_fb: ioctl FBIOGET_FSCREENINFO"); + return 0; + } - if (!this) { - printf ("video_out_fb: malloc failed\n"); - return NULL; + if((fix->visual != FB_VISUAL_TRUECOLOR && + fix->visual != FB_VISUAL_DIRECTCOLOR) || + fix->type != FB_TYPE_PACKED_PIXELS) + { + fprintf(stderr, "video_out_fb: only packed truecolor/directcolor is supported (%d).\n" + " Check 'fbset -i' or try 'fbset -depth 16'.\n", + fix->visual); + return 0; } - memset (this, 0, sizeof(fb_driver_t)); + return 1; +} +static void register_callbacks(fb_driver_t *this) +{ this->vo_driver.get_capabilities = fb_get_capabilities; this->vo_driver.alloc_frame = fb_alloc_frame; this->vo_driver.update_frame_format = fb_update_frame_format; - this->vo_driver.overlay_begin = NULL; /* not used */ + this->vo_driver.overlay_begin = 0; /* not used */ this->vo_driver.overlay_blend = fb_overlay_blend; - this->vo_driver.overlay_end = NULL; /* not used */ + this->vo_driver.overlay_end = 0; /* not used */ this->vo_driver.display_frame = fb_display_frame; this->vo_driver.get_property = fb_get_property; this->vo_driver.set_property = fb_set_property; @@ -584,82 +755,116 @@ static vo_driver_t *fb_open_plugin (video_driver_class_t *class_gen, const void this->vo_driver.gui_data_exchange = fb_gui_data_exchange; this->vo_driver.dispose = fb_dispose; this->vo_driver.redraw_needed = fb_redraw_needed; +} - device_name = config->register_string (config, devkey, "", - _("framebuffer device"), NULL, 10, NULL, NULL); - - if( strlen(device_name) > 3 ) { - this->fd = open(device_name, O_RDWR); - } else { +static int open_fb_device(config_values_t *config) +{ + static char devkey[] = "video.fb_device"; /* Why static? */ + char *device_name; + int fd; + + device_name = config->register_string(config, devkey, "", + _("framebuffer device"), + NULL, 10, NULL, NULL); + if(strlen(device_name) > 3) + { + fd = open(device_name, O_RDWR); + } + else + { device_name = "/dev/fb1"; - this->fd = open(device_name, O_RDWR); + fd = open(device_name, O_RDWR); - if( this->fd < 0 ) { + if(fd < 0) + { device_name = "/dev/fb0"; - this->fd = open(device_name, O_RDWR); + fd = open(device_name, O_RDWR); } } - if( this->fd < 0) { - printf("video_out_fb: aborting. (unable to open device \"%s\")\n", device_name); - free(this); - return NULL; + if(fd < 0) + { + fprintf(stderr, "video_out_fb: Unable to open device \"%s\", aborting: %s\n", + device_name, strerror(errno)); + return -1; } - config->update_string (config, devkey, device_name); + config->update_string(config, devkey, device_name); - if (ioctl(this->fd, FBIOGET_VSCREENINFO, &var)) { - printf("video_out_fb: ioctl FBIOGET_VSCREENINFO: %s\n", - strerror(errno)); - free(this); - return NULL; - } + return fd; +} - var.xres_virtual = var.xres; - var.yres_virtual = var.yres; - var.xoffset = 0; - var.yoffset = 0; - var.nonstd = 0; - var.vmode &= ~FB_VMODE_YWRAP; +static int mode_visual(fb_driver_t *this, config_values_t *config, + struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix) +{ + switch(fix->visual) + { + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_DIRECTCOLOR: + switch(this->depth) + { + case 24: + if(this->bpp == 32) + { + if(!var->blue.offset) + return MODE_32_RGB; + return MODE_32_BGR; + } + if(!var->blue.offset) + return MODE_24_RGB; + return MODE_24_BGR; + + case 16: + if(!var->blue.offset) + return MODE_16_RGB; + return MODE_16_BGR; - if (ioctl(this->fd, FBIOPUT_VSCREENINFO, &var)) { - printf("video_out_fb: ioctl FBIOPUT_VSCREENINFO: %s\n", - strerror(errno)); - free(this); - return NULL; - } + case 15: + if(!var->blue.offset) + return MODE_15_RGB; + return MODE_15_BGR; - if (ioctl(this->fd, FBIOGET_FSCREENINFO, &fix)) { - printf("video_out_fb: ioctl FBIOGET_FSCREENINFO: %s\n", - strerror(errno)); - free(this); - return NULL; - } - - if( (fix.visual != FB_VISUAL_TRUECOLOR && fix.visual != FB_VISUAL_DIRECTCOLOR) || fix.type != FB_TYPE_PACKED_PIXELS ) { - printf("video_out_fb: only packed truecolor/directcolor is supported (%d).\n",fix.visual); - printf(" check 'fbset -i' or try 'fbset -depth 16'\n"); - free(this); - return NULL; + case 8: + if(!var->blue.offset) + return MODE_8_RGB; + return MODE_8_BGR; + + } } - if (fix.line_length) - this->fb_linelength = fix.line_length; - else - this->fb_linelength = (var.xres_virtual * var.bits_per_pixel) / 8; + fprintf(stderr, "video_out_fb: Your video mode was not recognized, sorry.\n"); + return 0; +} - vo_scale_init( &this->sc, 0, 0, config ); - this->sc.gui_width = var.xres; - this->sc.gui_height = var.yres; - this->sc.user_ratio = ASPECT_AUTO; - - this->sc.scaling_disabled = config->register_bool (config, "video.disable_scaling", 0, - _("disable all video scaling (faster!)"), - NULL, 10, NULL, NULL); +static int setup_yuv2rgb(fb_driver_t *this, config_values_t *config, + struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix) +{ + this->yuv2rgb_mode = mode_visual(this, config, var, fix); + if(!this->yuv2rgb_mode) + return 0; + + this->yuv2rgb_swap = 0; + this->yuv2rgb_gamma = + config->register_range(config, "video.fb_gamma", 0, + -100, 100, + "gamma correction for fb driver", + NULL, 0, NULL, NULL); + + this->yuv2rgb_factory = yuv2rgb_factory_init(this->yuv2rgb_mode, + this->yuv2rgb_swap, + this->yuv2rgb_cmap); + this->yuv2rgb_factory->set_gamma(this->yuv2rgb_factory, + this->yuv2rgb_gamma); + return 1; +} +static void setup_buffers(fb_driver_t *this, + struct fb_var_screeninfo *var) +{ /* - * * depth in X11 terminology land is the number of bits used to * actually represent the colour. * @@ -668,114 +873,144 @@ static vo_driver_t *fb_open_plugin (video_driver_class_t *class_gen, const void * * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit * color is 24 bit depth, but can be 24 bpp or 32 bpp. - */ - - /* fb assumptions: bpp % 8 = 0 (e.g. 8, 16, 24, 32 bpp) + * + * fb assumptions: bpp % 8 = 0 (e.g. 8, 16, 24, 32 bpp) * bpp <= 32 * msb_right = 0 */ - this->bytes_per_pixel = (var.bits_per_pixel + 7)/8; + this->bytes_per_pixel = (this->fb_var.bits_per_pixel + 7)/8; this->bpp = this->bytes_per_pixel * 8; - this->depth = var.red.length + var.green.length + var.blue.length; - - if (this->depth>16) - printf ("\n\n" - "WARNING: current display depth is %d. For better performance\n" - "a depth of 16 bpp is recommended!\n\n", - this->depth); - - printf ("video_out_fb: video mode depth is %d (%d bpp),\n" - "\tred: %d/%d, green: %d/%d, blue: %d/%d\n", - this->depth, this->bpp, - var.red.length, var.red.offset, - var.green.length, var.green.offset, - var.blue.length, var.blue.offset ); - - mode = 0; - - switch (fix.visual) { - case FB_VISUAL_TRUECOLOR: - case FB_VISUAL_DIRECTCOLOR: - switch (this->depth) { - case 24: - if (this->bpp == 32) { - if (!var.blue.offset) - mode = MODE_32_RGB; - else - mode = MODE_32_BGR; - } else { - if (!var.blue.offset) - mode = MODE_24_RGB; - else - mode = MODE_24_BGR; - } - break; - case 16: - if (!var.blue.offset) - mode = MODE_16_RGB; - else - mode = MODE_16_BGR; - break; - case 15: - if (!var.blue.offset) - mode = MODE_15_RGB; - else - mode = MODE_15_BGR; - break; - case 8: - if (!var.blue.offset) - mode = MODE_8_RGB; - else - mode = MODE_8_BGR; - break; + this->depth = this->fb_var.red.length + + this->fb_var.green.length + + this->fb_var.blue.length; + + this->total_num_native_buffers = var->yres_virtual / var->yres; + this->used_num_buffers = 0; + + this->cur_frame = this->old_frame = 0; + + printf("video_out_fb: %d video RAM buffers are available.\n", + this->total_num_native_buffers); + + if(this->total_num_native_buffers < RECOMMENDED_NUM_BUFFERS) + { + this->use_zero_copy = 0; + printf("WARNING: video_out_fb: Zero copy buffers are DISABLED because only %d buffers\n" + " are available which is less than the recommended %d buffers. Lowering\n" + " the frame buffer resolution might help.\n", + this->total_num_native_buffers, + RECOMMENDED_NUM_BUFFERS); + } + else + { + /* test if FBIOPAN_DISPLAY works */ + this->fb_var.yoffset = this->fb_var.yres; + if(ioctl(this->fd, FBIOPAN_DISPLAY, &this->fb_var) == -1) { + printf("WARNING: video_out_fb: Zero copy buffers are DISABLED because kernel driver\n" + " do not support screen panning (used for frame flips).\n"); + } else { + this->fb_var.yoffset = 0; + ioctl(this->fd, FBIOPAN_DISPLAY, &this->fb_var); + + this->use_zero_copy = 1; + printf("video_out_fb: Using zero copy buffers.\n"); } - break; } +} - if (!mode) { - printf ("video_out_fb: your video mode was not recognized, sorry :-(\n"); - return NULL; +static vo_driver_t *fb_open_plugin(video_driver_class_t *class_gen, + const void *visual_gen) +{ + config_values_t *config; + fb_driver_t *this; + fb_class_t *class; + + class = (fb_class_t *)class_gen; + config = class->config; + + /* allocate plugin struct */ + this = malloc(sizeof(fb_driver_t)); + if(!this) + { + fprintf(stderr, "video_out_fb: malloc failed\n"); + return 0; } + memset(this, 0, sizeof(fb_driver_t)); - /* mmap whole video memory */ - this->mem_size = fix.smem_len; - this->video_mem = (char *) mmap(0, this->mem_size, PROT_READ | PROT_WRITE, - MAP_SHARED, this->fd, 0); - - this->yuv2rgb_mode = mode; - this->yuv2rgb_swap = 0; - this->yuv2rgb_gamma = config->register_range (config, "video.fb_gamma", 0, - -100, 100, - "gamma correction for fb driver", - NULL, 0, NULL, NULL); - - this->yuv2rgb_factory = yuv2rgb_factory_init (mode, this->yuv2rgb_swap, - this->yuv2rgb_cmap); - this->yuv2rgb_factory->set_gamma (this->yuv2rgb_factory, this->yuv2rgb_gamma); + register_callbacks(this); + + this->fd = open_fb_device(config); + if(this->fd == -1) + goto error; + if(!get_fb_var_screeninfo(this->fd, &this->fb_var)) + goto error; + if(!get_fb_fix_screeninfo(this->fd, &this->fb_fix)) + goto error; + + if(this->fb_fix.line_length) + this->fb_bytes_per_line = this->fb_fix.line_length; + else + this->fb_bytes_per_line = + (this->fb_var.xres_virtual * + this->fb_var.bits_per_pixel)/8; + + vo_scale_init(&this->sc, 0, 0, config); + this->sc.gui_width = this->fb_var.xres; + this->sc.gui_height = this->fb_var.yres; + this->sc.user_ratio = ASPECT_AUTO; + + this->sc.scaling_disabled = + config->register_bool(config, "video.disable_scaling", 0, + _("disable all video scaling (faster!)"), + NULL, 10, NULL, NULL); + + setup_buffers(this, &this->fb_var); + + if(this->depth > 16) + printf("WARNING: video_out_fb: current display depth is %d. For better performance\n" + " a depth of 16 bpp is recommended!\n\n", + this->depth); + + printf("video_out_fb: video mode depth is %d (%d bpp),\n" + " red: %d/%d, green: %d/%d, blue: %d/%d\n", + this->depth, this->bpp, + this->fb_var.red.length, this->fb_var.red.offset, + this->fb_var.green.length, this->fb_var.green.offset, + this->fb_var.blue.length, this->fb_var.blue.offset); - printf ("video_out_fb: warning, xine's framebuffer driver is EXPERIMENTAL\n"); + if(!setup_yuv2rgb(this, config, &this->fb_var, &this->fb_fix)) + goto error; + + /* mmap whole video memory */ + this->mem_size = this->fb_fix.smem_len; + this->video_mem_base = mmap(0, this->mem_size, PROT_READ | PROT_WRITE, + MAP_SHARED, this->fd, 0); return &this->vo_driver; +error: + free(this); + return 0; } -static char* fb_get_identifier (video_driver_class_t *this_gen) { +static char* fb_get_identifier(video_driver_class_t *this_gen) +{ return "fb"; } -static char* fb_get_description (video_driver_class_t *this_gen) { - return _("xine video output plugin using linux framebuffer device"); +static char* fb_get_description(video_driver_class_t *this_gen) +{ + return _("Xine video output plugin using the Linux frame buffer device"); } -static void fb_dispose_class (video_driver_class_t *this_gen) { - - fb_class_t *this = (fb_class_t *) this_gen; - - free (this); +static void fb_dispose_class(video_driver_class_t *this_gen) +{ + fb_class_t *this = (fb_class_t *)this_gen; + free(this); } -static void *fb_init_class (xine_t *xine, void *visual_gen) { - - fb_class_t *this = (fb_class_t *) malloc (sizeof (fb_class_t)); +static void *fb_init_class(xine_t *xine, void *visual_gen) +{ + fb_class_t *this = (fb_class_t *)malloc(sizeof(fb_class_t)); this->driver_class.open_plugin = fb_open_plugin; this->driver_class.get_identifier = fb_get_identifier; @@ -787,22 +1022,33 @@ static void *fb_init_class (xine_t *xine, void *visual_gen) { return this; } - -static vo_info_t vo_info_fb = { +static vo_info_t vo_info_fb = +{ 1, /* priority */ +#ifdef USE_X11_VISUAL + XINE_VISUAL_TYPE_X11 /* visual type */ +#else XINE_VISUAL_TYPE_FB /* visual type */ - -/* OBS: to use it from xine-ui set the X11 visual type */ -/* XINE_VISUAL_TYPE_X11 */ +#endif }; -/* - * exported plugin catalog entry - */ - -plugin_info_t xine_plugin_info[] = { +/* exported plugin catalog entry */ +plugin_info_t xine_plugin_info[] = +{ /* type, API, "name", version, special_info, init_function */ - { PLUGIN_VIDEO_OUT, 14, "fb", XINE_VERSION_CODE, &vo_info_fb, fb_init_class }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } + { + PLUGIN_VIDEO_OUT, + 14, + "fb", + XINE_VERSION_CODE, + &vo_info_fb, fb_init_class + }, + { + PLUGIN_NONE, + 0, + "", + 0, + NULL, + NULL + } }; - -- cgit v1.2.3