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:
commit
97ac824124
7
Makefile
7
Makefile
@ -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
|
||||
|
1
av_log.c
1
av_log.c
@ -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
1
bstr.h
@ -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
187
configure
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
1397
libvo/vo_corevideo.m
1397
libvo/vo_corevideo.m
File diff suppressed because it is too large
Load Diff
37
libvo/vo_sharedbuffer.h
Normal file
37
libvo/vo_sharedbuffer.h
Normal 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
277
libvo/vo_sharedbuffer.m
Normal 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
|
||||
};
|
34
mplayer.c
34
mplayer.c
@ -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
30
osdep/cocoa_events.h
Normal 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
137
osdep/cocoa_events.m
Normal 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
8
path.c
@ -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';
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user