0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

Merge remote-tracking branch 'origin/master'

Conflicts:
	bstr.c
	bstr.h
	libvo/cocoa_common.m
	libvo/gl_common.c
	libvo/video_out.c
	mplayer.c
	screenshot.c
	sub/subassconvert.c

Merge of cocoa_common.m done by pigoz.

Picking my version of screenshot.c. The fix in commit aadf1002f8 will
be redone in a follow-up commit, as the original commit causes too many
conflicts with the work done locally in this branch, and other work in
progress.
This commit is contained in:
wm4 2012-04-29 07:16:09 +02:00
commit 97ac824124
21 changed files with 1244 additions and 1296 deletions

View File

@ -100,6 +100,9 @@ SRCS_COMMON-$(LIVE555) += libmpdemux/demux_rtp.cpp \
libmpdemux/demux_rtp_codec.cpp \
stream/stream_live555.c
SRCS_COMMON-$(MACOSX_FINDER) += osdep/macosx_finder_args.m
SRCS_COMMON-$(COCOA) += libvo/osx_common.c \
libvo/cocoa_common.m \
osdep/cocoa_events.m
SRCS_COMMON-$(MNG) += libmpdemux/demux_mng.c
SRCS_COMMON-$(MPG123) += libmpcodecs/ad_mpg123.c
@ -439,7 +442,8 @@ SRCS_MPLAYER-$(ARTS) += libao2/ao_arts.c
SRCS_MPLAYER-$(BL) += libvo/vo_bl.c
SRCS_MPLAYER-$(CACA) += libvo/vo_caca.c
SRCS_MPLAYER-$(COREAUDIO) += libao2/ao_coreaudio.c
SRCS_MPLAYER-$(COREVIDEO) += libvo/vo_corevideo.m libvo/osx_common.c
SRCS_MPLAYER-$(COREVIDEO) += libvo/vo_corevideo.m
SRCS_MPLAYER-$(SHAREDBUFFER) += libvo/vo_sharedbuffer.m
SRCS_MPLAYER-$(DGA) += libvo/vo_dga.c
SRCS_MPLAYER-$(DIRECT3D) += libvo/vo_direct3d.c libvo/w32_common.c
SRCS_MPLAYER-$(DIRECTFB) += libvo/vo_directfb2.c libvo/vo_dfbmga.c
@ -451,7 +455,6 @@ SRCS_MPLAYER-$(GGI) += libvo/vo_ggi.c
SRCS_MPLAYER-$(GIF) += libvo/vo_gif89a.c
SRCS_MPLAYER-$(GL) += libvo/gl_common.c libvo/vo_gl.c libvo/vo_gl3.c \
pnm_loader.c
SRCS_MPLAYER-$(GL_COCOA) += libvo/cocoa_common.m
SRCS_MPLAYER-$(GL_SDL) += libvo/sdl_common.c
SRCS_MPLAYER-$(GL_WIN32) += libvo/w32_common.c
SRCS_MPLAYER-$(GL_X11) += libvo/x11_common.c

View File

@ -112,6 +112,7 @@ void init_libav(void)
av_log_set_callback(mp_msg_av_log_callback);
avcodec_register_all();
av_register_all();
avformat_network_init();
}
#define V(x) (x)>>16, (x)>>8 & 255, (x) & 255

1
bstr.h
View File

