MPlayer-dev-eng
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1999 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
May 2019
- 3 participants
- 7 discussions
Allows specifying options to ffmpeg-based streams.
---
DOCS/man/en/mplayer.1 | 4 ++++
cfg-common.h | 1 +
stream/stream.h | 1 +
stream/stream_ffmpeg.c | 19 ++++++++++++++++++-
4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index 2a143cb..d8e9b3b 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -1806,6 +1806,10 @@ Skip the proxy for IPv6 addresses.
It will still be used for IPv4 connections.
.
.TP
+.B \-lavfstreamopts <options>
+Specify extra options for libavformat based streams.
+.
+.TP
.B \-loadidx <index file>
The file from which to read the video index data saved by \-saveidx.
This index will be used for seeking, overriding any index data
diff --git a/cfg-common.h b/cfg-common.h
index 3a422cf..ca4e9c9 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -545,6 +545,7 @@ const m_option_t common_opts[] = {
#ifdef CONFIG_FFMPEG
{"lavdopts", lavc_decode_opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
{"lavfdopts", lavfdopts_conf, CONF_TYPE_SUBCONFIG, CONF_GLOBAL, 0, 0, NULL},
+ {"lavfstreamopts", &lavfstreamopts, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
#endif
#ifdef CONFIG_XVID4
{"xvidopts", xvid_dec_opts, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
diff --git a/stream/stream.h b/stream/stream.h
index 615f579..388c353 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -392,6 +392,7 @@ extern char *dvd_device;
extern const m_option_t dvbin_opts_conf[];
extern char *rtsp_destination;
+extern char *lavfstreamopts;
typedef struct {
int id; // 0 - 31 mpeg; 128 - 159 ac3; 160 - 191 pcm
diff --git a/stream/stream_ffmpeg.c b/stream/stream_ffmpeg.c
index 57d45e4..1883af3 100644
--- a/stream/stream_ffmpeg.c
+++ b/stream/stream_ffmpeg.c
@@ -27,6 +27,8 @@
#include "av_helpers.h"
#include "libmpdemux/demuxer.h"
+char *lavfstreamopts;
+
static int fill_buffer(stream_t *s, char *buffer, int max_len)
{
int r = avio_read(s->priv, buffer, max_len);
@@ -90,6 +92,7 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format)
{
int flags = 0;
const char *filename;
+ AVDictionary *avopts = NULL;
AVIOContext *ctx = NULL;
int res = STREAM_ERROR;
int64_t size;
@@ -125,9 +128,23 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format)
dummy = !strncmp(filename, "rtsp:", 5) || !strncmp(filename, "dummy:", 6);
mp_msg(MSGT_OPEN, MSGL_V, "[ffmpeg] Opening %s\n", filename);
- if (!dummy && avio_open(&ctx, filename, flags) < 0)
+ if (lavfstreamopts && av_dict_parse_string(&avopts, lavfstreamopts, "=", ",", 0) < 0) {
+ mp_msg(MSGT_HEADER,MSGL_ERR, "Your options /%s/ look like gibberish to me pal\n", lavfstreamopts);
+ goto out;
+ }
+
+ if (!dummy && avio_open2(&ctx, filename, flags, NULL, &avopts) < 0)
goto out;
+ if (!dummy && av_dict_count(avopts)) {
+ AVDictionaryEntry *e = NULL;
+ while ((e = av_dict_get(avopts, "", e, AV_DICT_IGNORE_SUFFIX))) {
+ mp_msg(MSGT_HEADER,MSGL_ERR,"Unknown option %s\n", e->key);
+ }
+ goto out;
+ }
+ av_dict_free(&avopts);
+
stream->priv = ctx;
size = dummy ? 0 : avio_size(ctx);
if (size >= 0)
--
2.7.0
1
1
IVTV support is for a long time available through Video4Linux.
The hardware can still be used through the v4l2 vo and ao drivers.
There is still IVTV linux code in a VIDIX driver. This change
doesn't remove the IVTV remnants in the VIDIX source.
Signed-off-by: Alexander Strasser <eclipse7(a)gmx.net>
---
The VIDIX driver is named ivtv (vidix/ivtv_vid.c in MPlayer). It
supports MPEG decoder cards via the ivtv kernel driver or the V4L
kernel driver.
Is there by chance anyone reading this, using vidix ivtv driver in
MPlayer? Or outside of MPlayer?
Anyway as IVTV vs V4L is determined at compile time, I guess I could
safely remove it based on the #ifdefs.
DOCS/man/en/mplayer.1 | 20 ---
DOCS/tech/MAINTAINERS | 2 -
Makefile | 1 -
configure | 35 -----
libao2/ao_ivtv.c | 162 -----------------------
libao2/audio_out.c | 4 -
libvo/video_out.c | 4 -
libvo/vo_ivtv.c | 300 ------------------------------------------
libvo/vo_ivtv.h | 34 -----
stream/pvr.h | 2 -
stream/stream_pvr.c | 2 -
11 files changed, 566 deletions(-)
delete mode 100644 libao2/ao_ivtv.c
delete mode 100644 libvo/vo_ivtv.c
delete mode 100644 libvo/vo_ivtv.h
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index c832df7d8..a8b1bfacf 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -3268,11 +3268,6 @@ Set buffer size to <size> in samples (default: 2048).
Creative DXR2 specific output driver
.
.TP
-.B ivtv (IVTV only)
-IVTV specific MPEG audio output driver.
-Works with \-ac hwmpa only.
-.
-.TP
.B v4l2 (requires Linux 2.6.22+ kernel)
Audio output driver for V4L2 cards with hardware MPEG decoder.
.
@@ -4730,21 +4725,6 @@ Specifies the device number to use if you have more than one em8300 card.
.PD 1
.
.TP
-.B ivtv (IVTV only)
-Conexant CX23415 (iCompression iTVC15) or Conexant CX23416 (iCompression
-iTVC16) MPEG decoder chip (Hauppauge WinTV PVR-150/250/350/500)
-specific video output driver for TV-out.
-Also see the lavc video filter.
-.PD 0
-.RSs
-.IPs <device>
-Explicitly choose the MPEG decoder device name to use (default: /dev/video16).
-.IPs <output>
-Explicitly choose the TV-out output to be used for the video signal.
-.RE
-.PD 1
-.
-.TP
.B v4l2 (requires Linux 2.6.22+ kernel)
Video output driver for V4L2 compliant cards with built-in hardware MPEG decoder.
Also see the lavc video filter.
diff --git a/DOCS/tech/MAINTAINERS b/DOCS/tech/MAINTAINERS
index 442d3b133..8b114814b 100644
--- a/DOCS/tech/MAINTAINERS
+++ b/DOCS/tech/MAINTAINERS
@@ -169,7 +169,6 @@ libvo drivers:
* vo_gif89a.c - Joey Parrish
* vo_gl.c - Reimar Döffinger
* vo_gl2.c - Reimar Döffinger
- * vo_ivtv.c - Benjamin Zores
* vo_jpeg.c - Ivo van Poorten
* vo_md5sum.c - Ivo van Poorten
* vo_mga.c - None
@@ -206,7 +205,6 @@ libao2 drivers:
* ao_dsound.c - None
* ao_dxr2.c - None
* ao_esd.c - None
- * ao_ivtv.c - Benjamin Zores
* ao_jack.c - Reimar Döffinger
* ao_mpegpes.c - None
* ao_nas.c - Tobias Diedrich
diff --git a/Makefile b/Makefile
index efa871d01..d2e406723 100644
--- a/Makefile
+++ b/Makefile
@@ -509,7 +509,6 @@ SRCS_MPLAYER-$(GUI_WIN32) += gui/win32/dialogs.c \
gui/win32/widgetrender.c \
gui/win32/wincfg.c \
-SRCS_MPLAYER-$(IVTV) += libao2/ao_ivtv.c libvo/vo_ivtv.c
SRCS_MPLAYER-$(JACK) += libao2/ao_jack.c
SRCS_MPLAYER-$(JOYSTICK) += input/joystick.c
SRCS_MPLAYER-$(JPEG) += libvo/vo_jpeg.c
diff --git a/configure b/configure
index 15cf1b3a4..8f14bab22 100755
--- a/configure
+++ b/configure
@@ -478,7 +478,6 @@ Video output:
--enable-directx enable DirectX video output [autodetect]
--enable-dxr2 enable DXR2 video output [autodetect]
--enable-dxr3 enable DXR3/H+ video output [autodetect]
- --enable-ivtv enable IVTV TV-Out video output [autodetect]
--enable-v4l2 enable V4L2 Decoder audio/video output [autodetect]
--enable-dvb enable DVB video output [autodetect]
--enable-mga enable mga_vid video output [autodetect]
@@ -706,7 +705,6 @@ _fbdev=auto
_dvb=auto
_dxr2=auto
_dxr3=auto
-_ivtv=auto
_v4l2=auto
_iconv=auto
_langinfo=auto
@@ -1083,8 +1081,6 @@ for ac_option do
--disable-dxr2) _dxr2=no ;;
--enable-dxr3) _dxr3=yes ;;
--disable-dxr3) _dxr3=no ;;
- --enable-ivtv) _ivtv=yes ;;
- --disable-ivtv) _ivtv=no ;;
--enable-v4l2) _v4l2=yes ;;
--disable-v4l2) _v4l2=no ;;
--enable-iconv) _iconv=yes ;;
@@ -5835,35 +5831,6 @@ fi
echores "$_dxr3"
-echocheck "IVTV TV-Out (pre linux-2.6.24)"
-if test "$_ivtv" = auto ; then
- cat > $TMPC << EOF
-#include <sys/time.h>
-#include <linux/videodev2.h>
-#include <linux/ivtv.h>
-#include <sys/ioctl.h>
-int main(void) {
-struct ivtv_cfg_stop_decode sd;
-struct ivtv_cfg_start_decode sd1;
-ioctl(0, IVTV_IOC_START_DECODE, &sd1);
-ioctl(0, IVTV_IOC_STOP_DECODE, &sd);
-return 0; }
-EOF
- _ivtv=no
- cc_check && _ivtv=yes
-fi
-if test "$_ivtv" = yes ; then
- def_ivtv='#define CONFIG_IVTV 1'
- vomodules="ivtv $vomodules"
- aomodules="ivtv $aomodules"
-else
- def_ivtv='#undef CONFIG_IVTV'
- novomodules="ivtv $novomodules"
- noaomodules="ivtv $noaomodules"
-fi
-echores "$_ivtv"
-
-
echocheck "V4L2 MPEG Decoder"
if test "$_v4l2" = auto ; then
cat > $TMPC << EOF
@@ -8498,7 +8465,6 @@ GUI_WIN32 = $_gui_win32
HAVE_POSIX_SELECT = $_posix_select
HAVE_SYS_MMAN_H = $_mman
HAVE_WINDOWS_H = $windows_h
-IVTV = $_ivtv
JACK = $_jack
JOYSTICK = $_joystick
JPEG = $_jpeg
@@ -9139,7 +9105,6 @@ $def_gl_egl_x11
$def_gl_sdl
$def_gl_osx
$def_matrixview
-$def_ivtv
$def_jpeg
$def_kva
$def_md5sum
diff --git a/libao2/ao_ivtv.c b/libao2/ao_ivtv.c
deleted file mode 100644
index b432cd05d..000000000
--- a/libao2/ao_ivtv.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * audio output for WinTV PVR-150/250/350 (a.k.a IVTV) cards
- * through Connexant hardware MPEG decoder
- * See http://ivtvdriver.org/index.php/Main_Page for more details on the
- * cards supported by the ivtv driver.
- *
- * WARNING: You need to force -ac hwmpa for audio output to work.
- *
- * Copyright (C) 2006 Benjamin Zores
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <inttypes.h>
-
-#include "config.h"
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#include "audio_out.h"
-#include "audio_out_internal.h"
-#include "libaf/af_format.h"
-#include "libmpdemux/mpeg_packetizer.h"
-#include "libvo/vo_ivtv.h"
-#include "libvo/video_out.h" /* only for vo_pts */
-
-#define MPEG_AUDIO_ID 0x1C0
-
-static int freq = 0;
-
-static const ao_info_t info =
-{
- "IVTV MPEG Audio Decoder output",
- "ivtv",
- "Benjamin Zores",
- ""
-};
-
-LIBAO_EXTERN(ivtv)
-
-/* to set/get/query special features/parameters */
-static int
-control (int cmd,void *arg)
-{
- return CONTROL_UNKNOWN;
-}
-
-/* open & setup audio device */
-static int
-init (int rate, int channels, int format, int flags)
-{
- if (ivtv_fd < 0)
- return 0;
-
- if (format != AF_FORMAT_MPEG2)
- {
- mp_msg (MSGT_AO, MSGL_FATAL,
- "AO: [ivtv] can only handle MPEG audio streams.\n");
- return 0;
- }
-
- ao_data.outburst = 2048;
- ao_data.samplerate = rate;
- ao_data.channels = channels;
- ao_data.format = AF_FORMAT_MPEG2;
- ao_data.buffersize = 2048;
- ao_data.bps = rate * 2 * 2;
- ao_data.pts = 0;
- freq = rate;
-
- /* check for supported audio rate */
- if (rate != 32000 && rate != 41000 && rate != 48000)
- {
- mp_msg (MSGT_AO, MSGL_ERR, MSGTR_AO_MPEGPES_UnsupSamplerate, rate);
- rate = 48000;
- }
-
- return 1;
-}
-
-/* close audio device */
-static void
-uninit (int immed)
-{
- /* nothing to do */
-}
-
-/* stop playing and empty buffers (for seeking/pause) */
-static void
-reset (void)
-{
- /* nothing to do */
-}
-
-/* stop playing, keep buffers (for pause) */
-static void
-audio_pause (void)
-{
- reset ();
-}
-
-/* resume playing, after audio_pause() */
-static void
-audio_resume (void)
-{
- /* nothing to do */
-}
-
-/* how many bytes can be played without blocking */
-static int
-get_space (void)
-{
- float x;
- int y;
-
- x = (float) (vo_pts - ao_data.pts) / 90000.0;
- if (x <= 0)
- return 0;
-
- y = freq * 4 * x;
- y /= ao_data.outburst;
- y *= ao_data.outburst;
-
- if (y > 32000)
- y = 32000;
-
- return y;
-}
-
-/* number of bytes played */
-static int
-play (void *data, int len, int flags)
-{
- if (ao_data.format != AF_FORMAT_MPEG2)
- return 0;
-
- send_mpeg_pes_packet (data, len, MPEG_AUDIO_ID, ao_data.pts, 2, ivtv_write);
-
- return len;
-}
-
-/* delay in seconds between first and last sample in buffer */
-static float
-get_delay (void)
-{
- return 0.0;
-}
diff --git a/libao2/audio_out.c b/libao2/audio_out.c
index 197a63bf7..1b4caf122 100644
--- a/libao2/audio_out.c
+++ b/libao2/audio_out.c
@@ -50,7 +50,6 @@ extern const ao_functions_t audio_out_dsound;
extern const ao_functions_t audio_out_kai;
extern const ao_functions_t audio_out_dart;
extern const ao_functions_t audio_out_dxr2;
-extern const ao_functions_t audio_out_ivtv;
extern const ao_functions_t audio_out_v4l2;
extern const ao_functions_t audio_out_mpegpes;
extern const ao_functions_t audio_out_pcm;
@@ -115,9 +114,6 @@ const ao_functions_t* const audio_out_drivers[] =
#ifdef CONFIG_DXR2
&audio_out_dxr2,
#endif
-#ifdef CONFIG_IVTV
- &audio_out_ivtv,
-#endif
#ifdef CONFIG_V4L2_DECODER
&audio_out_v4l2,
#endif
diff --git a/libvo/video_out.c b/libvo/video_out.c
index bcf5174f0..a0a01400d 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -129,7 +129,6 @@ extern const vo_functions_t video_out_directx;
extern const vo_functions_t video_out_kva;
extern const vo_functions_t video_out_dxr2;
extern const vo_functions_t video_out_dxr3;
-extern const vo_functions_t video_out_ivtv;
extern const vo_functions_t video_out_v4l2;
extern const vo_functions_t video_out_jpeg;
extern const vo_functions_t video_out_gif89a;
@@ -245,9 +244,6 @@ const vo_functions_t* const video_out_drivers[] =
#ifdef CONFIG_DXR3
&video_out_dxr3,
#endif
-#ifdef CONFIG_IVTV
- &video_out_ivtv,
-#endif
#ifdef CONFIG_V4L2_DECODER
&video_out_v4l2,
#endif
diff --git a/libvo/vo_ivtv.c b/libvo/vo_ivtv.c
deleted file mode 100644
index f58140207..000000000
--- a/libvo/vo_ivtv.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * video output for WinTV PVR-150/250/350 (a.k.a IVTV) cards
- * TV-Out through hardware MPEG decoder
- * Based on some old code from ivtv driver authors.
- * See http://ivtvdriver.org/index.php/Main_Page for more details on the
- * cards supported by the ivtv driver.
- *
- * Copyright (C) 2006 Benjamin Zores
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include <linux/ivtv.h>
-#include <linux/ioctl.h>
-
-#include "mp_msg.h"
-#include "subopt-helper.h"
-#include "video_out.h"
-#define NO_DRAW_SLICE
-#include "video_out_internal.h"
-#include "vo_ivtv.h"
-#include "libmpdemux/mpeg_packetizer.h"
-
-#define DEFAULT_MPEG_DECODER "/dev/video16"
-#define IVTV_VO_HDR "VO: [ivtv]"
-
-/* ivtv private */
-int ivtv_fd = -1;
-static vo_mpegpes_t *pes;
-
-/* suboptions */
-static int output = -1;
-static char *device = NULL;
-
-static const opt_t subopts[] = {
- {"output", OPT_ARG_INT, &output, int_non_neg},
- {"device", OPT_ARG_MSTRZ, &device, NULL},
- {NULL}
-};
-
-static const vo_info_t info =
-{
- "IVTV MPEG Video Decoder TV-Out",
- "ivtv",
- "Benjamin Zores",
- ""
-};
-const LIBVO_EXTERN (ivtv)
-
-/* ivtv internals */
-
-static uint32_t
-ivtv_reset (int blank_screen)
-{
- struct ivtv_cfg_stop_decode sd;
- struct ivtv_cfg_start_decode sd1;
- int flags = 0;
-
- if (blank_screen)
- flags |= IVTV_STOP_FL_HIDE_FRAME;
- sd.flags = flags;
-
- if (ioctl (ivtv_fd, IVTV_IOC_STOP_DECODE, &sd) < 0)
- {
- mp_msg (MSGT_VO, MSGL_ERR,
- "IVTV_IOC_STOP_DECODE: %s\n", strerror (errno));
- return 1;
- }
-
- sd1.gop_offset = 0;
- sd1.muted_audio_frames = 0;
-
- if (ioctl (ivtv_fd, IVTV_IOC_START_DECODE, &sd1) < 0)
- {
- mp_msg (MSGT_VO, MSGL_ERR,
- "IVTV_IOC_START_DECODE: %s\n", strerror (errno));
- return 1;
- }
-
- return 0;
-}
-
-int
-ivtv_write (const unsigned char *data, int len)
-{
- if (ivtv_fd < 0)
- return 0;
-
- return write (ivtv_fd, data, len);
-}
-
-/* video out functions */
-
-static int
-config (uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height,
- uint32_t fullscreen, char *title, uint32_t format)
-{
- return 0;
-}
-
-static int
-preinit (const char *arg)
-{
- struct v4l2_output vout;
- int err;
-
- if (subopt_parse (arg, subopts) != 0)
- {
- mp_msg (MSGT_VO, MSGL_FATAL,
- "\n-vo ivtv command line help:\n"
- "Example: mplayer -vo ivtv:device=/dev/video16:output=2\n"
- "\nOptions:\n"
- " device=/dev/videoX\n"
- " Name of the MPEG decoder device file.\n"
- " output=<0-...>\n"
- " V4L2 id of the TV output.\n"
- "\n" );
- return -1;
- }
-
- if (!device)
- device = strdup (DEFAULT_MPEG_DECODER);
-
- ivtv_fd = open (device, O_RDWR);
- if (ivtv_fd < 0)
- {
- free (device);
- mp_msg (MSGT_VO, MSGL_FATAL, "%s %s\n", IVTV_VO_HDR, strerror (errno));
- return -1;
- }
-
- /* list available outputs */
- vout.index = 0;
- err = 1;
- mp_msg (MSGT_VO, MSGL_INFO, "%s Available video outputs: ", IVTV_VO_HDR);
- while (ioctl (ivtv_fd, VIDIOC_ENUMOUTPUT, &vout) >= 0)
- {
- err = 0;
- mp_msg (MSGT_VO, MSGL_INFO, "'#%d, %s' ", vout.index, vout.name);
- vout.index++;
- }
- if (err)
- {
- mp_msg (MSGT_VO, MSGL_INFO, "none\n");
- free (device);
- return -1;
- }
- else
- mp_msg (MSGT_VO, MSGL_INFO, "\n");
-
- /* set user specified output */
- if (output != -1)
- {
- if (ioctl (ivtv_fd, VIDIOC_S_OUTPUT, &output) < 0)
- {
- mp_msg (MSGT_VO, MSGL_ERR,
- "%s can't set output (%s)\n", IVTV_VO_HDR, strerror (errno));
- free (device);
- return -1;
- }
- }
-
- /* display device name */
- mp_msg (MSGT_VO, MSGL_INFO, "%s using %s\n", IVTV_VO_HDR, device);
- free (device);
-
- /* display current video output */
- if (ioctl (ivtv_fd, VIDIOC_G_OUTPUT, &output) == 0)
- {
- vout.index = output;
- if (ioctl (ivtv_fd, VIDIOC_ENUMOUTPUT, &vout) < 0)
- {
- mp_msg (MSGT_VO, MSGL_ERR,
- "%s can't get output (%s).\n", IVTV_VO_HDR, strerror (errno));
- return -1;
- }
- else
- mp_msg (MSGT_VO, MSGL_INFO,
- "%s video output: %s\n", IVTV_VO_HDR, vout.name);
- }
- else
- {
- mp_msg (MSGT_VO, MSGL_ERR,
- "%s can't get output (%s).\n", IVTV_VO_HDR, strerror (errno));
- return -1;
- }
-
- /* clear output */
- ivtv_reset (1);
-
- return 0;
-}
-
-static void
-draw_osd (void)
-{
- /* do nothing */
-}
-
-static int
-draw_frame (uint8_t * src[])
-{
- pes = (vo_mpegpes_t *) src[0];
- return 0;
-}
-
-static void
-flip_page (void)
-{
- if (ivtv_fd < 0)
- return;
-
- if (!pes)
- return;
-
- send_mpeg_pes_packet (pes->data, pes->size, pes->id,
- pes->timestamp ? pes->timestamp : vo_pts, 2,
- ivtv_write);
-
- /* ensure flip_page() won't be called twice */
- pes = NULL;
-}
-
-static void
-uninit (void)
-{
- if (ivtv_fd < 0)
- return;
-
- /* clear output */
- ivtv_reset (1);
-
- /* close device */
- close (ivtv_fd);
- ivtv_fd = -1;
-}
-
-static void
-check_events (void)
-{
- /* do nothing */
-}
-
-static int
-query_format (uint32_t format)
-{
- if (format != IMGFMT_MPEGPES)
- return 0;
-
- return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_TIMER;
-}
-
-static int
-control (uint32_t request, void *data)
-{
- switch (request)
- {
- case VOCTRL_PAUSE:
- case VOCTRL_RESUME:
- return ivtv_reset (0);
-
- case VOCTRL_RESET:
- return ivtv_reset (1);
-
- case VOCTRL_QUERY_FORMAT:
- return query_format (*((uint32_t*) data));
- }
-
- return VO_NOTIMPL;
-}
diff --git a/libvo/vo_ivtv.h b/libvo/vo_ivtv.h
deleted file mode 100644
index da957b4a7..000000000
--- a/libvo/vo_ivtv.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * video output for WinTV PVR-150/250/350 (a.k.a IVTV) cards
- * TV-Out through hardware MPEG decoder
- * Based on some old code from ivtv driver authors.
- * See http://ivtvdriver.org/index.php/Main_Page for more details on the
- * cards supported by the ivtv driver.
- *
- * Copyright (C) 2006 Benjamin Zores
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_VO_IVTV_H
-#define MPLAYER_VO_IVTV_H
-
-extern int ivtv_fd;
-
-int ivtv_write(const unsigned char *data, int len);
-
-#endif /* MPLAYER_VO_IVTV_H */
diff --git a/stream/pvr.h b/stream/pvr.h
index 7659c1437..6dda73ce7 100644
--- a/stream/pvr.h
+++ b/stream/pvr.h
@@ -1,8 +1,6 @@
/*
* stream layer for hardware MPEG 1/2/4 encoders a.k.a PVR
* (such as WinTV PVR-150/250/350/500 (a.k.a IVTV), pvrusb2 and cx88)
- * See http://ivtvdriver.org/index.php/Main_Page for more details on the
- * cards supported by the ivtv driver.
*
* Copyright (C) 2006 Benjamin Zores
* Copyright (C) 2007 Sven Gothel (Channel Navigation)
diff --git a/stream/stream_pvr.c b/stream/stream_pvr.c
index c6f6d185a..e03e76a73 100644
--- a/stream/stream_pvr.c
+++ b/stream/stream_pvr.c
@@ -1,8 +1,6 @@
/*
* stream layer for hardware MPEG 1/2/4 encoders a.k.a PVR
* (such as WinTV PVR-150/250/350/500 (a.k.a IVTV), pvrusb2 and cx88)
- * See http://ivtvdriver.org/index.php/Main_Page for more details on the
- * cards supported by the ivtv driver.
*
* Copyright (C) 2006 Benjamin Zores
* Copyright (C) 2007 Sven Gothel (channel navigation)
--
3
5
Hello.
I tried to add libdav1d support into mplayer/ffmpeg.
It works as in - shows picture from webm/mp4 and allow me to seek around.
But my check for header (like in ALSA check) may be not good (ffmpeg only
supports libdav1d >=0.2.1)
MPlayer svn 38140
ffmpeg git commit 1eb54323c82ff6eff18553fd3f2788a695bdf812
MPlayer emit this warning, I assume for removing it whole interface between
mplayer and libavcodec's decoders must be upgraded?
./mplayer /dev/shm/av1_svt_0.5_2100frames-7.webm
MPlayer SVN-r38140-5.5.0 (C) 2000-2019 MPlayer Team
224 audio & 465 video codecs
Playing /dev/shm/av1_svt_0.5_2100frames-7.webm.
libavformat version 58.27.103 (internal)
libavformat file format detected.
[libdav1d @ 0x5774cb00]libdav1d 0.3.1
[lavf] stream 0: video (libdav1d), -vid 0
VIDEO: [AV01] 1280x720 0bpp 30.000 fps 0.0 kbps ( 0.0 kbyte/s)
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 58.52.102 (internal)
[libdav1d @ 0x5774cb00]libdav1d 0.3.1
Selected video codec: [av1] vfm: ffmpeg (AV1)
==========================================================================
Clip info:
ENCODER: Lavf58.27.103
Load subtitles in /dev/shm/
Audio: no sound
Starting playback...
Movie-Aspect is 1.78:1 - prescaling to correct movie aspect.
VO: [vdpau] 1280x720 => 1280x720 Planar YV12
V: 0.2 0/ 0 ??% ??% ??,?% 0 0
[libdav1d @ 0x5774cb00]The deprecated avcodec_decode_* API cannot return all the frames for this decoder. Some frames will be dropped. Update your code to the new decoding API to fix this.
V: 10.4 0/ 0 5% 13% 0.0% 0 0
Exiting... (Quit)
1
0
26 May '19
Intrinsics are not well liked for good reason,
but it is much faster to implement and compilers
are no longer completely horrible for x86.
Speed is about 2x-3x and it matches the C code instead
of the less accurate MMX code.
Primary motivation is though that MMX is starting to
have worse and worse support in CPUs.
To benchmark, use this command and remove the reading code
from rawvideo and the memcpy_pic from vf_expand.
./mplayer /dev/zero -demuxer rawvideo -rawvideo w=1920:h=1080:format=yuy2 -vo null -osdlevel 3 -benchmark -quiet -frames 50000 -vf expand=osd=1 -subfont-osd-scale 20
---
configure | 26 ++++
sub/osd.c | 94 +++++++++++---
sub/osd_template.c | 303 +++++++++++++++++++++++++++++++++++++++++++--
sub/sub.c | 2 +-
4 files changed, 398 insertions(+), 27 deletions(-)
diff --git a/configure b/configure
index fc04a568a..9cfae1785 100755
--- a/configure
+++ b/configure
@@ -3863,6 +3863,26 @@ header_check sys/poll.h && poll_h=yes &&
def_poll_h='#define HAVE_POLL_H 1'
echores "$poll_h"
+echocheck "emmintrin.h (SSE intrinsics)"
+emmintrin_h=no
+def_emmintrin_h='#define HAVE_EMMINTRIN_H 0'
+ cat > $TMPC << EOF
+#include <emmintrin.h>
+
+__attribute__((target("sse2")))
+static int sse2test(int i) {
+ __m128i mmi = _mm_set1_epi16(i);
+ mmi = _mm_add_epi16(mmi, mmi);
+ return _mm_extract_epi16(mmi, 2);
+}
+
+int main(int argc, char **argv) {
+ return sse2test(argc);
+}
+EOF
+cc_check && emmintrin_h=yes &&
+ def_emmintrin_h='#define HAVE_EMMINTRIN_H 1'
+echores "$emmintrin_h"
echocheck "inttypes.h (required)"
_inttypes=no
@@ -9223,6 +9243,12 @@ $def_direct_h
$def_io_h
$def_poll_h
$def_windows_h
+$def_emmintrin_h
+#if ARCH_X86_32
+#define ATTR_TARGET_SSE2 __attribute__((target("sse2")))
+#else
+#define ATTR_TARGET_SSE2
+#endif
/* external libraries */
$def_bzlib
diff --git a/sub/osd.c b/sub/osd.c
index a2d002526..3e336b5e4 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -31,7 +31,12 @@
#include "libmpcodecs/img_format.h"
#include "cpudetect.h"
-#if ARCH_X86
+#if !HAVE_EMMINTRIN_H
+#undef HAVE_SSE2
+#define HAVE_SSE2 0
+#endif
+
+#if ARCH_X86 && (!HAVE_SSE2 || CONFIG_RUNTIME_CPUDETECT)
static const uint64_t bFF __attribute__((aligned(8))) = 0xFFFFFFFFFFFFFFFFULL;
static const unsigned long long mask24lh __attribute__((aligned(8))) = 0xFFFF000000000000ULL;
static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FFFFFFFFFFFFULL;
@@ -39,32 +44,38 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
//Note: we have C, X86-nommx, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
//Plain C versions
-#if !HAVE_MMX || CONFIG_RUNTIME_CPUDETECT
+#if (!HAVE_MMX && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_C
#endif
#if ARCH_X86
-#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
+#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2 && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_MMX
#endif
-#if HAVE_MMX2 || CONFIG_RUNTIME_CPUDETECT
+#if (HAVE_MMX2 && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_MMX2
#endif
-#if (HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
+#if (HAVE_AMD3DNOW && !HAVE_MMX2 && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_3DNOW
#endif
+#if HAVE_SSE2 || CONFIG_RUNTIME_CPUDETECT
+#define COMPILE_SSE2
+#endif
+
#endif /* ARCH_X86 */
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 0
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#if ! ARCH_X86
@@ -72,9 +83,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 0
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _C
#include "osd_template.c"
#endif
@@ -87,9 +100,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 0
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _X86
#include "osd_template.c"
#endif
@@ -100,9 +115,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 1
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _MMX
#include "osd_template.c"
#endif
@@ -113,9 +130,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 1
#define HAVE_MMX2 1
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _MMX2
#include "osd_template.c"
#endif
@@ -126,20 +145,39 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 1
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 1
+#define HAVE_SSE2 0
#define RENAME(a) a ## _3DNow
#include "osd_template.c"
#endif
+//SSE2 versions
+#ifdef COMPILE_SSE2
+#undef RENAME
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
+#define HAVE_MMX 0
+#define HAVE_MMX2 0
+#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 1
+#define RENAME(a) a ## _SSE2
+#include <emmintrin.h>
+#include "osd_template.c"
+#endif
#endif /* ARCH_X86 */
void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(HAVE_EMMINTRIN_H && gCpuCaps.hasSSE2)
+ vo_draw_alpha_yv12_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -151,7 +189,9 @@ void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, in
vo_draw_alpha_yv12_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_yv12_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -169,7 +209,9 @@ void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, in
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(HAVE_EMMINTRIN_H && gCpuCaps.hasSSE2)
+ vo_draw_alpha_yuy2_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -181,7 +223,9 @@ void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, in
vo_draw_alpha_yuy2_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_yuy2_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -199,7 +243,9 @@ void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, in
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(HAVE_EMMINTRIN_H && gCpuCaps.hasSSE2)
+ vo_draw_alpha_uyvy_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -211,7 +257,9 @@ void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, in
vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_uyvy_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -229,7 +277,9 @@ void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, i
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(HAVE_EMMINTRIN_H && gCpuCaps.hasSSE2)
+ vo_draw_alpha_rgb24_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -241,7 +291,9 @@ void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, i
vo_draw_alpha_rgb24_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_rgb24_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -259,7 +311,9 @@ void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, i
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(HAVE_EMMINTRIN_H && gCpuCaps.hasSSE2)
+ vo_draw_alpha_rgb32_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -271,7 +325,9 @@ void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, i
vo_draw_alpha_rgb32_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_rgb32_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -306,7 +362,9 @@ void vo_draw_alpha_init(void){
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered per speed fasterst first
- if(gCpuCaps.hasMMX2)
+ if(HAVE_EMMINTRIN_H && gCpuCaps.hasSSE2)
+ mp_msg(MSGT_OSD,MSGL_INFO,"Using SSE2 Optimized OnScreenDisplay\n");
+ else if(gCpuCaps.hasMMX2)
mp_msg(MSGT_OSD,MSGL_INFO,"Using MMX (with tiny bit MMX2) Optimized OnScreenDisplay\n");
else if(gCpuCaps.has3DNow)
mp_msg(MSGT_OSD,MSGL_INFO,"Using MMX (with tiny bit 3DNow) Optimized OnScreenDisplay\n");
@@ -318,7 +376,9 @@ void vo_draw_alpha_init(void){
mp_msg(MSGT_OSD,MSGL_INFO,"Using Unoptimized OnScreenDisplay\n");
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ mp_msg(MSGT_OSD,MSGL_INFO,"Using SSE2 Optimized OnScreenDisplay\n");
+#elif HAVE_MMX2
mp_msg(MSGT_OSD,MSGL_INFO,"Using MMX (with tiny bit MMX2) Optimized OnScreenDisplay\n");
#elif HAVE_AMD3DNOW
mp_msg(MSGT_OSD,MSGL_INFO,"Using MMX (with tiny bit 3DNow) Optimized OnScreenDisplay\n");
diff --git a/sub/osd_template.c b/sub/osd_template.c
index 6d8305a3c..1e7fb8205 100644
--- a/sub/osd_template.c
+++ b/sub/osd_template.c
@@ -44,9 +44,60 @@
#define EMMS "emms"
#endif
+#if HAVE_SSE2
+ATTR_TARGET_SSE2
+static inline __m128i muladd_src_unpacked(__m128i dstlo, __m128i dsthi, __m128i src, __m128i srcalo, __m128i srcahi)
+{
+ // (mmhigh,mmlow) = (dst * (srca * 256)) / 65536 (= (dst * srca) >> 8)
+ __m128i mmlow = _mm_mulhi_epu16(dstlo, srcalo);
+ __m128i mmhigh = _mm_mulhi_epu16(dsthi, srcahi);
+
+ __m128i res = _mm_packus_epi16(mmlow, mmhigh);
+
+ return _mm_add_epi8(res, src);
+}
+
+ATTR_TARGET_SSE2
+static inline __m128i muladd_src(__m128i dst, __m128i src, __m128i srca)
+{
+ __m128i zero = _mm_setzero_si128();
+ __m128i dstlo = _mm_unpacklo_epi8(dst, zero);
+ __m128i dsthi = _mm_unpackhi_epi8(dst, zero);
+ __m128i srcalo = _mm_unpacklo_epi8(zero, srca);
+ __m128i srcahi = _mm_unpackhi_epi8(zero, srca);
+ return muladd_src_unpacked(dstlo, dsthi, src, srcalo, srcahi);
+}
+
+ATTR_TARGET_SSE2
+static inline __m128i alphamask(__m128i orig, __m128i blended, __m128i srca)
+{
+ __m128i zero = _mm_setzero_si128();
+ // if (!srca) res |= dst --- assumes srca == 0 implies src == 0,
+ // thus no need to mask res
+ __m128i mask = _mm_cmpeq_epi8(srca, zero);
+ orig = _mm_and_si128(orig, mask);
+ return _mm_or_si128(blended, orig);
+}
+
+// Special version that compares alpha in 16 bit chunks instead of bytewise
+ATTR_TARGET_SSE2
+static inline __m128i alphamask16(__m128i orig, __m128i blended, __m128i srca)
+{
+ __m128i zero = _mm_setzero_si128();
+ // if (!srca) res |= dst --- assumes srca == 0 implies src == 0,
+ // thus no need to mask res
+ __m128i mask = _mm_cmpeq_epi16(srca, zero);
+ orig = _mm_and_si128(orig, mask);
+ return _mm_or_si128(blended, orig);
+}
+#endif
+
+#if HAVE_SSE2
+ATTR_TARGET_SSE2
+#endif
static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
int y;
-#if defined(FAST_OSD) && !HAVE_MMX
+#if defined(FAST_OSD) && !HAVE_MMX && !HAVE_SSE2
w=w>>1;
#endif
#if HAVE_MMX
@@ -94,7 +145,28 @@ static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, u
:: "m" (dstbase[x]), "m" (srca[x]), "m" (src[x])
: "%eax");
}
-#else
+#elif HAVE_SSE2
+ __m128i zero = _mm_setzero_si128();
+ for(x=0;x+8<w;x+=16){
+ __m128i mmsrc, mmdst, res;
+ __m128i mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+
+ int alpha = _mm_movemask_epi8(_mm_cmpeq_epi8(mmsrca, zero));
+ if (alpha == 0xffff) continue;
+
+ mmdst = _mm_loadu_si128((const __m128i *)(dstbase + x));
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+
+ res = muladd_src(mmdst, mmsrc, mmsrca);
+
+ // _mm_maskmoveu_s128 would be an alternative but slower
+ res = alphamask(mmdst, res, mmsrca);
+ _mm_storeu_si128((__m128i *)(dstbase + x), res);
+ }
+ for(;x<w;x++){
+ if(srca[x]) dstbase[x]=((dstbase[x]*srca[x])>>8)+src[x];
+ }
+#else /* HAVE_SSE2 */
for(x=0;x<w;x++){
#ifdef FAST_OSD
if(srca[2*x+0]) dstbase[2*x+0]=src[2*x+0];
@@ -114,6 +186,9 @@ static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, u
return;
}
+#if HAVE_SSE2
+ATTR_TARGET_SSE2
+#endif
static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
int y;
#if defined(FAST_OSD) && !HAVE_MMX
@@ -155,7 +230,7 @@ static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, u
"psrlw $8, %%mm0\n\t"
"pand %%mm5, %%mm1\n\t" //U0V0U0V0
"movd %2, %%mm2\n\t" //src 0000DCBA
- "punpcklbw %%mm7, %%mm2\n\t" //srca 0D0C0B0A
+ "punpcklbw %%mm7, %%mm2\n\t" //src 0D0C0B0A
"por %%mm1, %%mm0\n\t"
"paddb %%mm2, %%mm0\n\t"
"movq %%mm0, %0\n\t"
@@ -163,7 +238,56 @@ static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, u
:: "m" (dstbase[x*2]), "m" (srca[x]), "m" (src[x])
: "%eax");
}
-#else
+#elif HAVE_SSE2
+ __m128i zero = _mm_setzero_si128();
+ __m128i ymask = _mm_set1_epi16(0xff);
+ __m128i uvofs = _mm_set1_epi16(0x8000);
+ for(x=0;x+12<w;x+=16){
+ __m128i mmsrc, mmsrcalo, mmsrcahi, mmdst, mmdst2, mmlow, mmhigh, mmy, mmuv, res;
+ __m128i mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+ int alpha = _mm_movemask_epi8(_mm_cmpeq_epi8(mmsrca, zero));
+ if (alpha == 0xffff) continue;
+
+ mmdst = _mm_loadu_si128((const __m128i *)(dstbase + 2*x));
+ mmdst2 = _mm_loadu_si128((const __m128i *)(dstbase + 2*x + 16));
+
+ // convert UV to signed
+ mmdst = _mm_xor_si128(mmdst, uvofs);
+ mmdst2 = _mm_xor_si128(mmdst2, uvofs);
+
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+ mmsrcalo = _mm_unpacklo_epi8(zero, mmsrca);
+ mmsrcahi = _mm_unpackhi_epi8(zero, mmsrca);
+
+ mmy = muladd_src_unpacked(_mm_and_si128(mmdst, ymask), _mm_and_si128(mmdst2, ymask), mmsrc, mmsrcalo, mmsrcahi);
+
+ // mmuv = ((dst(uv) ^ 128) * (srca * 256)) / 65536 ^ 128 (= (((dst - 128) * srca) >> 8)) + 128
+ mmlow = _mm_srai_epi16(mmdst, 8);
+ mmlow = _mm_mulhi_epi16(mmlow, mmsrcalo);
+ mmhigh = _mm_srai_epi16(mmdst2, 8);
+ mmhigh = _mm_mulhi_epi16(mmhigh, mmsrcahi);
+
+ mmuv = _mm_packs_epi16(mmlow, mmhigh);
+
+ res = _mm_unpacklo_epi8(mmy, mmuv);
+ res = alphamask16(mmdst, res, mmsrcalo);
+ // convert UV to unsigned
+ res = _mm_xor_si128(res, uvofs);
+ _mm_storeu_si128((__m128i *)(dstbase + 2 * x), res);
+
+ res = _mm_unpackhi_epi8(mmy, mmuv);
+ res = alphamask16(mmdst2, res, mmsrcahi);
+ // convert UV to unsigned
+ res = _mm_xor_si128(res, uvofs);
+ _mm_storeu_si128((__m128i *)(dstbase + 2 * x + 16), res);
+ }
+ for(;x<w;x++){
+ if(srca[x]) {
+ dstbase[2*x]=((dstbase[2*x]*srca[x])>>8)+src[x];
+ dstbase[2*x+1]=((((signed)dstbase[2*x+1]-128)*srca[x])>>8)+128;
+ }
+ }
+#else /* HAVE_SSE2 */
for(x=0;x<w;x++){
#ifdef FAST_OSD
if(srca[2*x+0]) dstbase[4*x+0]=src[2*x+0];
@@ -186,6 +310,9 @@ static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, u
return;
}
+#if HAVE_SSE2
+ATTR_TARGET_SSE2
+#endif
static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
int y;
#if defined(FAST_OSD)
@@ -193,6 +320,58 @@ static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, unsigned char* src, u
#endif
for(y=0;y<h;y++){
register int x;
+#if HAVE_SSE2
+ __m128i zero = _mm_setzero_si128();
+ __m128i uvofs = _mm_set1_epi16(0x80);
+ for(x=0;x+12<w;x+=16){
+ __m128i mmsrc, mmsrcalo, mmsrcahi, mmdst, mmdst2, mmlow, mmhigh, mmy, mmuv, res;
+ __m128i mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+ int alpha = _mm_movemask_epi8(_mm_cmpeq_epi8(mmsrca, zero));
+ if (alpha == 0xffff) continue;
+
+ mmdst = _mm_loadu_si128((const __m128i *)(dstbase + 2*x));
+ mmdst2 = _mm_loadu_si128((const __m128i *)(dstbase + 2*x + 16));
+
+ // convert UV to signed
+ mmdst = _mm_xor_si128(mmdst, uvofs);
+ mmdst2 = _mm_xor_si128(mmdst2, uvofs);
+
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+ mmsrcalo = _mm_unpacklo_epi8(zero, mmsrca);
+ mmsrcahi = _mm_unpackhi_epi8(zero, mmsrca);
+
+ mmy = muladd_src_unpacked(_mm_srli_epi16(mmdst, 8), _mm_srli_epi16(mmdst2, 8), mmsrc, mmsrcalo, mmsrcahi);
+
+ // mmuv = ((dst(uv) ^ 128) * (srca * 256)) / 65536 ^ 128 (= (((dst - 128) * srca) >> 8)) + 128
+ // sign-extend and multiply
+ mmlow = _mm_slli_epi16(mmdst, 8);
+ mmlow = _mm_srai_epi16(mmlow, 8);
+ mmlow = _mm_mulhi_epi16(mmlow, mmsrcalo);
+ mmhigh = _mm_slli_epi16(mmdst2, 8);
+ mmhigh = _mm_srai_epi16(mmhigh, 8);
+ mmhigh = _mm_mulhi_epi16(mmhigh, mmsrcahi);
+
+ mmuv = _mm_packs_epi16(mmlow, mmhigh);
+
+ res = _mm_unpacklo_epi8(mmuv, mmy);
+ res = alphamask16(mmdst, res, mmsrcalo);
+ // convert UV to unsigned
+ res = _mm_xor_si128(res, uvofs);
+ _mm_storeu_si128((__m128i *)(dstbase + 2 * x), res);
+
+ res = _mm_unpackhi_epi8(mmuv, mmy);
+ res = alphamask16(mmdst2, res, mmsrcahi);
+ // convert UV to unsigned
+ res = _mm_xor_si128(res, uvofs);
+ _mm_storeu_si128((__m128i *)(dstbase + 2 * x + 16), res);
+ }
+ for(;x<w;x++){
+ if(srca[x]) {
+ dstbase[2*x+1]=((dstbase[2*x+1]*srca[x])>>8)+src[x];
+ dstbase[2*x]=((((signed)dstbase[2*x]-128)*srca[x])>>8)+128;
+ }
+ }
+#else /* HAVE_SSE2 */
for(x=0;x<w;x++){
#ifdef FAST_OSD
if(srca[2*x+0]) dstbase[4*x+2]=src[2*x+0];
@@ -204,12 +383,25 @@ static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, unsigned char* src, u
}
#endif
}
+#endif
src+=srcstride;
srca+=srcstride;
dstbase+=dststride;
}
}
+#define REPL3X(out, sd1, sa1, sd2, sa2, in) \
+do { \
+ __m128i shuf012 = _mm_shufflelo_epi16(in, 0x40); \
+ __m128i shuf345 = _mm_shufflelo_epi16(in, 0xA5); \
+ __m128i repl3x_mmtmp = _mm_unpacklo_epi64(shuf012, shuf345); \
+ repl3x_mmtmp = _mm_and_si128(repl3x_mmtmp, one_in_three_mask); \
+ out = _mm_or_si128(_mm_or_si128(repl3x_mmtmp, _mm_s##sd1##li_si128(repl3x_mmtmp, sa1)), _mm_s##sd2##li_si128(repl3x_mmtmp, sa2)); \
+} while (0)
+
+#if HAVE_SSE2
+ATTR_TARGET_SSE2
+#endif
static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
int y;
#if HAVE_MMX
@@ -221,7 +413,7 @@ static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src,
for(y=0;y<h;y++){
register unsigned char *dst = dstbase;
register int x;
-#if ARCH_X86 && (!ARCH_X86_64 || HAVE_MMX)
+#if ARCH_X86 && (!ARCH_X86_64 || HAVE_MMX || HAVE_SSE2)
#if HAVE_MMX
__asm__ volatile(
PREFETCHW" %0\n\t"
@@ -264,7 +456,62 @@ static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src,
:: "m" (dst[0]), "m" (srca[x]), "m" (src[x]), "m"(mask24hl), "m"(mask24lh));
dst += 6;
}
-#else /* HAVE_MMX */
+#elif HAVE_SSE2
+ __m128i one_in_three_mask = _mm_set_epi32(0xff0000ffu, 0x0000ff00u, 0x00ff0000u, 0xff0000ffu);
+ __m128i zero = _mm_setzero_si128();
+ for(x=0;x+14<w;x+=16){
+ __m128i mmsrc, mmtmp, mmtmpa, mmdst, res;
+ __m128i mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+ int alpha = _mm_movemask_epi8(_mm_cmpeq_epi8(mmsrca, zero));
+ if (alpha == 0xffff) { dst += 48; continue; }
+
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+
+ if ((alpha & 0x3f) != 0x3f) {
+ mmdst = _mm_loadu_si128((const __m128i *)dst);
+ REPL3X(mmtmpa, l, 1, l, 2, mmsrca);
+ REPL3X(mmtmp, l, 1, l, 2, mmsrc);
+ res = muladd_src(mmdst, mmtmp, mmtmpa);
+ res = alphamask(mmdst, res, mmtmpa);
+ _mm_storeu_si128((__m128i *)dst, res);
+ }
+ dst += 16;
+
+ mmsrca = _mm_srli_si128(mmsrca, 5);
+ mmsrc = _mm_srli_si128(mmsrc, 5);
+
+ if ((alpha & 0x7e0) != 0x7e0) {
+ mmdst = _mm_loadu_si128((const __m128i *)dst);
+ REPL3X(mmtmpa, l, 1, r, 1, mmsrca);
+ REPL3X(mmtmp, l, 1, r, 1, mmsrc);
+ res = muladd_src(mmdst, mmtmp, mmtmpa);
+ res = alphamask(mmdst, res, mmtmpa);
+ _mm_storeu_si128((__m128i *)dst, res);
+ }
+ dst += 16;
+
+ mmsrc = _mm_srli_si128(mmsrc, 5);
+ mmsrca = _mm_srli_si128(mmsrca, 5);
+
+ if ((alpha & 0xfc00) != 0xfc00) {
+ mmdst = _mm_loadu_si128((const __m128i *)dst);
+ REPL3X(mmtmpa, r, 1, r, 2, mmsrca);
+ REPL3X(mmtmp, r, 1, r, 2, mmsrc);
+ res = muladd_src(mmdst, mmtmp, mmtmpa);
+ res = alphamask(mmdst, res, mmtmpa);
+ _mm_storeu_si128((__m128i *)dst, res);
+ }
+ dst += 16;
+ }
+ for(;x<w;x++){
+ if(srca[x]){
+ dst[0]=((dst[0]*srca[x])>>8)+src[x];
+ dst[1]=((dst[1]*srca[x])>>8)+src[x];
+ dst[2]=((dst[2]*srca[x])>>8)+src[x];
+ }
+ dst+=3; // 24bpp
+ }
+#else /* HAVE_SSE2 */
for(x=0;x<w;x++){
if(srca[x]){
__asm__ volatile(
@@ -294,7 +541,7 @@ static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src,
dst += 3;
}
#endif /* !HAVE_MMX */
-#else /*non x86 arch or x86_64 with MMX disabled */
+#else /*non x86 arch or x86_64 with MMX and SSE2 disabled */
for(x=0;x<w;x++){
if(srca[x]){
#ifdef FAST_OSD
@@ -318,6 +565,9 @@ static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src,
return;
}
+#if HAVE_SSE2
+ATTR_TARGET_SSE2
+#endif
static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
int y;
#if HAVE_BIGENDIAN
@@ -341,7 +591,7 @@ static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, unsigned char* src,
#endif /* HAVE_MMX */
for(y=0;y<h;y++){
register int x;
-#if ARCH_X86 && (!ARCH_X86_64 || HAVE_MMX)
+#if ARCH_X86 && (!ARCH_X86_64 || HAVE_MMX || HAVE_SSE2)
#if HAVE_MMX
#if HAVE_AMD3DNOW
__asm__ volatile(
@@ -431,7 +681,42 @@ static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, unsigned char* src,
: "%eax");
}
#endif
-#else /* HAVE_MMX */
+#elif HAVE_SSE2
+ __m128i zero = _mm_setzero_si128();
+ __m128i mmsrca = _mm_setzero_si128();
+ for(x=0;x<w;x+=4){
+ __m128i mmsrc, mmdst, mmsrcexp, mmsrcaexp, res;
+ if ((x & 15) == 0) {
+ int alpha;
+ mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+ alpha = _mm_movemask_epi8(_mm_cmpeq_epi8(mmsrca, zero));
+ if (alpha == 0xffff) { x += 12; continue; }
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+ }
+
+ mmdst = _mm_loadu_si128((const __m128i *)(dstbase + 4*x));
+
+ mmsrcaexp = _mm_unpacklo_epi8(mmsrca, mmsrca);
+ mmsrcaexp = _mm_unpacklo_epi8(mmsrcaexp, mmsrcaexp);
+ mmsrcexp = _mm_unpacklo_epi8(mmsrc, mmsrc);
+ mmsrcexp = _mm_unpacklo_epi8(mmsrcexp, mmsrcexp);
+
+ res = muladd_src(mmdst, mmsrcexp, mmsrcaexp);
+
+ res = alphamask(mmdst, res, mmsrcaexp);
+ _mm_storeu_si128((__m128i *)(dstbase + 4*x), res);
+
+ mmsrca = _mm_srli_si128(mmsrca, 4);
+ mmsrc = _mm_srli_si128(mmsrc, 4);
+ }
+ for(;x<w;x++){
+ if(srca[x]){
+ dstbase[4*x+0]=((dstbase[4*x+0]*srca[x])>>8)+src[x];
+ dstbase[4*x+1]=((dstbase[4*x+1]*srca[x])>>8)+src[x];
+ dstbase[4*x+2]=((dstbase[4*x+2]*srca[x])>>8)+src[x];
+ }
+ }
+#else /* HAVE_SSE2 */
for(x=0;x<w;x++){
if(srca[x]){
__asm__ volatile(
diff --git a/sub/sub.c b/sub/sub.c
index 86f7fffad..0d285e134 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -152,7 +152,7 @@ static void alloc_buf(mp_osd_obj_t* obj)
int len;
if (obj->bbox.x2 < obj->bbox.x1) obj->bbox.x2 = obj->bbox.x1;
if (obj->bbox.y2 < obj->bbox.y1) obj->bbox.y2 = obj->bbox.y1;
- obj->stride = ((obj->bbox.x2-obj->bbox.x1)+7)&(~7);
+ obj->stride = ((obj->bbox.x2-obj->bbox.x1)+15)&(~15);
len = obj->stride*(obj->bbox.y2-obj->bbox.y1);
if (obj->allocated<len) {
obj->allocated = len;
--
2.20.1
1
3
Automatically detect 64- vs. 32-bit build
like for other architectures.
Also detect NEON and VFP support correctly.
Lastly, disable inline assembly NEON code
on AARCH64 that only works on 32-bit.
---
configure | 26 ++++++++++++++++++++++----
libaf/af_format.c | 2 +-
libaf/af_volume.c | 2 +-
libmpcodecs/ad_ffmpeg.c | 2 +-
4 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/configure b/configure
index fc04a568a..af54fe83b 100755
--- a/configure
+++ b/configure
@@ -270,9 +270,16 @@ alpha() {
esac
}
+aarch64() {
+ case "$host_arch" in
+ aarch64*) return 0;;
+ *) return 1;;
+ esac
+}
+
arm() {
case "$host_arch" in
- arm*) return 0;;
+ arm*|aarch64*) return 0;;
*) return 1;;
esac
}
@@ -1895,6 +1902,9 @@ fi
if sparc ; then
cc_check && host_arch=sparc64 || host_arch=sparc
fi
+if arm ; then
+ cc_check && host_arch=aarch64 || host_arch=arm
+fi
fi
echo "Detected operating system: $system_name"
@@ -3223,6 +3233,7 @@ if arm ; then
if test $_armvfp = "auto" ; then
_armvfp=no
inline_asm_check '"fadds s0, s0, s0"' && _armvfp=yes
+ inline_asm_check '"fmadd d0, d0, d1, d2"' && _armvfp=yes
fi
echores "$_armvfp"
@@ -3254,9 +3265,15 @@ if arm ; then
if test $neon = "auto" ; then
neon=no
inline_asm_check '"vadd.i16 q0, q0, q0"' && neon=yes
+ inline_asm_check '"ext v0.8B, v0.8B, v1.8B, #1"' && neon=yes
fi
echores "$neon"
+ echocheck "ARM NEON intrinsics"
+ neon_intrinsics=no
+ statement_check "arm_neon.h" "int16x8_t test = vdupq_n_s16(0)" && neon_intrinsics=yes
+ echores "$neon_intrinsics"
+
echocheck "ARM THUMB"
if test $armthumb = "auto" ; then
armthumb=no
@@ -3265,7 +3282,7 @@ if arm ; then
extra_cflags="$extra_cflags -mthumb"
def_armthumb='#define CONFIG_THUMB 1'
else
- extra_cflags="$extra_cflags -marm"
+ aarch64 || extra_cflags="$extra_cflags -marm"
def_armthumb='#define CONFIG_THUMB 0'
fi
echores "$armthumb"
@@ -3278,7 +3295,7 @@ if arm ; then
echores "$_iwmmxt"
fi
-cpuexts_all='ALTIVEC XOP AVX AVX2 AVX512 FMA3 FMA4 MMX MMX2 MMXEXT AMD3DNOW AMD3DNOWEXT SSE SSE2 SSE3 SSSE3 SSE4 SSE42 FAST_CMOV I686 FAST_CLZ ARMV5TE ARMV6 ARMV6T2 VFP VFPV3 SETEND NEON IWMMXT MMI VIS MVI'
+cpuexts_all='ALTIVEC XOP AVX AVX2 AVX512 FMA3 FMA4 MMX MMX2 MMXEXT AMD3DNOW AMD3DNOWEXT SSE SSE2 SSE3 SSSE3 SSE4 SSE42 FAST_CMOV I686 FAST_CLZ ARMV5TE ARMV6 ARMV6T2 VFP VFPV3 SETEND NEON INTRINSICS_NEON IWMMXT MMI VIS MVI'
test "$_altivec" = yes && cpuexts="ALTIVEC $cpuexts"
test "$_mmx" = yes && cpuexts="MMX $cpuexts"
test "$_mmxext" = yes && cpuexts="MMX2 $cpuexts"
@@ -3307,6 +3324,7 @@ test "$_armvfp" = yes && cpuexts="VFP $cpuexts"
test "$vfpv3" = yes && cpuexts="VFPV3 $cpuexts"
test "$setend" = yes && cpuexts="SETEND $cpuexts"
test "$neon" = yes && cpuexts="NEON $cpuexts"
+test "$neon_intrinsics" = yes && cpuexts="INTRINSICS_NEON $cpuexts"
test "$_iwmmxt" = yes && cpuexts="IWMMXT $cpuexts"
test "$_vis" = yes && cpuexts="VIS $cpuexts"
test "$_mvi" = yes && cpuexts="MVI $cpuexts"
@@ -8987,6 +9005,7 @@ $(ff_config_enable "$cpuexts_all" "$cpuexts" "#" "HAVE")
$(ff_config_enable "$cpuexts_all" "$cpuexts_external" "#" "HAVE" "_EXTERNAL")
$(ff_config_enable "$cpuexts_all" "$cpuexts" "#" "HAVE" "_INLINE")
+#define HAVE_ARMV8 ARCH_AARCH64
/* Blu-ray/DVD/VCD/CD */
#define DEFAULT_CDROM_DEVICE "$default_cdrom_device"
@@ -9340,7 +9359,6 @@ $def_openssl
#define HAVE_INLINE_ASM 1
#define HAVE_INLINE_ASM_NONLOCAL_LABELS 1
#define HAVE_INLINE_ASM_DIRECT_SYMBOL_REFS 1
-#define HAVE_INTRINSICS_NEON 0
#define HAVE_ISATTY 0
#define HAVE_LDBRX 0
#define HAVE_LIBC_MSVCRT 0
diff --git a/libaf/af_format.c b/libaf/af_format.c
index 94109807b..46b6e1d93 100644
--- a/libaf/af_format.c
+++ b/libaf/af_format.c
@@ -494,7 +494,7 @@ static void float2int(const float* in, void* out, int len, int bps)
((int8_t *)out)[i] = av_clip_int8(lrintf(128.0f * in[i]));
break;
case(2):
-#if HAVE_NEON
+#if HAVE_NEON && !ARCH_AARCH64
{
const float *in_end = in + len;
while (in < in_end - 7) {
diff --git a/libaf/af_volume.c b/libaf/af_volume.c
index 0690d58cc..e79aa25f8 100644
--- a/libaf/af_volume.c
+++ b/libaf/af_volume.c
@@ -125,7 +125,7 @@ static av_always_inline void s16_inner_loop(int16_t *data, int len, int offset,
static av_always_inline void float_inner_loop(float *data, int len, int offset, int step, float level, int softclip)
{
int i;
-#if HAVE_NEON
+#if HAVE_NEON && !ARCH_AARCH64
if (offset == 0 && step == 1 && !softclip && len >= 8)
{
__asm__(
diff --git a/libmpcodecs/ad_ffmpeg.c b/libmpcodecs/ad_ffmpeg.c
index ff78a4252..456be5dc9 100644
--- a/libmpcodecs/ad_ffmpeg.c
+++ b/libmpcodecs/ad_ffmpeg.c
@@ -223,7 +223,7 @@ static av_always_inline void copy_samples_planar(size_t bps,
{
size_t s, c, o = 0;
-#if HAVE_NEON_INLINE
+#if HAVE_NEON_INLINE && !ARCH_AARCH64
if (nb_channels == 2 && bps == 4) {
const unsigned char *src0 = src[0];
const unsigned char *src1 = src[1];
--
2.20.1
1
1
The values are only "double", and "long double"
on x86 forces the use of x87 instructions which
are less efficient.
Also "long double" is not available on other
architectures.
---
libmpdemux/demux_mkv.c | 10 +++++-----
libmpdemux/ebml.c | 4 ++--
libmpdemux/ebml.h | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c
index e6d90985d..a50c7a612 100644
--- a/libmpdemux/demux_mkv.c
+++ b/libmpdemux/demux_mkv.c
@@ -402,7 +402,7 @@ static int demux_mkv_read_info(demuxer_t *demuxer)
uint64_t length, l;
int il;
uint64_t tc_scale = 1000000;
- long double duration = 0.;
+ double duration = 0.;
length = ebml_read_length(s, NULL);
while (length > 0) {
@@ -420,11 +420,11 @@ static int demux_mkv_read_info(demuxer_t *demuxer)
case MATROSKA_ID_DURATION:
{
- long double num = ebml_read_float(s, &l);
+ double num = ebml_read_float(s, &l);
if (num == EBML_FLOAT_INVALID)
return 1;
duration = num;
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n",
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n",
duration * tc_scale / 1000000000.0);
break;
}
@@ -615,7 +615,7 @@ static int demux_mkv_read_trackaudio(demuxer_t *demuxer, mkv_track_t *track)
switch (ebml_read_id(s, &il)) {
case MATROSKA_ID_AUDIOSAMPLINGFREQ:
{
- long double num = ebml_read_float(s, &l);
+ double num = ebml_read_float(s, &l);
if (num == EBML_FLOAT_INVALID)
return 0;
track->a_sfreq = num;
@@ -667,7 +667,7 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track)
switch (ebml_read_id(s, &il)) {
case MATROSKA_ID_VIDEOFRAMERATE:
{
- long double num = ebml_read_float(s, &l);
+ double num = ebml_read_float(s, &l);
if (num == EBML_FLOAT_INVALID)
return 0;
track->v_frate = num;
diff --git a/libmpdemux/ebml.c b/libmpdemux/ebml.c
index e35ded948..858811d37 100644
--- a/libmpdemux/ebml.c
+++ b/libmpdemux/ebml.c
@@ -176,9 +176,9 @@ int64_t ebml_read_int(stream_t *s, uint64_t *length)
/*
* Read the next element as a float.
*/
-long double ebml_read_float(stream_t *s, uint64_t *length)
+double ebml_read_float(stream_t *s, uint64_t *length)
{
- long double value;
+ double value;
uint64_t len;
int l;
diff --git a/libmpdemux/ebml.h b/libmpdemux/ebml.h
index fb44faa43..6ecbd1be9 100644
--- a/libmpdemux/ebml.h
+++ b/libmpdemux/ebml.h
@@ -200,7 +200,7 @@ int64_t ebml_read_vlen_int (uint8_t *buffer, int *length);
uint64_t ebml_read_length (stream_t *s, int *length);
uint64_t ebml_read_uint (stream_t *s, uint64_t *length);
int64_t ebml_read_int (stream_t *s, uint64_t *length);
-long double ebml_read_float (stream_t *s, uint64_t *length);
+double ebml_read_float (stream_t *s, uint64_t *length);
char *ebml_read_ascii (stream_t *s, uint64_t *length);
char *ebml_read_utf8 (stream_t *s, uint64_t *length);
int ebml_read_skip (stream_t *s, uint64_t *length);
--
2.20.1
2
2
Unfinished.
In particular, more functions are missing and
intrinsic support needs to be auto-detected.
Intrinsics are not well liked for good reason,
but it is much faster to implement and compilers
are no longer completely horrible for x86.
Speed is about 2x and it matches the C code instead
of the less accurate MMX code.
Primary motivation is though that MMX is starting to
have worse and worse support in CPUs.
To benchmark, use this command and remove the reading code
from rawvideo and the memcpy_pic from vf_expand.
./mplayer /dev/zero -demuxer rawvideo -rawvideo w=1920:h=1080:format=yuy2 -vo null -osdlevel 3 -benchmark -quiet -frames 50000 -vf expand=osd=1 -subfont-osd-scale 20
---
sub/osd.c | 83 +++++++++++++++++++++++++++++++--------
sub/osd_template.c | 96 +++++++++++++++++++++++++++++++++++++++++++++-
sub/sub.c | 2 +-
3 files changed, 162 insertions(+), 19 deletions(-)
diff --git a/sub/osd.c b/sub/osd.c
index a2d002526..14906eca9 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -31,40 +31,46 @@
#include "libmpcodecs/img_format.h"
#include "cpudetect.h"
-#if ARCH_X86
+//#if ARCH_X86 && (!HAVE_SSE2 || CONFIG_RUNTIME_CPUDETECT)
static const uint64_t bFF __attribute__((aligned(8))) = 0xFFFFFFFFFFFFFFFFULL;
static const unsigned long long mask24lh __attribute__((aligned(8))) = 0xFFFF000000000000ULL;
static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FFFFFFFFFFFFULL;
-#endif
+//#endif
//Note: we have C, X86-nommx, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
//Plain C versions
-#if !HAVE_MMX || CONFIG_RUNTIME_CPUDETECT
+#if (!HAVE_MMX && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_C
#endif
#if ARCH_X86
-#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
+#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2 && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_MMX
#endif
-#if HAVE_MMX2 || CONFIG_RUNTIME_CPUDETECT
+#if (HAVE_MMX2 && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_MMX2
#endif
-#if (HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
+#if (HAVE_AMD3DNOW && !HAVE_MMX2 && !HAVE_SSE2) || CONFIG_RUNTIME_CPUDETECT
#define COMPILE_3DNOW
#endif
+#if HAVE_SSE2 || CONFIG_RUNTIME_CPUDETECT
+#define COMPILE_SSE2
+#endif
+
#endif /* ARCH_X86 */
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 0
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#if ! ARCH_X86
@@ -72,9 +78,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 0
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _C
#include "osd_template.c"
#endif
@@ -87,9 +95,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 0
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _X86
#include "osd_template.c"
#endif
@@ -100,9 +110,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 1
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _MMX
#include "osd_template.c"
#endif
@@ -113,9 +125,11 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 1
#define HAVE_MMX2 1
#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 0
#define RENAME(a) a ## _MMX2
#include "osd_template.c"
#endif
@@ -126,20 +140,39 @@ static const unsigned long long mask24hl __attribute__((aligned(8))) = 0x0000FF
#undef HAVE_MMX
#undef HAVE_MMX2
#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
#define HAVE_MMX 1
#define HAVE_MMX2 0
#define HAVE_AMD3DNOW 1
+#define HAVE_SSE2 0
#define RENAME(a) a ## _3DNow
#include "osd_template.c"
#endif
+//SSE2 versions
+#ifdef COMPILE_SSE2
+#undef RENAME
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_AMD3DNOW
+#undef HAVE_SSE2
+#define HAVE_MMX 0
+#define HAVE_MMX2 0
+#define HAVE_AMD3DNOW 0
+#define HAVE_SSE2 1
+#define RENAME(a) a ## _SSE2
+#include <emmintrin.h>
+#include "osd_template.c"
+#endif
#endif /* ARCH_X86 */
void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(gCpuCaps.hasSSE2)
+ vo_draw_alpha_yv12_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -151,7 +184,9 @@ void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, in
vo_draw_alpha_yv12_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_yv12_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -169,7 +204,9 @@ void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, in
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(gCpuCaps.hasSSE2)
+ vo_draw_alpha_yuy2_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -181,7 +218,9 @@ void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, in
vo_draw_alpha_yuy2_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_yuy2_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -199,7 +238,9 @@ void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, in
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(gCpuCaps.hasSSE2)
+ vo_draw_alpha_uyvy_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -211,7 +252,9 @@ void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, in
vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_uyvy_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -229,7 +272,9 @@ void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, i
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(gCpuCaps.hasSSE2)
+ vo_draw_alpha_rgb24_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -241,7 +286,9 @@ void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, i
vo_draw_alpha_rgb24_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_rgb24_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -259,7 +306,9 @@ void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, i
#if CONFIG_RUNTIME_CPUDETECT
#if ARCH_X86
// ordered by speed / fastest first
- if(gCpuCaps.hasMMX2)
+ if(gCpuCaps.hasSSE2)
+ vo_draw_alpha_rgb32_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+ else if(gCpuCaps.hasMMX2)
vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
else if(gCpuCaps.has3DNow)
vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
@@ -271,7 +320,9 @@ void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, i
vo_draw_alpha_rgb32_C(w, h, src, srca, srcstride, dstbase, dststride);
#endif
#else //CONFIG_RUNTIME_CPUDETECT
-#if HAVE_MMX2
+#if HAVE_SSE2
+ vo_draw_alpha_rgb32_SSE2(w, h, src, srca, srcstride, dstbase, dststride);
+#elif HAVE_MMX2
vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
#elif HAVE_AMD3DNOW
vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
diff --git a/sub/osd_template.c b/sub/osd_template.c
index 6d8305a3c..9ef2ada46 100644
--- a/sub/osd_template.c
+++ b/sub/osd_template.c
@@ -24,6 +24,9 @@
#undef PREFETCHW
#undef PAVGB
+//#define HAVE_MMX 1
+//#define HAVE_MMX2 1
+
#if HAVE_AMD3DNOW
#define PREFETCH "prefetch"
#define PREFETCHW "prefetchw"
@@ -46,7 +49,7 @@
static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
int y;
-#if defined(FAST_OSD) && !HAVE_MMX
+#if defined(FAST_OSD) && !HAVE_MMX && !HAVE_SSE2
w=w>>1;
#endif
#if HAVE_MMX
@@ -94,6 +97,34 @@ static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, u
:: "m" (dstbase[x]), "m" (srca[x]), "m" (src[x])
: "%eax");
}
+#elif HAVE_SSE2
+ __m128i zero = _mm_set1_epi8(0);
+ for(x=0;x+8<w;x+=16){
+ __m128i mmsrc, mmsrca, mmdst, mmlow, mmhigh, premult, res, mask;
+ mmdst = _mm_loadu_si128((const __m128i *)(dstbase + x));
+ mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+
+ // (mmhigh,mmlow) = (dst * (srca * 256)) / 65536 (= (dst * srca) >> 8)
+ mmlow = _mm_mulhi_epu16(_mm_unpacklo_epi8(mmdst, zero), _mm_unpacklo_epi8(zero, mmsrca));
+ mmhigh = _mm_mulhi_epu16(_mm_unpackhi_epi8(mmdst, zero), _mm_unpackhi_epi8(zero, mmsrca));
+
+ premult = _mm_packus_epi16(mmlow, mmhigh);
+
+ // += src
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+ res = _mm_add_epi8(premult, mmsrc);
+
+ // if (!srca) res |= dst --- assumes srca == 0 implies src == 0,
+ // thus no need to mask res
+ // _mm_maskmoveu_s128 would be an alternative but slower
+ mask = _mm_cmpeq_epi8(mmsrca, zero);
+ mmdst = _mm_and_si128(mmdst, mask);
+ res = _mm_or_si128(res, mmdst);
+ _mm_storeu_si128((__m128i *)(dstbase + x), res);
+ }
+ for(;x<w;x++){
+ if(srca[x]) dstbase[x]=((dstbase[x]*srca[x])>>8)+src[x];
+ }
#else
for(x=0;x<w;x++){
#ifdef FAST_OSD
@@ -155,7 +186,7 @@ static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, u
"psrlw $8, %%mm0\n\t"
"pand %%mm5, %%mm1\n\t" //U0V0U0V0
"movd %2, %%mm2\n\t" //src 0000DCBA
- "punpcklbw %%mm7, %%mm2\n\t" //srca 0D0C0B0A
+ "punpcklbw %%mm7, %%mm2\n\t" //src 0D0C0B0A
"por %%mm1, %%mm0\n\t"
"paddb %%mm2, %%mm0\n\t"
"movq %%mm0, %0\n\t"
@@ -163,6 +194,67 @@ static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, u
:: "m" (dstbase[x*2]), "m" (srca[x]), "m" (src[x])
: "%eax");
}
+#elif HAVE_SSE2
+ __m128i zero = _mm_set1_epi8(0);
+ __m128i ymask = _mm_set1_epi16(0xff);
+ __m128i uvofs = _mm_set1_epi16(0x8000);
+ for(x=0;x+12<w;x+=16){
+ __m128i mmsrc, mmsrca, mmsrcalo, mmsrcahi, mmdst, mmdst2, mmlow, mmhigh, mmy, mmuv, premult, res, mask;
+ mmdst = _mm_loadu_si128((const __m128i *)(dstbase + 2*x));
+ mmdst2 = _mm_loadu_si128((const __m128i *)(dstbase + 2*x + 8));
+
+ // convert UV to signed
+ mmdst = _mm_xor_si128(mmdst, uvofs);
+ mmdst2 = _mm_xor_si128(mmdst2, uvofs);
+
+ mmsrca = _mm_load_si128((const __m128i *)(srca + x));
+ mmsrcalo = _mm_unpacklo_epi8(zero, mmsrca);
+ mmsrcahi = _mm_unpackhi_epi8(zero, mmsrca);
+
+ // (mmhigh,mmlow) = (dst(y) * (srca * 256)) / 65536 (= (dst * srca) >> 8)
+ mmlow = _mm_mulhi_epu16(_mm_and_si128(mmdst, ymask), mmsrcalo);
+ mmhigh = _mm_mulhi_epu16(_mm_and_si128(mmdst2, ymask), mmsrcahi);
+
+ mmy = _mm_packus_epi16(mmlow, mmhigh);
+
+ // += src
+ mmsrc = _mm_load_si128((const __m128i *)(src + x));
+ mmy = _mm_add_epi8(mmy, mmsrc);
+
+ // mmuv = ((dst(uv) ^ 128) * (srca * 256)) / 65536 ^ 128 (= (((dst - 128) * srca) >> 8)) + 128
+ mmlow = _mm_srai_epi16(mmdst, 8);
+ mmlow = _mm_mulhi_epi16(mmlow, mmsrcalo);
+ mmhigh = _mm_srai_epi16(mmdst2, 8);
+ mmhigh = _mm_mulhi_epi16(mmhigh, mmsrcahi);
+
+ mmuv = _mm_packs_epi16(mmlow, mmhigh);
+
+ // if (!srca) res |= dst --- assumes srca == 0 implies src == 0,
+ // thus no need to mask mmy.
+ // Since mmuv is still signed the same applies to it.
+ // _mm_maskmoveu_s128 would be an alternative but slower
+ mask = _mm_cmpeq_epi16(mmsrcalo, zero);
+ mmdst = _mm_and_si128(mmdst, mask);
+ res = _mm_unpacklo_epi8(mmy, mmuv);
+ res = _mm_or_si128(res, mmdst);
+ // convert UV to unsigned
+ res = _mm_xor_si128(res, uvofs);
+ _mm_storeu_si128((__m128i *)(dstbase + 2 * x), res);
+
+ mask = _mm_cmpeq_epi16(mmsrcahi, zero);
+ mmdst2 = _mm_and_si128(mmdst2, mask);
+ res = _mm_unpackhi_epi8(mmy, mmuv);
+ res = _mm_or_si128(res, mmdst2);
+ // convert UV to unsigned
+ res = _mm_xor_si128(res, uvofs);
+ _mm_storeu_si128((__m128i *)(dstbase + 2 * x + 8), res);
+ }
+ for(;x<w;x++){
+ if(srca[x]) {
+ dstbase[2*x]=((dstbase[2*x]*srca[x])>>8)+src[x];
+ dstbase[2*x+1]=((((signed)dstbase[2*x+1]-128)*srca[x])>>8)+128;
+ }
+ }
#else
for(x=0;x<w;x++){
#ifdef FAST_OSD
diff --git a/sub/sub.c b/sub/sub.c
index 86f7fffad..0d285e134 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -152,7 +152,7 @@ static void alloc_buf(mp_osd_obj_t* obj)
int len;
if (obj->bbox.x2 < obj->bbox.x1) obj->bbox.x2 = obj->bbox.x1;
if (obj->bbox.y2 < obj->bbox.y1) obj->bbox.y2 = obj->bbox.y1;
- obj->stride = ((obj->bbox.x2-obj->bbox.x1)+7)&(~7);
+ obj->stride = ((obj->bbox.x2-obj->bbox.x1)+15)&(~15);
len = obj->stride*(obj->bbox.y2-obj->bbox.y1);
if (obj->allocated<len) {
obj->allocated = len;
--
2.20.1
1
3