@ -96,7 +96,6 @@ bool bstr_case_endswith(struct bstr s, struct bstr suffix);
struct bstr bstr_strip_ext(struct bstr str);
struct bstr bstr_get_ext(struct bstr s);
static inline struct bstr bstr_cut(struct bstr str, int n)
{
if (n < 0) {

187
configure vendored
View File

@ -435,6 +435,7 @@ Video output:
--disable-yuv4mpeg disable yuv4mpeg video output [enable]
--disable-corevideo disable CoreVideo video output [autodetect]
--disable-cocoa disable Cocoa OpenGL backend [autodetect]
--disable-sharedbuffer disable OSX shared buffer video output [autodetect]
Audio output:
--disable-alsa disable ALSA audio output [autodetect]
@ -692,6 +693,7 @@ _qtx=auto
_coreaudio=auto
_corevideo=auto
_cocoa=auto
_sharedbuffer=auto
quicktime=auto
_macosx_finder=no
_macosx_bundle=auto
@ -1121,6 +1123,8 @@ for ac_option do
--disable-corevideo) _corevideo=no ;;
--enable-cocoa) _cocoa=yes ;;
--disable-cocoa) _cocoa=no ;;
--enable-sharedbuffer) _sharedbuffer=yes ;;
--disable-sharedbuffer) _sharedbuffer=no ;;
--enable-macosx-finder) _macosx_finder=yes ;;
--disable-macosx-finder) _macosx_finder=no ;;
--enable-macosx-bundle) _macosx_bundle=yes ;;
@ -2311,23 +2315,22 @@ fi # if darwin && test "$cc_vendor" = "gnu" ; then
# Checking for CFLAGS
_install_strip="-s"
if test "$_profile" != "" || test "$_debug" != "" ; then
CFLAGS="-O2 $_march $_mcpu $_pipe $_debug $_profile"
WARNFLAGS="-W -Wall"
_install_strip=
elif test -z "$CFLAGS" ; then
fi
if test -z "$CFLAGS" ; then
if test "$cc_vendor" = "intel" ; then
CFLAGS="-O2 $_march $_mcpu $_pipe -fomit-frame-pointer"
CFLAGS="-O2 $_debug $_profile $_march $_mcpu $_pipe -fomit-frame-pointer"
WARNFLAGS="-wd167 -wd556 -wd144"
elif test "$cc_vendor" = "sun" ; then
CFLAGS="-O2 $_march $_mcpu $_pipe -xc99 -xregs=frameptr"
CFLAGS="-O2 $_debug $_profile $_march $_mcpu $_pipe -xc99 -xregs=frameptr"
elif test "$cc_vendor" = "clang"; then
CFLAGS="-O2 $_march $_pipe"
CFLAGS="-O2 $_debug $_profile $_march $_pipe"
WARNFLAGS="-Wall -Wno-switch-enum -Wno-logical-op-parentheses -Wpointer-arith -Wundef -Wno-pointer-sign -Wmissing-prototypes"
ERRORFLAGS="-Werror=implicit-function-declaration"
elif test "$cc_vendor" != "gnu" ; then
CFLAGS="-O2 $_march $_mcpu $_pipe"
CFLAGS="-O2 $_debug $_profile $_march $_mcpu $_pipe"
else
CFLAGS="-O2 $_march $_mcpu $_pipe -ffast-math -fomit-frame-pointer"
CFLAGS="-O2 $_debug $_profile $_march $_mcpu $_pipe -ffast-math -fomit-frame-pointer"
WARNFLAGS="-Wall -Wno-switch -Wno-parentheses -Wpointer-arith -Wredundant-decls"
ERRORFLAGS="-Werror-implicit-function-declaration"
extra_ldflags="$extra_ldflags -ffast-math"
@ -3794,6 +3797,87 @@ fi
echores "$_directfb"
if darwin; then
echocheck "QuickTime"
if test "$quicktime" = auto ; then
quicktime=no
statement_check QuickTime/QuickTime.h 'ImageDescription *desc; EnterMovies(); ExitMovies()' -framework QuickTime && quicktime=yes
fi
if test "$quicktime" = yes ; then
extra_ldflags="$extra_ldflags -framework QuickTime"
def_quicktime='#define CONFIG_QUICKTIME 1'
else
def_quicktime='#undef CONFIG_QUICKTIME'
fi
echores $quicktime
echocheck "Cocoa"
if test "$_cocoa" = auto ; then
cat > $TMPC <<EOF
#include <CoreServices/CoreServices.h>
#include <OpenGL/OpenGL.h>
int main(void) {
NSApplicationLoad();
}
EOF
_cocoa=no
cc_check -framework Cocoa -framework OpenGL && _cocoa=yes
fi
if test "$_cocoa" = yes ; then
libs_mplayer="$libs_mplayer -framework Cocoa -framework OpenGL"
def_cocoa='#define CONFIG_COCOA 1'
else
def_cocoa='#undef CONFIG_COCOA'
fi
echores "$_cocoa"
echocheck "CoreVideo"
if test "$_cocoa" = yes && test "$_corevideo" = auto ; then
cat > $TMPC <<EOF
#include <QuartzCore/CoreVideo.h>
int main(void) { return 0; }
EOF
_corevideo=no
cc_check -framework Cocoa -framework QuartzCore -framework OpenGL && _corevideo=yes
fi
if test "$_corevideo" = yes ; then
vomodules="corevideo $vomodules"
libs_mplayer="$libs_mplayer -framework QuartzCore"
def_corevideo='#define CONFIG_COREVIDEO 1'
else
novomodules="corevideo $novomodules"
def_corevideo='#undef CONFIG_COREVIDEO'
fi
echores "$_corevideo"
echocheck "SharedBuffer"
if test "$_sharedbuffer" = auto ; then
cat > $TMPC <<EOF
int main(void) {
NSApplicationLoad();
}
EOF
_sharedbuffer=no
cc_check -framework Cocoa && _sharedbuffer=yes
fi
if test "$_sharedbuffer" = yes ; then
vomodules="sharedbuffer $vomodules"
libs_mplayer="$libs_mplayer -framework Cocoa"
def_sharedbuffer='#define CONFIG_SHAREDBUFFER 1'
else
novomodules="sharedbuffer $novomodules"
def_sharedbuffer='#undef CONFIG_SHAREDBUFFER'
fi
echores "$_sharedbuffer"
depends_on_application_services(){
test "$_corevideo" = yes
}
fi #if darwin
echocheck "X11 headers presence"
_x11_headers="no"
res_comment="check if the dev(el) packages are installed"
@ -3829,7 +3913,20 @@ if test "$_x11" = auto && test "$_x11_headers" = yes ; then
_ld_tmp="$I -lXext -lX11 $_ld_pthread"
fi
statement_check X11/Xutil.h 'XCreateWindow(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)' $_ld_tmp &&
libs_mplayer="$libs_mplayer $_ld_tmp" && _x11=yes && break
_x11=yes
# Check that there aren't conflicting headers between ApplicationServices
# and X11. On versions of Mac OSX prior to 10.7 the deprecated QuickDraw API
# is included by -framework ApplicationServices and clashes with the X11
# definition of the "Cursor" type.
if darwin && depends_on_application_services && test "$_x11" = yes ; then
_x11=no
header_check_broken ApplicationServices/ApplicationServices.h \
X11/Xutil.h $_ld_tmp && _x11=yes
fi
if test "$_x11" = yes ; then
libs_mplayer="$libs_mplayer $_ld_tmp"
break
fi
done
fi
if test "$_x11" = yes ; then
@ -4174,66 +4271,6 @@ else
fi
if darwin; then
echocheck "QuickTime"
if test "$quicktime" = auto ; then
quicktime=no
statement_check QuickTime/QuickTime.h 'ImageDescription *desc; EnterMovies(); ExitMovies()' -framework QuickTime && quicktime=yes
fi
if test "$quicktime" = yes ; then
extra_ldflags="$extra_ldflags -framework QuickTime"
def_quicktime='#define CONFIG_QUICKTIME 1'
else
def_quicktime='#undef CONFIG_QUICKTIME'
fi
echores $quicktime
echocheck "CoreVideo"
if test "$_corevideo" = auto ; then
cat > $TMPC <<EOF
#include <Carbon/Carbon.h>
#include <CoreServices/CoreServices.h>
#include <OpenGL/OpenGL.h>
#include <QuartzCore/CoreVideo.h>
int main(void) { return 0; }
EOF
_corevideo=no
cc_check -framework Carbon -framework Cocoa -framework QuartzCore -framework OpenGL && _corevideo=yes
fi
if test "$_corevideo" = yes ; then
vomodules="corevideo $vomodules"
libs_mplayer="$libs_mplayer -framework Carbon -framework Cocoa -framework QuartzCore -framework OpenGL"
def_corevideo='#define CONFIG_COREVIDEO 1'
else
novomodules="corevideo $novomodules"
def_corevideo='#undef CONFIG_COREVIDEO'
fi
echores "$_corevideo"
echocheck "Cocoa"
if test "$_gl" = no ; then
# if _gl is not enabled there is no point to add potentially unused linker flags
_cocoa=no
fi
if test "$_cocoa" = auto ; then
cat > $TMPC <<EOF
#include <CoreServices/CoreServices.h>
#include <OpenGL/OpenGL.h>
#include <QuartzCore/CoreVideo.h>
int main(void) { return 0; }
EOF
_cocoa=no
cc_check -framework Cocoa -framework QuartzCore -framework OpenGL && _cocoa=yes
fi
if test "$_cocoa" = yes ; then
libs_mplayer="$libs_mplayer -framework Cocoa -framework QuartzCore -framework OpenGL"
fi
echores "$_cocoa"
fi #if darwin
echocheck "PNG support"
if test "$_png" = auto ; then
_png=no
@ -4525,7 +4562,7 @@ int main(int argc, char *argv[]) {
EOF
_gl=no
for _ld_tmp in "" -lGL "-lGL -lXdamage" "-lGL $_ld_pthread" ; do
if test "$_cocoa" != yes && cc_check $_ld_tmp $_ld_lm ; then
if cc_check $_ld_tmp $_ld_lm ; then
_gl=yes
_gl_x11=yes
libs_mplayer="$libs_mplayer $_ld_tmp $_ld_dl"
@ -6349,8 +6386,10 @@ BL = $_bl
CACA = $_caca
CDDA = $_cdda
CDDB = $_cddb
COCOA = $_cocoa
COREAUDIO = $_coreaudio
COREVIDEO = $_corevideo
SHAREDBUFFER = $_sharedbuffer
DGA = $_dga
DIRECT3D = $_direct3d
DIRECTFB = $_directfb
@ -6752,6 +6791,8 @@ $def_aa
$def_bl
$def_caca
$def_corevideo
$def_cocoa
$def_sharedbuffer
$def_dga
$def_dga1
$def_dga2
@ -6829,12 +6870,8 @@ $def_yasm
#define HAVE_INLINE_ASM 1
/* Use these registers in FFmpeg x86 inline asm. No proper detection yet. */
#ifndef MP_DEBUG
/* Use these registers in x86 inline asm. No proper detection yet. */
#define HAVE_EBP_AVAILABLE 1
#else
#define HAVE_EBP_AVAILABLE 0
#endif
#endif /* MPLAYER_CONFIG_H */
EOF

View File

@ -59,6 +59,10 @@
#include "ar.h"
#ifdef CONFIG_COCOA
#include "osdep/cocoa_events.h"
#endif
#define MP_MAX_KEY_DOWN 32
struct cmd_bind {
@ -1454,7 +1458,7 @@ static void read_events(struct input_ctx *ictx, int time)
* every source until it's known to be empty. Instead we use this wrapper
* to run select() again.
*/
static void read_all_events(struct input_ctx *ictx, int time)
static void read_all_fd_events(struct input_ctx *ictx, int time)
{
while (1) {
read_events(ictx, time);
@ -1464,6 +1468,15 @@ static void read_all_events(struct input_ctx *ictx, int time)
}
}
static void read_all_events(struct input_ctx *ictx, int time)
{
#ifdef CONFIG_COCOA
cocoa_events_read_all_events(ictx, time);
#else
read_all_fd_events(ictx, time);
#endif
}
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
{
ictx->got_new_events = true;
@ -1761,6 +1774,10 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf)
.wakeup_pipe = {-1, -1},
};
#ifdef CONFIG_COCOA
cocoa_events_init(ictx, read_all_fd_events);
#endif
#ifndef __MINGW32__
long ret = pipe(ictx->wakeup_pipe);
for (int i = 0; i < 2 && ret >= 0; i++) {
@ -1866,11 +1883,16 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf)
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Can't open %s: %s\n",
input_conf->in_file, strerror(errno));
}
return ictx;
}
void mp_input_uninit(struct input_ctx *ictx)
{
#ifdef CONFIG_COCOA
cocoa_events_uninit();
#endif
if (!ictx)
return;

View File

@ -49,12 +49,15 @@ LIBAD_EXTERN(ffmpeg)
struct priv {
AVCodecContext *avctx;
int previous_data_left;
AVFrame *avframe;
char *output;
int output_left;
int unitsize;
int previous_data_left; // input demuxer packet data
};
static int preinit(sh_audio_t *sh)
{
sh->audio_out_minsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
return 1;
}
@ -74,6 +77,7 @@ static int setup_format(sh_audio_t *sh_audio,
case AV_SAMPLE_FMT_FLT: sample_format = AF_FORMAT_FLOAT_NE; break;
default:
mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Unsupported sample format\n");
sample_format = AF_FORMAT_UNKNOWN;
}
bool broken_srate = false;
@ -122,6 +126,7 @@ static int init(sh_audio_t *sh_audio)
sh_audio->context = ctx;
lavc_context = avcodec_alloc_context3(lavc_codec);
ctx->avctx = lavc_context;
ctx->avframe = avcodec_alloc_frame();
// Always try to set - option only exists for AC3 at the moment
av_opt_set_double(lavc_context, "drc_scale", opts->drc_level,
@ -223,6 +228,7 @@ static void uninit(sh_audio_t *sh)
av_freep(&lavc_context->extradata);
av_freep(&lavc_context);
}
av_free(ctx->avframe);
talloc_free(ctx);
sh->context = NULL;
}
@ -235,86 +241,123 @@ static int control(sh_audio_t *sh, int cmd, void *arg, ...)
avcodec_flush_buffers(ctx->avctx);
ds_clear_parser(sh->ds);
ctx->previous_data_left = 0;
ctx->output_left = 0;
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
static int decode_new_packet(struct sh_audio *sh)
{
struct priv *priv = sh->context;
AVCodecContext *avctx = priv->avctx;
double pts = MP_NOPTS_VALUE;
int insize;
bool packet_already_used = priv->previous_data_left;
struct demux_packet *mpkt = ds_get_packet2(sh->ds,
priv->previous_data_left);
unsigned char *start;
if (!mpkt) {
assert(!priv->previous_data_left);
start = NULL;
insize = 0;
ds_parse(sh->ds, &start, &insize, pts, 0);
if (insize <= 0)
return -1; // error or EOF
} else {
assert(mpkt->len >= priv->previous_data_left);
if (!priv->previous_data_left) {
priv->previous_data_left = mpkt->len;
pts = mpkt->pts;
}
insize = priv->previous_data_left;
start = mpkt->buffer + mpkt->len - priv->previous_data_left;
int consumed = ds_parse(sh->ds, &start, &insize, pts, 0);
priv->previous_data_left -= consumed;
}
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = start;
pkt.size = insize;
if (mpkt && mpkt->avpacket) {
pkt.side_data = mpkt->avpacket->side_data;
pkt.side_data_elems = mpkt->avpacket->side_data_elems;
}
if (pts != MP_NOPTS_VALUE && !packet_already_used) {
sh->pts = pts;
sh->pts_bytes = 0;
}
int got_frame = 0;
int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt);
// LATM may need many packets to find mux info
if (ret == AVERROR(EAGAIN))
return 0;
if (ret < 0) {
mp_msg(MSGT_DECAUDIO, MSGL_V, "lavc_audio: error\n");
return -1;
}
if (!sh->parser)
priv->previous_data_left += insize - ret;
if (!got_frame)
return 0;
/* An error is reported later from output format checking, but make
* sure we don't crash by overreading first plane. */
if (av_sample_fmt_is_planar(avctx->sample_fmt) && avctx->channels > 1)
return 0;
uint64_t unitsize = (uint64_t)av_get_bytes_per_sample(avctx->sample_fmt) *
avctx->channels;
if (unitsize > 100000)
abort();
priv->unitsize = unitsize;
uint64_t output_left = unitsize * priv->avframe->nb_samples;
if (output_left > 500000000)
abort();
priv->output_left = output_left;
priv->output = priv->avframe->data[0];
mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", insize,
priv->output_left);
return 0;
}
static int decode_audio(sh_audio_t *sh_audio, unsigned char *buf, int minlen,
int maxlen)
{
struct priv *ctx = sh_audio->context;
AVCodecContext *avctx = ctx->avctx;
struct priv *priv = sh_audio->context;
AVCodecContext *avctx = priv->avctx;
unsigned char *start = NULL;
int y, len = -1;
int len = -1;
while (len < minlen) {
AVPacket pkt;
int len2 = maxlen;
double pts = MP_NOPTS_VALUE;
int x;
bool packet_already_used = ctx->previous_data_left;
struct demux_packet *mpkt = ds_get_packet2(sh_audio->ds,
ctx->previous_data_left);
if (!mpkt) {
assert(!ctx->previous_data_left);
start = NULL;
x = 0;
ds_parse(sh_audio->ds, &start, &x, pts, 0);
if (x <= 0)
break; // error
} else {
assert(mpkt->len >= ctx->previous_data_left);
if (!ctx->previous_data_left) {
ctx->previous_data_left = mpkt->len;
pts = mpkt->pts;
}
x = ctx->previous_data_left;
start = mpkt->buffer + mpkt->len - ctx->previous_data_left;
int consumed = ds_parse(sh_audio->ds, &start, &x, pts, 0);
ctx->previous_data_left -= consumed;
}
av_init_packet(&pkt);
pkt.data = start;
pkt.size = x;
if (mpkt && mpkt->avpacket) {
pkt.side_data = mpkt->avpacket->side_data;
pkt.side_data_elems = mpkt->avpacket->side_data_elems;
}
if (pts != MP_NOPTS_VALUE && !packet_already_used) {
sh_audio->pts = pts;
sh_audio->pts_bytes = 0;
}
y = avcodec_decode_audio3(avctx, (int16_t *)buf, &len2, &pkt);
// LATM may need many packets to find mux info
if (y == AVERROR(EAGAIN))
if (!priv->output_left) {
if (decode_new_packet(sh_audio) < 0)
break;
continue;
if (y < 0) {
mp_msg(MSGT_DECAUDIO, MSGL_V, "lavc_audio: error\n");
break;
}
if (!sh_audio->parser)
ctx->previous_data_left += x - y;
if (len2 > 0) {
if (avctx->channels >= 5) {
int samplesize = av_get_bytes_per_sample(avctx->sample_fmt);
reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_LAVC_DEFAULT,
AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
avctx->channels,
len2 / samplesize, samplesize);
}
if (len < 0)
len = len2;
else
len += len2;
buf += len2;
maxlen -= len2;
sh_audio->pts_bytes += len2;
}
mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", y, len2);
if (setup_format(sh_audio, avctx))
break;
return len;
int size = (minlen - len + priv->unitsize - 1);
size -= size % priv->unitsize;
size = FFMIN(size, priv->output_left);
if (size > maxlen)
abort();
memcpy(buf, priv->output, size);
priv->output += size;
priv->output_left -= size;
if (avctx->channels >= 5) {
int samplesize = av_get_bytes_per_sample(avctx->sample_fmt);
reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_LAVC_DEFAULT,
AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
avctx->channels,
size / samplesize, samplesize);
}
if (len < 0)
len = size;
else
len += size;
buf += size;
maxlen -= size;
sh_audio->pts_bytes += size;
}
return len;
}

View File

@ -22,6 +22,9 @@
#include "video_out.h"
bool vo_cocoa_gui_running(void);
void *vo_cocoa_glgetaddr(const char *s);
int vo_cocoa_init(struct vo *vo);
void vo_cocoa_uninit(struct vo *vo);
@ -40,4 +43,7 @@ void vo_cocoa_ontop(struct vo *vo);
// returns an int to conform to the gl extensions from other platforms
int vo_cocoa_swap_interval(int enabled);
void *vo_cocoa_cgl_context(void);
void *vo_cocoa_cgl_pixel_format(void);
#endif /* MPLAYER_COCOA_COMMON_H */

View File

@ -21,6 +21,8 @@
#import <OpenGL/OpenGL.h>
#import <QuartzCore/QuartzCore.h>
#import <CoreServices/CoreServices.h> // for CGDisplayHideCursor and Gestalt
#include <dlfcn.h>
#include "cocoa_common.h"
#include "options.h"
@ -66,6 +68,7 @@ struct vo_cocoa_state {
NSAutoreleasePool *pool;
GLMPlayerWindow *window;
NSOpenGLContext *glContext;
NSOpenGLPixelFormat *pixelFormat;
NSSize current_video_size;
NSSize previous_video_size;
@ -125,6 +128,24 @@ struct vo_cocoa_state *vo_cocoa_init_state(void)
return s;
}
bool vo_cocoa_gui_running(void)
{
return !!s;
}
void *vo_cocoa_glgetaddr(const char *s)
{
void *ret = NULL;
void *handle = dlopen(
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
RTLD_LAZY | RTLD_LOCAL);
if (!handle)
return NULL;
ret = dlsym(handle, s);
dlclose(handle);
return ret;
}
int vo_cocoa_init(struct vo *vo)
{
s = vo_cocoa_init_state();
@ -140,6 +161,8 @@ int vo_cocoa_init(struct vo *vo)
void vo_cocoa_uninit(struct vo *vo)
{
CGDisplayShowCursor(kCGDirectMainDisplay);
[NSApp setPresentationOptions:NSApplicationPresentationDefault];
[s->window release];
s->window = nil;
[s->glContext release];
@ -148,6 +171,7 @@ void vo_cocoa_uninit(struct vo *vo)
s->pool = nil;
talloc_free(s);
s = nil;
}
void update_screen_info(void)
@ -232,8 +256,8 @@ int vo_cocoa_create_window(struct vo *vo, uint32_t d_width,
attr[i++] = (NSOpenGLPixelFormatAttribute)16; // 16 bit depth buffer
attr[i] = (NSOpenGLPixelFormatAttribute)0;
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
s->glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
s->pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
s->glContext = [[NSOpenGLContext alloc] initWithFormat:s->pixelFormat shareContext:nil];
create_menu();
@ -365,6 +389,16 @@ int vo_cocoa_swap_interval(int enabled)
return 0;
}
void *vo_cocoa_cgl_context(void)
{
return [s->glContext CGLContextObj];
}
void *vo_cocoa_cgl_pixel_format(void)
{
return [s->pixelFormat CGLPixelFormatObj];
}
void create_menu()
{
NSMenu *menu;
@ -565,18 +599,19 @@ bool is_lion_or_better(void)
- (void) applicationWillBecomeActive:(NSNotification *)aNotification
{
if (vo_fs) {
[s->window makeKeyAndOrderFront:s->window];
[s->window setLevel:s->fullscreen_window_level];
[NSApp setPresentationOptions:NSApplicationPresentationHideDock|NSApplicationPresentationHideMenuBar];
[s->window makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps: YES];
[NSApp setPresentationOptions:NSApplicationPresentationHideDock|
NSApplicationPresentationHideMenuBar];
}
}
- (void) applicationWillResignActive:(NSNotification *)aNotification
{
if (vo_fs) {
[s->window setLevel:s->windowed_window_level];
[NSApp setPresentationOptions:NSApplicationPresentationDefault];
[s->window setLevel:s->windowed_window_level];
[s->window orderBack:s->window];
}
}

View File

@ -330,6 +330,7 @@ static const extfunc_desc_t extfuncs[] = {
DEF_FUNC_DESC(Color4ub),
DEF_FUNC_DESC(Color4f),
DEF_FUNC_DESC(TexCoord2f),
DEF_FUNC_DESC(TexCoord2fv),
DEF_FUNC_DESC(Vertex2f),
DEF_FUNC_DESC(VertexPointer),
DEF_FUNC_DESC(ColorPointer),
@ -1725,14 +1726,14 @@ static int create_window_cocoa_gl3(struct MPGLContext *ctx, int gl_flags,
uint32_t d_height, uint32_t flags)
{
int rv = vo_cocoa_create_window(ctx->vo, d_width, d_height, flags, 1);
getFunctions(ctx->gl, (void *)getdladdr, NULL, true);
getFunctions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL, true);
return rv;
}
static int setGlWindow_cocoa(MPGLContext *ctx)
{
vo_cocoa_change_attributes(ctx->vo);
getFunctions(ctx->gl, (void *)getdladdr, NULL, false);
getFunctions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL, false);
if (!ctx->gl->SwapInterval)
ctx->gl->SwapInterval = vo_cocoa_swap_interval;
return SET_WINDOW_OK;

View File

@ -260,6 +260,7 @@ struct GL {
void (GLAPIENTRY *TexParameterf)(GLenum, GLenum, GLfloat);
void (GLAPIENTRY *TexParameterfv)(GLenum, GLenum, const GLfloat *);
void (GLAPIENTRY *TexCoord2f)(GLfloat, GLfloat);
void (GLAPIENTRY *TexCoord2fv)(const GLfloat *);
void (GLAPIENTRY *Vertex2f)(GLfloat, GLfloat);
void (GLAPIENTRY *GetIntegerv)(GLenum, GLint *);
void (GLAPIENTRY *GetBooleanv)(GLenum, GLboolean *);

View File

@ -118,6 +118,7 @@ extern struct vo_driver video_out_tdfx_vid;
extern struct vo_driver video_out_xvr100;
extern struct vo_driver video_out_tga;
extern struct vo_driver video_out_corevideo;
extern struct vo_driver video_out_sharedbuffer;
extern struct vo_driver video_out_pnm;
extern struct vo_driver video_out_md5sum;
@ -221,6 +222,9 @@ const struct vo_driver *video_out_drivers[] =
#endif
&video_out_null,
// should not be auto-selected
#ifdef CONFIG_SHAREDBUFFER
&video_out_sharedbuffer,
#endif
#ifdef CONFIG_DIRECTFB
// vo directfb can call exit() if initialization fails
&video_out_directfb,

View File

@ -23,93 +23,6 @@
#ifndef MPLAYER_VO_COREVIDEO_H
#define MPLAYER_VO_COREVIDEO_H
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <Carbon/Carbon.h>
// MPlayer OS X VO Protocol
@protocol MPlayerOSXVOProto
- (int) startWithWidth: (bycopy int)width
withHeight: (bycopy int)height
withBytes: (bycopy int)bytes
withAspect: (bycopy int)aspect;
- (void) stop;
- (void) render;
- (void) toggleFullscreen;
- (void) ontop;
@end
@interface MPlayerOpenGLView : NSOpenGLView
{
//Cocoa
NSWindow *window;
//CoreVideo
CVPixelBufferRef frameBuffers[2];
CVOpenGLTextureCacheRef textureCache;
CVOpenGLTextureRef texture;
NSRect textureFrame;
GLfloat lowerLeft[2];
GLfloat lowerRight[2];
GLfloat upperRight[2];
GLfloat upperLeft[2];
BOOL mouseHide;
//menu command id
NSMenuItem *kHalfScreenCmd;
NSMenuItem *kNormalScreenCmd;
NSMenuItem *kDoubleScreenCmd;
NSMenuItem *kFullScreenCmd;
NSMenuItem *kKeepAspectCmd;
NSMenuItem *kAspectOrgCmd;
NSMenuItem *kAspectFullCmd;
NSMenuItem *kAspectWideCmd;
NSMenuItem *kPanScanCmd;
//timestamps for disabling screensaver and mouse hiding
int lastMouseHide;
int lastScreensaverUpdate;
@public
float winSizeMult;
}
- (BOOL) acceptsFirstResponder;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
//window & rendering
- (void) preinit;
- (void) config;
- (void) prepareOpenGL;
- (void) render;
- (void) reshape;
- (void) setCurrentTexture;
- (void) drawRect: (NSRect *) bounds;
//vo control
- (void) fullscreen: (BOOL) animate;
- (void) ontop;
- (void) panscan;
- (void) rootwin;
//menu
- (void) initMenu;
- (void) menuAction:(id)sender;
//event
- (void) keyDown: (NSEvent *) theEvent;
- (void) mouseMoved: (NSEvent *) theEvent;
- (void) mouseDown: (NSEvent *) theEvent;
- (void) mouseUp: (NSEvent *) theEvent;
- (void) rightMouseDown: (NSEvent *) theEvent;
- (void) rightMouseUp: (NSEvent *) theEvent;
- (void) otherMouseDown: (NSEvent *) theEvent;
- (void) otherMouseUp: (NSEvent *) theEvent;
- (void) scrollWheel: (NSEvent *) theEvent;
- (void) mouseEvent: (NSEvent *) theEvent;
- (void) check_events;
@end
#endif /* MPLAYER_VO_COREVIDEO_H */

File diff suppressed because it is too large Load Diff

37
libvo/vo_sharedbuffer.h Normal file
View File

@ -0,0 +1,37 @@
/*
* OSX Shared Buffer Video Output (extracted from mplayer's corevideo)
*
* This file is part of mplayer2.
*
* mplayer2 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.
*
* mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPLAYER_VO_OSX_SHAREDBUFFER_H
#define MPLAYER_VO_OSX_SHAREDBUFFER_H
#import <Cocoa/Cocoa.h>
// Protocol to communicate with the GUI
@protocol MPlayerOSXVOProto
- (int) startWithWidth: (bycopy int)width
withHeight: (bycopy int)height
withBytes: (bycopy int)bytes
withAspect: (bycopy int)aspect;
- (void) stop;
- (void) render;
- (void) toggleFullscreen;
- (void) ontop;
@end
#endif /* MPLAYER_VO_OSX_SHAREDBUFFER_H */

277
libvo/vo_sharedbuffer.m Normal file
View File

@ -0,0 +1,277 @@
/*
* OSX Shared Buffer Video Output (extracted from mplayer's corevideo)
*
* This file is part of mplayer2.
*
* mplayer2 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.
*
* mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This video output was extracted from mplayer's corevideo. It's purpose it
* to copy mp_image data to a shared buffer using mmap and to do simple
* coordination with the GUIs using Distributed Objects.
*/
#include <sys/mman.h>
#include "vo_sharedbuffer.h"
#include "video_out.h"
#include "subopt-helper.h"
#include "talloc.h"
#include "libmpcodecs/vfcap.h"
#include "libmpcodecs/mp_image.h"
#include "fastmemcpy.h"
#include "sub/sub.h"
#include "osd.h"
// declarations
struct priv {
char *buffer_name;
unsigned char *image_data;
unsigned int image_bytespp;
unsigned int image_width;
unsigned int image_height;
void (*vo_draw_alpha_fnc)(int w, int h, unsigned char* src,
unsigned char *srca, int srcstride, unsigned char* dstbase,
int dststride);
NSDistantObject *mposx_proxy;
id <MPlayerOSXVOProto> mposx_proto;
};
struct priv *p;
// implementation
static void draw_alpha(void *ctx, int x0, int y0, int w, int h,
unsigned char *src, unsigned char *srca,
int stride)
{
p->vo_draw_alpha_fnc(w, h, src, srca, stride,
p->image_data + (x0 + y0 * p->image_width) * p->image_bytespp,
p->image_width * p->image_bytespp);
}
static unsigned int image_bytes()
{
return p->image_width * p->image_height * p->image_bytespp;
}
static int preinit(struct vo *vo, const char *arg)
{
p = talloc_zero(NULL, struct priv);
const opt_t subopts[] = {
{"buffer_name", OPT_ARG_MSTRZ, &p->buffer_name, NULL},
{NULL}
};
if (subopt_parse(arg, subopts) != 0) {
mp_msg(MSGT_VO, MSGL_FATAL,
"\n-vo sharedbuffer command line help:\n"
"Example: mplayer -vo shared_buffer:buffer_name=mybuff\n"
"\nOptions:\n"
" buffer_name=<name>\n"
" Name of the shared buffer created with shm_open() as well as\n"
" the name of the NSConnection mplayer2 will try to open.\n"
"Example: mplayer -vo sharedbuffer\n"
"\n" );
return -1;
}
if (!p->buffer_name) p->buffer_name = "mplayerosx";
return 0;
}
static void flip_page(struct vo *vo)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[p->mposx_proto render];
[pool release];
}
static void check_events(struct vo *vo) { }
static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
{
memcpy_pic(p->image_data, mpi->planes[0],
(p->image_width) * (p->image_bytespp), p->image_height,
(p->image_width) * (p->image_bytespp), mpi->stride[0]);
return 0;
}
static void draw_osd(struct vo *vo, struct osd_state *osd) {
osd_draw_text(osd, p->image_width, p->image_height, draw_alpha, vo);
}
static void free_buffers(void)
{
[p->mposx_proto stop];
p->mposx_proto = nil;
[p->mposx_proxy release];
p->mposx_proxy = nil;
if (p->image_data) {
if (munmap(p->image_data, image_bytes()) == -1)
mp_msg(MSGT_VO, MSGL_FATAL, "[vo_sharedbuffer] uninit: munmap "
"failed. Error: %s\n", strerror(errno));
if (shm_unlink(p->buffer_name) == -1)
mp_msg(MSGT_VO, MSGL_FATAL, "[vo_sharedbuffer] uninit: shm_unlink "
"failed. Error: %s\n", strerror(errno));
}
}
static int config(struct vo *vo, uint32_t width, uint32_t height,
uint32_t d_width, uint32_t d_height, uint32_t flags,
uint32_t format)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
free_buffers();
p->image_width = width;
p->image_height = height;
mp_msg(MSGT_VO, MSGL_INFO, "[vo_sharedbuffer] writing output to a shared "
"buffer named \"%s\"\n", p->buffer_name);
// create shared memory
int shm_fd = shm_open(p->buffer_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
mp_msg(MSGT_VO, MSGL_FATAL,
"[vo_sharedbuffer] failed to open shared memory. Error: %s\n",
strerror(errno));
goto err_out;
}
if (ftruncate(shm_fd, image_bytes()) == -1) {
mp_msg(MSGT_VO, MSGL_FATAL,
"[vo_sharedbuffer] failed to size shared memory, possibly "
"already in use. Error: %s\n", strerror(errno));
close(shm_fd);
shm_unlink(p->buffer_name);
goto err_out;
}
p->image_data = mmap(NULL, image_bytes(),
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
close(shm_fd);
if (p->image_data == MAP_FAILED) {
mp_msg(MSGT_VO, MSGL_FATAL,
"[vo_sharedbuffer] failed to map shared memory. "
"Error: %s\n", strerror(errno));
shm_unlink(p->buffer_name);
goto err_out;
}
//connect to mplayerosx
p->mposx_proxy = [NSConnection
rootProxyForConnectionWithRegisteredName:
[NSString stringWithUTF8String:p->buffer_name] host:nil];
if ([p->mposx_proxy conformsToProtocol:@protocol(MPlayerOSXVOProto)]) {
[p->mposx_proxy setProtocolForProxy:@protocol(MPlayerOSXVOProto)];
p->mposx_proto = (id <MPlayerOSXVOProto>)p->mposx_proxy;
[p->mposx_proto startWithWidth:p->image_width
withHeight:p->image_height
withBytes:p->image_bytespp
withAspect:d_width*100/d_height];
} else {
mp_msg(MSGT_VO, MSGL_ERR,
"[vo_sharedbuffer] distributed object doesn't conform "
"to the correct protocol.\n");
[p->mposx_proxy release];
p->mposx_proxy = nil;
p->mposx_proto = nil;
}
[pool release];
return 0;
err_out:
[pool release];
return 1;
}
static int query_format(uint32_t format)
{
unsigned int image_depth = 0;
switch (format) {
case IMGFMT_YUY2:
p->vo_draw_alpha_fnc = vo_draw_alpha_yuy2;
image_depth = 16;
goto supported;
case IMGFMT_RGB24:
p->vo_draw_alpha_fnc = vo_draw_alpha_rgb24;
image_depth = 24;
goto supported;
case IMGFMT_ARGB:
p->vo_draw_alpha_fnc = vo_draw_alpha_rgb32;
image_depth = 32;
goto supported;
case IMGFMT_BGRA:
p->vo_draw_alpha_fnc = vo_draw_alpha_rgb32;
image_depth = 32;
goto supported;
}
return 0;
supported:
p->image_bytespp = (image_depth + 7) / 8;
return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN |
VOCAP_NOSLICES;
}
static void uninit(struct vo *vo)
{
free_buffers();
}
static int control(struct vo *vo, uint32_t request, void *data)
{
switch (request) {
case VOCTRL_DRAW_IMAGE:
return draw_image(vo, data);
case VOCTRL_FULLSCREEN:
[p->mposx_proto toggleFullscreen];
return VO_TRUE;
case VOCTRL_QUERY_FORMAT:
return query_format(*(uint32_t*)data);
case VOCTRL_ONTOP:
[p->mposx_proto ontop];
return VO_TRUE;
}
return VO_NOTIMPL;
}
const struct vo_driver video_out_sharedbuffer = {
.is_new = true,
.info = &(const vo_info_t) {
"Mac OS X Shared Buffer (headless video output for GUIs)",
"sharedbuffer",
"Stefano Pigozzi <stefano.pigozzi@gmail.com> and others.",
""
},
.preinit = preinit,
.config = config,
.control = control,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
.draw_osd = draw_osd
};

View File

@ -31,6 +31,16 @@
#if defined(__MINGW32__) || defined(__CYGWIN__)
#include <windows.h>
// No proper file descriptor event handling; keep waking up to poll input
#define WAKEUP_PERIOD 0.02
#else
/* Even if we can immediately wake up in response to most input events,
* there are some timers which are not registered to the event loop
* and need to be checked periodically (like automatic mouse cursor hiding).
* OSD content updates behave similarly. Also some uncommon input devices
* may not have proper FD event support.
*/
#define WAKEUP_PERIOD 0.5
#endif
#include <string.h>
#include <unistd.h>
@ -1766,8 +1776,10 @@ void reinit_audio_chain(struct MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
struct ao *ao;
if (!mpctx->sh_audio)
if (!mpctx->sh_audio) {
uninit_player(mpctx, INITIALIZED_AO);
return;
}
if (!(mpctx->initialized_flags & INITIALIZED_ACODEC)) {
current_module = "init_audio_codec";
mp_msg(MSGT_CPLAYER, MSGL_INFO, "==========================================================================\n");
@ -2621,11 +2633,10 @@ int reinit_video_chain(struct MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
sh_video_t * const sh_video = mpctx->sh_video;
if (!sh_video){
if (!sh_video) {
uninit_player(mpctx, INITIALIZED_VO);
return 0;
}
double ar = -1.0;
//================== Init VIDEO (codec & libvo) ==========================
if (!opts->fixed_vo || !(mpctx->initialized_flags & INITIALIZED_VO)) {
@ -2717,6 +2728,8 @@ int reinit_video_chain(struct MPContext *mpctx)
sh_video->last_pts = MP_NOPTS_VALUE;
sh_video->num_buffered_pts = 0;
sh_video->next_frame_time = 0;
mpctx->restart_playback = true;
mpctx->delay = 0;
if (opts->auto_quality > 0) {
// Auto quality option enabled
@ -3424,7 +3437,7 @@ static void run_playloop(struct MPContext *mpctx)
bool audio_left = false, video_left = false;
double endpts = end_at.type == END_AT_TIME ? end_at.pos : MP_NOPTS_VALUE;
bool end_is_chapter = false;
double sleeptime = 0.5;
double sleeptime = WAKEUP_PERIOD;
bool was_restart = mpctx->restart_playback;
if (mpctx->timeline) {
@ -4256,17 +4269,13 @@ play_next_file:
mp_msg(MSGT_CPLAYER, MSGL_DBG2, "\n[[[init getch2]]]\n");
}
// ================= GUI idle loop (STOP state) =========================
// ================= idle loop (STOP state) =========================
while (opts->player_idle_mode && !mpctx->filename) {
uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_VO);
play_tree_t *entry = NULL;
mp_cmd_t *cmd;
if (mpctx->video_out && mpctx->video_out->config_ok)
vo_control(mpctx->video_out, VOCTRL_PAUSE, NULL);
while (!(cmd = mp_input_get_cmd(mpctx->input, 0, 0))) {
if (mpctx->video_out)
vo_check_events(mpctx->video_out);
usec_sleep(20000);
}
while (!(cmd = mp_input_get_cmd(mpctx->input, WAKEUP_PERIOD * 1000,
false)));
switch (cmd->id) {
case MP_CMD_LOADFILE:
// prepare a tree entry with the new filename
@ -4853,7 +4862,6 @@ goto_enable_cache:
mixer_setvolume(&mpctx->mixer, start_volume, start_volume);
if (!ignore_start)
audio_delay -= mpctx->sh_audio->stream_delay;
mpctx->delay = -audio_delay;
}
if (!mpctx->sh_audio) {

30
osdep/cocoa_events.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Cocoa Event Handling
*
* This file is part of mplayer2.
*
* mplayer2 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.
*
* mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPLAYER_COCOA_EVENTS_H
#define MPLAYER_COCOA_EVENTS_H
#include "input/input.h"
void cocoa_events_init(struct input_ctx *ictx,
void (*read_all_fd_events)(struct input_ctx *ictx, int time));
void cocoa_events_uninit(void);
void cocoa_events_read_all_events(struct input_ctx *ictx, int time);
#endif /* MPLAYER_COCOA_EVENTS_H */

137
osdep/cocoa_events.m Normal file
View File

@ -0,0 +1,137 @@
/*
* Cocoa Event Handling
*
* This file is part of mplayer2.
*
* mplayer2 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.
*
* mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Implementation details:
* This file deals with custom event polling on MacOSX. When mplayer2 is paused
* it will asynchronously poll for events using select. This works correctly on
* Linux with X11 since the events are notified through the file descriptors
* where mplayer2 is listening on. On the other hand, the OSX window server
* notifies the processes for events using mach ports.
*
* The code below uses functionality from Cocoa that abstracts the async polling
* of events from the window server. When a Cocoa event comes in, the polling is
* interrupted and the event is dealt with in the next vo_check_events.
*
* To keep the select fd polling code working, that functionality is executed
* from another thread. Whoever finishes polling before the given time, be it
* Cocoa or the original select code, notifies the other for an immediate wake.
*/
#include "cocoa_events.h"
#include "libvo/cocoa_common.h"
#include "talloc.h"
#import <Cocoa/Cocoa.h>
#include <dispatch/dispatch.h>
// Bogus event subtype to wake the Cocoa code from polling state
#define MP_EVENT_SUBTYPE_WAKE_EVENTLOOP 100
// This is the threshold in milliseconds below which the Cocoa polling is not
// executed. There is some overhead caused by the synchronization between
// threads. Even if in practice it isn't noticeable, we try to avoid the useless
// waste of resources.
#define MP_ASYNC_THRESHOLD 50
struct priv {
dispatch_queue_t select_queue;
bool is_runloop_polling;
void (*read_all_fd_events)(struct input_ctx *ictx, int time);
};
static struct priv *p;
static void cocoa_wait_events(int mssleeptime)
{
NSTimeInterval sleeptime = mssleeptime / 1000.0;
NSEvent *event;
p->is_runloop_polling = YES;
event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate dateWithTimeIntervalSinceNow:sleeptime]
inMode:NSEventTrackingRunLoopMode dequeue:NO];
// dequeue the next event if it is a fake to wake the cocoa polling
if (event && [event type] == NSApplicationDefined &&
[event subtype] == MP_EVENT_SUBTYPE_WAKE_EVENTLOOP) {
[NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
inMode:NSEventTrackingRunLoopMode dequeue:YES];
}
p->is_runloop_polling = NO;
}
static void cocoa_wake_runloop()
{
if (p->is_runloop_polling) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSEvent *event;
/* Post an event so we'll wake the run loop that is async polling */
event = [NSEvent otherEventWithType: NSApplicationDefined
location: NSZeroPoint
modifierFlags: 0
timestamp: 0
windowNumber: 0
context: nil
subtype: MP_EVENT_SUBTYPE_WAKE_EVENTLOOP
data1: 0
data2: 0];
[NSApp postEvent:event atStart:NO];
[pool release];
}
}
void cocoa_events_init(struct input_ctx *ictx,
void (*read_all_fd_events)(struct input_ctx *ictx, int time))
{
NSApplicationLoad();
p = talloc_ptrtype(NULL, p);
*p = (struct priv){
.is_runloop_polling = NO,
.read_all_fd_events = read_all_fd_events,
.select_queue = dispatch_queue_create("org.mplayer2.select_queue",
NULL),
};
}
void cocoa_events_uninit(void)
{
talloc_free(p);
}
void cocoa_events_read_all_events(struct input_ctx *ictx, int time)
{
// don't bother delegating the select to the async queue if the blocking
// time is really low or if we are not running a GUI
if (time > MP_ASYNC_THRESHOLD && vo_cocoa_gui_running()) {
dispatch_async(p->select_queue, ^{
p->read_all_fd_events(ictx, time);
cocoa_wake_runloop();
});
cocoa_wait_events(time);
mp_input_wakeup(ictx);
// wait for the async queue to get empty.
dispatch_sync(p->select_queue, ^{});
} else {
p->read_all_fd_events(ictx, time);
}
}

8
path.c
View File

@ -55,6 +55,9 @@ char *get_path(const char *filename){
static char *config_dir = "/mplayer";
#else
static char *config_dir = "/.mplayer";
#endif
#if defined(__MINGW32__) || defined(__CYGWIN__)
char exedir[260];
#endif
int len;
#ifdef CONFIG_MACOSX_BUNDLE
@ -73,9 +76,8 @@ char *get_path(const char *filename){
/* Hack to get fonts etc. loaded outside of Cygwin environment. */
{
int i,imax=0;
char exedir[260];
GetModuleFileNameA(NULL, exedir, 260);
for (i=0; i< strlen(exedir); i++)
len = (int)GetModuleFileNameA(NULL, exedir, 260);
for (i=0; i < len; i++)
if (exedir[i] =='\\')
{exedir[i]='/'; imax=i;}
exedir[imax]='\0';

View File

@ -56,7 +56,7 @@ static int seek(stream_t *s, off_t newpos)
static int control(stream_t *s, int cmd, void *arg)
{
AVIOContext *avio = avio;
AVIOContext *avio = s->priv;
int64_t size, ts;
double pts;
switch(cmd) {

View File

@ -106,25 +106,30 @@ static const struct {
#define SUBRIP_MAX_STACKED_FONT_TAGS 16
/* read the attribute value starting at *s, and skip *s past the value
* return the value in out_value, with possible '"' stripped
* return whether the attribute is well formed */
static bool read_value(char **s, struct bstr *out_value)
/* Read the HTML-style attribute starting at *s, and skip *s past the value.
* Set attr and val to the parsed attribute name and value.
* Return 0 on success, or -1 if no valid attribute was found.
*/
static int read_attr(char **s, struct bstr *attr, struct bstr *val)
{
char term = '\0';
if (**s == '"') {
term = '"';
(*s)++;
}
out_value->start = *s;
out_value->len = 0;
unsigned char *start = *s;
unsigned char *end = term ? strchr(start, term) : strpbrk(start, " >");
char *eq = strchr(*s, '=');
if (!eq)
return -1;
attr->start = *s;
attr->len = eq - *s;
for (int i = 0; i < attr->len; i++)
if (!isalnum(attr->start[i]))
return -1;
val->start = eq + 1;
bool quoted = val->start[0] == '"';
if (quoted)
val->start++;
unsigned char *end = strpbrk(val->start, quoted ? "\"" : " >");
if (!end)
return false;
out_value->len = end - out_value->start;
*s = end + (term ? 1 : 0);
return true;
return -1;
val->len = end - val->start;
*s = end + quoted;
return 0;
}
void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
@ -195,22 +200,21 @@ void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
line += 6;
while (*line && *line != '>') {
if (strncmp(line, "size=", 5) == 0) {
line += 5;
struct bstr val;
if (!read_value(&line, &val))
break;
if (*line == ' ') {
line++;
continue;
}
struct bstr attr, val;
if (read_attr(&line, &attr, &val) < 0)
break;
if (!bstrcmp0(attr, "size")) {
tag->size = bstrtoll(val, &val, 10);
if (val.len)
break;
append_text(&new_line, "{\\fs%d}", tag->size);
tag->has_size = true;
has_valid_attr = true;
} else if (strncmp(line, "color=", 6) == 0) {
line += 6;
struct bstr val;
if (!read_value(&line, &val))
break;
} else if (!bstrcmp0(attr, "color")) {
if (bstr_eatstart(&val, bstr("#"))) {
// #RRGGBB format
tag->color = bstrtoll(val, &val, 16) & 0x00ffffff;
@ -240,18 +244,15 @@ void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
append_text(&new_line, "{\\c&H%06X&}", tag->color);
tag->has_color = true;
has_valid_attr = true;
} else if (strncmp(line, "face=", 5) == 0) {
} else if (!bstrcmp0(attr, "face")) {
/* Font face attribute */
line += 5;
struct bstr val;
if (!read_value(&line, &val))
break;
tag->face = val;
append_text(&new_line, "{\\fn%.*s}", BSTR_P(tag->face));
tag->has_face = true;
has_valid_attr = true;
} else
line++;
mp_tmsg(MSGT_SUBREADER, MSGL_WARN,"SubRip: unrecognized "
"attribute \"%.*s\" in font tag\n", BSTR_P(attr));
}
if (!has_valid_attr || *line != '>') { /* Not valid font tag */