From aadf1002f8aa3a5813fd13ad18b8907b82068811 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sun, 15 Apr 2012 17:48:12 +0300 Subject: screenshot: fix dependency on sizeof(AVFrame) The AVFrame data structure may be extended at the end in new binary-compatible libavcodec versions. Therefore applications should not depend on the size of the structure. But screenshot.c declared an "AVFrame pic;" on stack. Change the code to allocate an AVFrame with avcodec_alloc_frame() instead. The frame is now stored in struct screenshot_ctx (rather than reallocated each time). --- screenshot.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/screenshot.c b/screenshot.c index af1c5c1da2..4a9a6c435a 100644 --- a/screenshot.c +++ b/screenshot.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,7 @@ #include "libvo/csputils.h" typedef struct screenshot_ctx { + AVFrame *pic; int full_window; int each_frame; int using_vf_screenshot; @@ -51,10 +53,22 @@ typedef struct screenshot_ctx { char fname[102]; } screenshot_ctx; +static int destroy_ctx(void *ptr) +{ + struct screenshot_ctx *ctx = ptr; + av_free(ctx->pic); + return 0; +} + static screenshot_ctx *screenshot_get_ctx(MPContext *mpctx) { - if (!mpctx->screenshot_ctx) - mpctx->screenshot_ctx = talloc_zero(mpctx, screenshot_ctx); + if (!mpctx->screenshot_ctx) { + struct screenshot_ctx *ctx = talloc_zero(mpctx, screenshot_ctx); + talloc_set_destructor(ctx, destroy_ctx); + ctx->pic = avcodec_alloc_frame(); + assert(ctx->pic); + mpctx->screenshot_ctx = ctx; + } return mpctx->screenshot_ctx; } @@ -91,13 +105,13 @@ static int write_png(screenshot_ctx *ctx, struct mp_image *image) if (!outbuffer) goto error_exit; - AVFrame pic; - avcodec_get_frame_defaults(&pic); + AVFrame *pic = ctx->pic; + avcodec_get_frame_defaults(pic); for (int n = 0; n < 4; n++) { - pic.data[n] = image->planes[n]; - pic.linesize[n] = image->stride[n]; + pic->data[n] = image->planes[n]; + pic->linesize[n] = image->stride[n]; } - int size = avcodec_encode_video(avctx, outbuffer, outbuffer_size, &pic); + int size = avcodec_encode_video(avctx, outbuffer, outbuffer_size, pic); if (size < 1) goto error_exit; -- cgit v1.2.3 From f0ce95607f566d288674f317176c51bcda026a9d Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 16 Apr 2012 23:00:19 +0200 Subject: subassconvert: handle unquoted attributes in subrip font tags Previously, mplayer didn't convert tags like . But such subtitles exist in the wild, and should be handled. --- bstr.c | 8 ++++++ bstr.h | 3 +++ sub/subassconvert.c | 72 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/bstr.c b/bstr.c index 0c46b1d9b0..2ce5f6787e 100644 --- a/bstr.c +++ b/bstr.c @@ -185,6 +185,14 @@ struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str) return r; } +bool bstr_eatstart(struct bstr *s, struct bstr prefix) +{ + if (!bstr_startswith(*s, prefix)) + return false; + *s = bstr_cut(*s, prefix.len); + return true; +} + void bstr_lower(struct bstr str) { for (int i = 0; i < str.len; i++) diff --git a/bstr.h b/bstr.h index 8b1644cac0..b3f942535e 100644 --- a/bstr.h +++ b/bstr.h @@ -82,6 +82,9 @@ int bstr_decode_utf8(struct bstr str, struct bstr *out_next); // On error, -1 is returned. On success, it returns a value in the range [1, 4]. int bstr_parse_utf8_code_length(unsigned char b); +// If s starts with prefix, return true and return the rest of the string in s. +bool bstr_eatstart(struct bstr *s, struct bstr prefix); + static inline struct bstr bstr_cut(struct bstr str, int n) { if (n > str.len) diff --git a/sub/subassconvert.c b/sub/subassconvert.c index 2a56b46022..77b27267dc 100644 --- a/sub/subassconvert.c +++ b/sub/subassconvert.c @@ -106,6 +106,27 @@ static const struct { #define SUBRIP_MAX_STACKED_FONT_TAGS 16 +/* Read the attribute value starting at *s, and skip *s past the value. + * Set out_value to the parsed value, with possible '"' stripped. + * Return whether the attribute is well formed. */ +static bool read_value(char **s, struct bstr *out_value) +{ + 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, " >"); + if (!end) + return false; + out_value->len = end - out_value->start; + *s = end + (term ? 1 : 0); + return true; +} + void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size) { /* line is not const to avoid warnings with strtol, etc. @@ -174,34 +195,35 @@ void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size) line += 6; while (*line && *line != '>') { - if (strncmp(line, "size=\"", 6) == 0) { - line += 6; - tag->size = strtol(line, &line, 10); - if (*line != '"') + if (strncmp(line, "size=", 5) == 0) { + line += 5; + struct bstr val; + if (!read_value(&line, &val)) + break; + 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=\"", 7) == 0) { - line += 7; - if (*line == '#') { + } else if (strncmp(line, "color=", 6) == 0) { + line += 6; + struct bstr val; + if (!read_value(&line, &val)) + break; + if (bstr_eatstart(&val, bstr("#"))) { // #RRGGBB format - line++; - tag->color = strtol(line, &line, 16) & 0x00ffffff; - if (*line != '"') + tag->color = bstrtoll(val, &val, 16) & 0x00ffffff; + if (val.len) break; tag->color = ((tag->color & 0xff) << 16) | (tag->color & 0xff00) | ((tag->color & 0xff0000) >> 16); } else { // Standard web colors - int len = indexof(line, '"'); - if (len <= 0) - break; for (int i = 0; i < FF_ARRAY_ELEMS(subrip_web_colors); i++) { char *color = subrip_web_colors[i].s; - if (strlen(color) == len - && strncasecmp(line, color, len) == 0) { + if (bstrcasecmp(val, bstr(color)) == 0) { tag->color = subrip_web_colors[i].v; goto foundcolor; } @@ -211,29 +233,25 @@ void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size) mp_tmsg(MSGT_SUBREADER, MSGL_WARN, "SubRip: unknown font color in subtitle: %s\n", orig); append_text(&new_line, "{\\c}"); - line += len + 1; continue; - foundcolor: - line += len; + foundcolor: ; } append_text(&new_line, "{\\c&H%06X&}", tag->color); tag->has_color = true; has_valid_attr = true; - } else if (strncmp(line, "face=\"", 6) == 0) { + } else if (strncmp(line, "face=", 5) == 0) { /* Font face attribute */ - line += 6; - int len = indexof(line, '"'); - if (len <= 0) + line += 5; + struct bstr val; + if (!read_value(&line, &val)) break; - tag->face.start = line; - tag->face.len = len; - line += len; + tag->face = val; append_text(&new_line, "{\\fn%.*s}", BSTR_P(tag->face)); tag->has_face = true; has_valid_attr = true; - } - line++; + } else + line++; } if (!has_valid_attr || *line != '>') { /* Not valid font tag */ -- cgit v1.2.3 From 81eb9117633e77514361f219ee4a72a88701d313 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 17 Apr 2012 02:07:55 +0300 Subject: subassconvert: make subrip attribute parsing more robust Add general code to separate the HTML-like attribute=value syntax used in srt font tags into attribute and value parts. This simplifies some of the parsing code, makes detection of malformed input more robust, and allows warning about unrecognized attributes. --- sub/subassconvert.c | 67 +++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/sub/subassconvert.c b/sub/subassconvert.c index 77b27267dc..e1db9bb033 100644 --- a/sub/subassconvert.c +++ b/sub/subassconvert.c @@ -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. - * Set out_value to the parsed 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 */ -- cgit v1.2.3 From b9fefc87c01bbf464fb74981313efa77e03735f6 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Wed, 18 Apr 2012 01:27:55 +0300 Subject: stream_ffmpeg: fix broken line from 30afc64532ff61 Commit 30afc64532ff61 ("stream_ffmpeg: switch to libavformat avio API") somehow contained a nonsense line which broke the control() function. Fix. Also add avformat_network_init() to central libav initialization code to avoid warnings. --- av_log.c | 1 + stream/stream_ffmpeg.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/av_log.c b/av_log.c index 63f8fd7dc3..4e27e98d0f 100644 --- a/av_log.c +++ b/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 diff --git a/stream/stream_ffmpeg.c b/stream/stream_ffmpeg.c index a76b9e5f3b..af71675713 100644 --- a/stream/stream_ffmpeg.c +++ b/stream/stream_ffmpeg.c @@ -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) { -- cgit v1.2.3 From deffd15a056f98bbe1bc34ce87dea0b4a530d61d Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Thu, 19 Apr 2012 01:26:56 +0300 Subject: ad_ffmpeg: switch to avcodec_decode_audio4() Switch libavcodec audio decoding from avcodec_decode_audio3() to avcodec_decode_audio4(). Instead of decoding directly to the output buffer, the data is now copied from the libavcodec output packet, adding an extra memory copy (optimizing this would require some interface changes). After libavcodec added avcodec_decode_audio4() earlier, it dropped support for splitting large audio packets into output chunks of size AVCODEC_MAX_AUDIO_FRAME_SIZE or less. This caused a regression with the previous API: audio files with huge packets could fail to decode, as libavcodec refused to write into the AVCODEC_MAX_AUDIO_FRAME_SIZE buffer provided by mplayer2. This occurrend mainly with some lossless audio formats. This commit restores support for those files; there are now no fixed limits on packet size. --- libmpcodecs/ad_ffmpeg.c | 181 ++++++++++++++++++++++++++++++------------------ 1 file changed, 112 insertions(+), 69 deletions(-) diff --git a/libmpcodecs/ad_ffmpeg.c b/libmpcodecs/ad_ffmpeg.c index 4a5062ba00..0bfc5e5f0a 100644 --- a/libmpcodecs/ad_ffmpeg.c +++ b/libmpcodecs/ad_ffmpeg.c @@ -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; } -- cgit v1.2.3 From e48c6f446c4de708dd9d3b47d3479620208f7430 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Thu, 19 Apr 2012 17:05:50 +0300 Subject: configure: --enable-debug: don't change other compiler flags The --enable-debug and --enable-profile options set their own compiler flags, completely different from normal flag selection. These flags sucked; especially '-W' (an obsolete alias for '-Wextra') generated a huge number of irrelevant warnings. Change configure to only add "-g" or similar to the flags that would be used otherwise. --- configure | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/configure b/configure index 12f5e9db31..27dde1a754 100755 --- a/configure +++ b/configure @@ -2310,23 +2310,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" @@ -6844,12 +6843,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 -- cgit v1.2.3 From b255b5ad32fe49e4c01060ae01c67d246b5d6d38 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 23 Apr 2012 21:52:54 +0300 Subject: core: uninitialize VO and AO when no track plays Uninitialize video and audio outputs when switching to a file without a corresponding track (audio-only file / file with no sound), or when entering --idle mode. Switching track choice to "off" during playback already did this. It could be useful to have a mode where the video window stays open even when no video plays, but implementing that properly would require more than just leaving the window on screen like the code did before this commit. --- mplayer.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mplayer.c b/mplayer.c index f3a9cbdc10..0f63907df8 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1760,8 +1760,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"); @@ -2615,8 +2617,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)) { @@ -4244,17 +4248,12 @@ 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, 500, false))); switch (cmd->id) { case MP_CMD_LOADFILE: // prepare a tree entry with the new filename -- cgit v1.2.3 From ab6c760b3b58ec5b95b7d3af4fda941e8532dd70 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 23 Apr 2012 22:18:44 +0300 Subject: core: change initial sync with --delay, video stream switch Make A/V sync at the start of playback with nonzero --delay behave the same way as it does when seeking to the beginning later, meaning video plays from the start and audio is truncated or padded with silence to match timing. This was already the default behavior in case the streams in the file started at different times, but not if the mismatch was due to --delay. Trigger similar audio synchronization when switching to a new video stream. Previously, switching a video stream on after playing for some time in audio-only mode was buggy and caused initial desync equal to the duration of prior audio-only playback. --- mplayer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mplayer.c b/mplayer.c index 0f63907df8..aecbce8275 100644 --- a/mplayer.c +++ b/mplayer.c @@ -2712,6 +2712,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 @@ -4837,7 +4839,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) { -- cgit v1.2.3 From 9ba3e1ddb25a780f31ad2ed3e2fbb6682c098456 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 23 Apr 2012 22:43:13 +0300 Subject: win32: core: wake up more often to poll for input MSWindows does not have properly working support for detecting events on file descriptors. As a result the current mplayer2 code does not support waking up when new input events occur. Make the central playloop wake up more often to poll for events; otherwise response would be a lot laggier than on better operating systems during pause or other cases where the process would not otherwise wake up. --- mplayer.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mplayer.c b/mplayer.c index aecbce8275..2ca8518335 100644 --- a/mplayer.c +++ b/mplayer.c @@ -31,6 +31,16 @@ #if defined(__MINGW32__) || defined(__CYGWIN__) #include +// 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 #include @@ -3421,7 +3431,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) { @@ -4255,7 +4265,8 @@ play_next_file: uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_VO); play_tree_t *entry = NULL; mp_cmd_t *cmd; - while (!(cmd = mp_input_get_cmd(mpctx->input, 500, false))); + 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 -- cgit v1.2.3 From 237f44db44b5479c78c90c1a045e0123a2f9c2b8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 11 Dec 2011 11:48:33 +0100 Subject: vo_corevideo: use soft tabs (4 spaces) --- libvo/vo_corevideo.m | 1368 +++++++++++++++++++++++++------------------------- 1 file changed, 684 insertions(+), 684 deletions(-) diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m index e937460636..5e1dd71259 100644 --- a/libvo/vo_corevideo.m +++ b/libvo/vo_corevideo.m @@ -92,68 +92,68 @@ static BOOL isLeopardOrLater; static vo_info_t info = { - "Mac OS X Core Video", - "corevideo", - "Nicolas Plourde ", - "" + "Mac OS X Core Video", + "corevideo", + "Nicolas Plourde ", + "" }; LIBVO_EXTERN(corevideo) static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { - switch (image_format) - { - case IMGFMT_RGB24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,image_data+3*(y0*image_width+x0),3*image_width); - break; - case IMGFMT_ARGB: - case IMGFMT_BGRA: - vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width); - break; - case IMGFMT_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2); - break; - } + switch (image_format) + { + case IMGFMT_RGB24: + vo_draw_alpha_rgb24(w,h,src,srca,stride,image_data+3*(y0*image_width+x0),3*image_width); + break; + case IMGFMT_ARGB: + case IMGFMT_BGRA: + vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width); + break; + case IMGFMT_YUY2: + vo_draw_alpha_yuy2(w,h,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2); + break; + } } static void update_screen_info(void) { - if (screen_id == -1 && xinerama_screen > -1) - screen_id = xinerama_screen; - - screen_array = [NSScreen screens]; - if(screen_id >= (int)[screen_array count]) - { - mp_msg(MSGT_VO, MSGL_INFO, "[vo_corevideo] Device ID %d does not exist, falling back to main device\n", screen_id); - screen_id = -1; - } - if (screen_id < 0 && [mpGLView window]) - screen_handle = [[mpGLView window] screen]; - else - screen_handle = [screen_array objectAtIndex:(screen_id < 0 ? 0 : screen_id)]; - - screen_frame = [screen_handle frame]; - vo_screenwidth = screen_frame.size.width; - vo_screenheight = screen_frame.size.height; - xinerama_x = xinerama_y = 0; - aspect_save_screenres(vo_screenwidth, vo_screenheight); + if (screen_id == -1 && xinerama_screen > -1) + screen_id = xinerama_screen; + + screen_array = [NSScreen screens]; + if(screen_id >= (int)[screen_array count]) + { + mp_msg(MSGT_VO, MSGL_INFO, "[vo_corevideo] Device ID %d does not exist, falling back to main device\n", screen_id); + screen_id = -1; + } + if (screen_id < 0 && [mpGLView window]) + screen_handle = [[mpGLView window] screen]; + else + screen_handle = [screen_array objectAtIndex:(screen_id < 0 ? 0 : screen_id)]; + + screen_frame = [screen_handle frame]; + vo_screenwidth = screen_frame.size.width; + vo_screenheight = screen_frame.size.height; + xinerama_x = xinerama_y = 0; + aspect_save_screenres(vo_screenwidth, vo_screenheight); } static void free_file_specific(void) { - if(shared_buffer) - { - [mplayerosxProto stop]; - mplayerosxProto = nil; - [mplayerosxProxy release]; - mplayerosxProxy = nil; - - if (munmap(image_data, image_width*image_height*image_bytes) == -1) - mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] uninit: munmap failed. Error: %s\n", strerror(errno)); - - if (shm_unlink(buffer_name) == -1) - mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] uninit: shm_unlink failed. Error: %s\n", strerror(errno)); + if(shared_buffer) + { + [mplayerosxProto stop]; + mplayerosxProto = nil; + [mplayerosxProxy release]; + mplayerosxProxy = nil; + + if (munmap(image_data, image_width*image_height*image_bytes) == -1) + mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] uninit: munmap failed. Error: %s\n", strerror(errno)); + + if (shm_unlink(buffer_name) == -1) + mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] uninit: shm_unlink failed. Error: %s\n", strerror(errno)); } else { free(image_datas[0]); if (vo_doublebuffering) @@ -166,165 +166,165 @@ static void free_file_specific(void) static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) { - free_file_specific(); - - //misc mplayer setup - image_width = width; - image_height = height; - switch (image_format) - { - case IMGFMT_RGB24: - image_depth = 24; - break; - case IMGFMT_ARGB: - case IMGFMT_BGRA: - image_depth = 32; - break; - case IMGFMT_YUY2: - image_depth = 16; - break; - } - image_bytes = (image_depth + 7) / 8; - - if(!shared_buffer) - { - config_movie_aspect((float)d_width/d_height); - - vo_dwidth = d_width *= mpGLView->winSizeMult; - vo_dheight = d_height *= mpGLView->winSizeMult; - - image_data = malloc(image_width*image_height*image_bytes); - image_datas[0] = image_data; - if (vo_doublebuffering) - image_datas[1] = malloc(image_width*image_height*image_bytes); - image_page = 0; - - vo_fs = flags & VOFLAG_FULLSCREEN; - - //config OpenGL View - [mpGLView config]; - [mpGLView reshape]; - } - else - { - int shm_fd; - mp_msg(MSGT_VO, MSGL_INFO, "[vo_corevideo] writing output to a shared buffer " - "named \"%s\"\n",buffer_name); - - // create shared memory - shm_fd = shm_open(buffer_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - if (shm_fd == -1) - { - mp_msg(MSGT_VO, MSGL_FATAL, - "[vo_corevideo] failed to open shared memory. Error: %s\n", strerror(errno)); - return 1; - } - - - if (ftruncate(shm_fd, image_width*image_height*image_bytes) == -1) - { - mp_msg(MSGT_VO, MSGL_FATAL, - "[vo_corevideo] failed to size shared memory, possibly already in use. Error: %s\n", strerror(errno)); - close(shm_fd); - shm_unlink(buffer_name); - return 1; - } - - image_data = mmap(NULL, image_width*image_height*image_bytes, - PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); - close(shm_fd); - - if (image_data == MAP_FAILED) - { - mp_msg(MSGT_VO, MSGL_FATAL, - "[vo_corevideo] failed to map shared memory. Error: %s\n", strerror(errno)); - shm_unlink(buffer_name); - return 1; - } - - //connect to mplayerosx - mplayerosxProxy=[NSConnection rootProxyForConnectionWithRegisteredName:[NSString stringWithCString:buffer_name] host:nil]; - if ([mplayerosxProxy conformsToProtocol:@protocol(MPlayerOSXVOProto)]) { - [mplayerosxProxy setProtocolForProxy:@protocol(MPlayerOSXVOProto)]; - mplayerosxProto = (id )mplayerosxProxy; - [mplayerosxProto startWithWidth: image_width withHeight: image_height withBytes: image_bytes withAspect:d_width*100/d_height]; - } - else { - [mplayerosxProxy release]; - mplayerosxProxy = nil; - mplayerosxProto = nil; - } - } - return 0; + free_file_specific(); + + //misc mplayer setup + image_width = width; + image_height = height; + switch (image_format) + { + case IMGFMT_RGB24: + image_depth = 24; + break; + case IMGFMT_ARGB: + case IMGFMT_BGRA: + image_depth = 32; + break; + case IMGFMT_YUY2: + image_depth = 16; + break; + } + image_bytes = (image_depth + 7) / 8; + + if(!shared_buffer) + { + config_movie_aspect((float)d_width/d_height); + + vo_dwidth = d_width *= mpGLView->winSizeMult; + vo_dheight = d_height *= mpGLView->winSizeMult; + + image_data = malloc(image_width*image_height*image_bytes); + image_datas[0] = image_data; + if (vo_doublebuffering) + image_datas[1] = malloc(image_width*image_height*image_bytes); + image_page = 0; + + vo_fs = flags & VOFLAG_FULLSCREEN; + + //config OpenGL View + [mpGLView config]; + [mpGLView reshape]; + } + else + { + int shm_fd; + mp_msg(MSGT_VO, MSGL_INFO, "[vo_corevideo] writing output to a shared buffer " + "named \"%s\"\n",buffer_name); + + // create shared memory + shm_fd = shm_open(buffer_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (shm_fd == -1) + { + mp_msg(MSGT_VO, MSGL_FATAL, + "[vo_corevideo] failed to open shared memory. Error: %s\n", strerror(errno)); + return 1; + } + + + if (ftruncate(shm_fd, image_width*image_height*image_bytes) == -1) + { + mp_msg(MSGT_VO, MSGL_FATAL, + "[vo_corevideo] failed to size shared memory, possibly already in use. Error: %s\n", strerror(errno)); + close(shm_fd); + shm_unlink(buffer_name); + return 1; + } + + image_data = mmap(NULL, image_width*image_height*image_bytes, + PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + close(shm_fd); + + if (image_data == MAP_FAILED) + { + mp_msg(MSGT_VO, MSGL_FATAL, + "[vo_corevideo] failed to map shared memory. Error: %s\n", strerror(errno)); + shm_unlink(buffer_name); + return 1; + } + + //connect to mplayerosx + mplayerosxProxy=[NSConnection rootProxyForConnectionWithRegisteredName:[NSString stringWithCString:buffer_name] host:nil]; + if ([mplayerosxProxy conformsToProtocol:@protocol(MPlayerOSXVOProto)]) { + [mplayerosxProxy setProtocolForProxy:@protocol(MPlayerOSXVOProto)]; + mplayerosxProto = (id )mplayerosxProxy; + [mplayerosxProto startWithWidth: image_width withHeight: image_height withBytes: image_bytes withAspect:d_width*100/d_height]; + } + else { + [mplayerosxProxy release]; + mplayerosxProxy = nil; + mplayerosxProto = nil; + } + } + return 0; } static void check_events(void) { - if (mpGLView) - [mpGLView check_events]; + if (mpGLView) + [mpGLView check_events]; } static void draw_osd(void) { - vo_draw_text(image_width, image_height, draw_alpha); + vo_draw_text(image_width, image_height, draw_alpha); } static void flip_page(void) { - if(shared_buffer) { - NSAutoreleasePool *pool = [NSAutoreleasePool new]; - [mplayerosxProto render]; - [pool release]; - } else { - [mpGLView setCurrentTexture]; - [mpGLView render]; - if (vo_doublebuffering) { - image_page = 1 - image_page; - image_data = image_datas[image_page]; - } - } + if(shared_buffer) { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + [mplayerosxProto render]; + [pool release]; + } else { + [mpGLView setCurrentTexture]; + [mpGLView render]; + if (vo_doublebuffering) { + image_page = 1 - image_page; + image_data = image_datas[image_page]; + } + } } static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y) { - return 0; + return 0; } static int draw_frame(uint8_t *src[]) { - return 0; + return 0; } static uint32_t draw_image(mp_image_t *mpi) { - memcpy_pic(image_data, mpi->planes[0], image_width*image_bytes, image_height, image_width*image_bytes, mpi->stride[0]); + memcpy_pic(image_data, mpi->planes[0], image_width*image_bytes, image_height, image_width*image_bytes, mpi->stride[0]); - return 0; + return 0; } static int query_format(uint32_t format) { const int supportflags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN; - image_format = format; + image_format = format; switch(format) - { - case IMGFMT_YUY2: - pixelFormat = kYUVSPixelFormat; - return supportflags; - - case IMGFMT_RGB24: - pixelFormat = k24RGBPixelFormat; - return supportflags; - - case IMGFMT_ARGB: - pixelFormat = k32ARGBPixelFormat; - return supportflags; - - case IMGFMT_BGRA: - pixelFormat = k32BGRAPixelFormat; - return supportflags; + { + case IMGFMT_YUY2: + pixelFormat = kYUVSPixelFormat; + return supportflags; + + case IMGFMT_RGB24: + pixelFormat = k24RGBPixelFormat; + return supportflags; + + case IMGFMT_ARGB: + pixelFormat = k32ARGBPixelFormat; + return supportflags; + + case IMGFMT_BGRA: + pixelFormat = k32BGRAPixelFormat; + return supportflags; } return 0; } @@ -360,81 +360,81 @@ static const opt_t subopts[] = { static int preinit(const char *arg) { - // set defaults - screen_id = -1; - shared_buffer = false; - buffer_name = NULL; - - if (subopt_parse(arg, subopts) != 0) { - mp_msg(MSGT_VO, MSGL_FATAL, - "\n-vo corevideo command line help:\n" - "Example: mplayer -vo corevideo:device_id=1:shared_buffer:buffer_name=mybuff\n" - "\nOptions:\n" - " device_id=<0-...>\n" - " Set screen device ID for fullscreen.\n" - " shared_buffer\n" - " Write output to a shared memory buffer instead of displaying it.\n" - " buffer_name=\n" - " Name of the shared buffer created with shm_open() as well as\n" - " the name of the NSConnection MPlayer will try to open.\n" - " Setting buffer_name implicitly enables shared_buffer.\n" - "\n" ); - return -1; - } - - autoreleasepool = [[NSAutoreleasePool alloc] init]; - - if (!buffer_name) - buffer_name = strdup(DEFAULT_BUFFER_NAME); - else - shared_buffer = true; - - if(!shared_buffer) - { - NSApplicationLoad(); - NSApp = [NSApplication sharedApplication]; - isLeopardOrLater = floor(NSAppKitVersionNumber) > 824; - - osx_foreground_hack(); - - if(!mpGLView) - { - mpGLView = [[MPlayerOpenGLView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:[MPlayerOpenGLView defaultPixelFormat]]; - [mpGLView autorelease]; - } - // Install an event handler so the Quit menu entry works - // The proper way using NSApp setDelegate: and - // applicationShouldTerminate: does not work, - // probably NSApplication never installs its handler. - [[NSAppleEventManager sharedAppleEventManager] - setEventHandler:mpGLView - andSelector:@selector(handleQuitEvent:withReplyEvent:) - forEventClass:kCoreEventClass - andEventID:kAEQuitApplication]; - - [mpGLView display]; - [mpGLView preinit]; - } + // set defaults + screen_id = -1; + shared_buffer = false; + buffer_name = NULL; + + if (subopt_parse(arg, subopts) != 0) { + mp_msg(MSGT_VO, MSGL_FATAL, + "\n-vo corevideo command line help:\n" + "Example: mplayer -vo corevideo:device_id=1:shared_buffer:buffer_name=mybuff\n" + "\nOptions:\n" + " device_id=<0-...>\n" + " Set screen device ID for fullscreen.\n" + " shared_buffer\n" + " Write output to a shared memory buffer instead of displaying it.\n" + " buffer_name=\n" + " Name of the shared buffer created with shm_open() as well as\n" + " the name of the NSConnection MPlayer will try to open.\n" + " Setting buffer_name implicitly enables shared_buffer.\n" + "\n" ); + return -1; + } + + autoreleasepool = [[NSAutoreleasePool alloc] init]; + + if (!buffer_name) + buffer_name = strdup(DEFAULT_BUFFER_NAME); + else + shared_buffer = true; + + if(!shared_buffer) + { + NSApplicationLoad(); + NSApp = [NSApplication sharedApplication]; + isLeopardOrLater = floor(NSAppKitVersionNumber) > 824; + + osx_foreground_hack(); + + if(!mpGLView) + { + mpGLView = [[MPlayerOpenGLView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:[MPlayerOpenGLView defaultPixelFormat]]; + [mpGLView autorelease]; + } + // Install an event handler so the Quit menu entry works + // The proper way using NSApp setDelegate: and + // applicationShouldTerminate: does not work, + // probably NSApplication never installs its handler. + [[NSAppleEventManager sharedAppleEventManager] + setEventHandler:mpGLView + andSelector:@selector(handleQuitEvent:withReplyEvent:) + forEventClass:kCoreEventClass + andEventID:kAEQuitApplication]; + + [mpGLView display]; + [mpGLView preinit]; + } return 0; } static int control(uint32_t request, void *data) { - switch (request) - { - case VOCTRL_DRAW_IMAGE: return draw_image(data); - case VOCTRL_PAUSE: return int_pause = 1; - case VOCTRL_RESUME: return int_pause = 0; - case VOCTRL_QUERY_FORMAT: return query_format(*(uint32_t*)data); - case VOCTRL_ONTOP: vo_ontop = !vo_ontop; if(!shared_buffer){ [mpGLView ontop]; } else { [mplayerosxProto ontop]; } return VO_TRUE; - case VOCTRL_ROOTWIN: vo_rootwin = !vo_rootwin; [mpGLView rootwin]; return VO_TRUE; - case VOCTRL_FULLSCREEN: vo_fs = !vo_fs; if(!shared_buffer){ [mpGLView fullscreen: NO]; } else { [mplayerosxProto toggleFullscreen]; } return VO_TRUE; - case VOCTRL_GET_PANSCAN: return VO_TRUE; - case VOCTRL_SET_PANSCAN: [mpGLView panscan]; return VO_TRUE; - case VOCTRL_UPDATE_SCREENINFO: update_screen_info(); return VO_TRUE; - } - return VO_NOTIMPL; + switch (request) + { + case VOCTRL_DRAW_IMAGE: return draw_image(data); + case VOCTRL_PAUSE: return int_pause = 1; + case VOCTRL_RESUME: return int_pause = 0; + case VOCTRL_QUERY_FORMAT: return query_format(*(uint32_t*)data); + case VOCTRL_ONTOP: vo_ontop = !vo_ontop; if(!shared_buffer){ [mpGLView ontop]; } else { [mplayerosxProto ontop]; } return VO_TRUE; + case VOCTRL_ROOTWIN: vo_rootwin = !vo_rootwin; [mpGLView rootwin]; return VO_TRUE; + case VOCTRL_FULLSCREEN: vo_fs = !vo_fs; if(!shared_buffer){ [mpGLView fullscreen: NO]; } else { [mplayerosxProto toggleFullscreen]; } return VO_TRUE; + case VOCTRL_GET_PANSCAN: return VO_TRUE; + case VOCTRL_SET_PANSCAN: [mpGLView panscan]; return VO_TRUE; + case VOCTRL_UPDATE_SCREENINFO: update_screen_info(); return VO_TRUE; + } + return VO_NOTIMPL; } ////////////////////////////////////////////////////////////////////////// @@ -443,167 +443,167 @@ static int control(uint32_t request, void *data) @implementation MPlayerOpenGLView - (void) preinit { - NSOpenGLContext *glContext; - GLint swapInterval = 1; - CVReturn error; - - //init menu - [self initMenu]; - - //create window - window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) - styleMask:NSTitledWindowMask|NSTexturedBackgroundWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask - backing:NSBackingStoreBuffered defer:NO]; - - [window autorelease]; - [window setDelegate:mpGLView]; - [window setContentView:mpGLView]; - [window setInitialFirstResponder:mpGLView]; - [window setAcceptsMouseMovedEvents:YES]; - [window setTitle:@"MPlayer - The Movie Player"]; - - isFullscreen = 0; - winSizeMult = 1; - - //create OpenGL Context - glContext = [[NSOpenGLContext alloc] initWithFormat:[NSOpenGLView defaultPixelFormat] shareContext:nil]; - - [self setOpenGLContext:glContext]; - [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; - [glContext setView:self]; - [glContext makeCurrentContext]; - [glContext release]; - - error = CVOpenGLTextureCacheCreate(NULL, 0, [glContext CGLContextObj], [[self pixelFormat] CGLPixelFormatObj], 0, &textureCache); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture Cache(%d)\n", error); + NSOpenGLContext *glContext; + GLint swapInterval = 1; + CVReturn error; + + //init menu + [self initMenu]; + + //create window + window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) + styleMask:NSTitledWindowMask|NSTexturedBackgroundWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask + backing:NSBackingStoreBuffered defer:NO]; + + [window autorelease]; + [window setDelegate:mpGLView]; + [window setContentView:mpGLView]; + [window setInitialFirstResponder:mpGLView]; + [window setAcceptsMouseMovedEvents:YES]; + [window setTitle:@"MPlayer - The Movie Player"]; + + isFullscreen = 0; + winSizeMult = 1; + + //create OpenGL Context + glContext = [[NSOpenGLContext alloc] initWithFormat:[NSOpenGLView defaultPixelFormat] shareContext:nil]; + + [self setOpenGLContext:glContext]; + [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + [glContext setView:self]; + [glContext makeCurrentContext]; + [glContext release]; + + error = CVOpenGLTextureCacheCreate(NULL, 0, [glContext CGLContextObj], [[self pixelFormat] CGLPixelFormatObj], 0, &textureCache); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture Cache(%d)\n", error); } - (void) releaseVideoSpecific { - CVPixelBufferRelease(frameBuffers[0]); - frameBuffers[0] = NULL; - CVPixelBufferRelease(frameBuffers[1]); - frameBuffers[1] = NULL; - CVOpenGLTextureRelease(texture); - texture = NULL; + CVPixelBufferRelease(frameBuffers[0]); + frameBuffers[0] = NULL; + CVPixelBufferRelease(frameBuffers[1]); + frameBuffers[1] = NULL; + CVOpenGLTextureRelease(texture); + texture = NULL; } - (void) dealloc { - [self releaseVideoSpecific]; - CVOpenGLTextureCacheRelease(textureCache); - textureCache = NULL; - [self setOpenGLContext:nil]; - [super dealloc]; + [self releaseVideoSpecific]; + CVOpenGLTextureCacheRelease(textureCache); + textureCache = NULL; + [self setOpenGLContext:nil]; + [super dealloc]; } - (void) config { - NSRect visibleFrame; - CVReturn error = kCVReturnSuccess; - - //config window - [window setContentSize:NSMakeSize(vo_dwidth, vo_dheight)]; - - // Use visibleFrame to position the window taking the menu bar and dock into account. - // Also flip vo_dy since the screen origin is in the bottom left on OSX. - update_screen_info(); - visibleFrame = [screen_handle visibleFrame]; - [window setFrameTopLeftPoint:NSMakePoint( - visibleFrame.origin.x + vo_dx, - visibleFrame.origin.y + visibleFrame.size.height - vo_dy)]; - - [self releaseVideoSpecific]; - error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, image_datas[0], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[0]); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Buffer(%d)\n", error); - if (vo_doublebuffering) { - error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, image_datas[1], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[1]); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Double Buffer(%d)\n", error); - } - - error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, textureCache, frameBuffers[image_page], 0, &texture); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture(%d)\n", error); - - //show window - [window makeKeyAndOrderFront:mpGLView]; - - if(vo_rootwin) - [mpGLView rootwin]; - - if(vo_fs) - [mpGLView fullscreen: NO]; - - if(vo_ontop) - [mpGLView ontop]; + NSRect visibleFrame; + CVReturn error = kCVReturnSuccess; + + //config window + [window setContentSize:NSMakeSize(vo_dwidth, vo_dheight)]; + + // Use visibleFrame to position the window taking the menu bar and dock into account. + // Also flip vo_dy since the screen origin is in the bottom left on OSX. + update_screen_info(); + visibleFrame = [screen_handle visibleFrame]; + [window setFrameTopLeftPoint:NSMakePoint( + visibleFrame.origin.x + vo_dx, + visibleFrame.origin.y + visibleFrame.size.height - vo_dy)]; + + [self releaseVideoSpecific]; + error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, image_datas[0], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[0]); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Buffer(%d)\n", error); + if (vo_doublebuffering) { + error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, image_datas[1], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[1]); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Double Buffer(%d)\n", error); + } + + error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, textureCache, frameBuffers[image_page], 0, &texture); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture(%d)\n", error); + + //show window + [window makeKeyAndOrderFront:mpGLView]; + + if(vo_rootwin) + [mpGLView rootwin]; + + if(vo_fs) + [mpGLView fullscreen: NO]; + + if(vo_ontop) + [mpGLView ontop]; } /* - Init Menu + Init Menu */ - (void)initMenu { - NSMenu *menu, *aspectMenu; - NSMenuItem *menuItem; + NSMenu *menu, *aspectMenu; + NSMenuItem *menuItem; - menu = [[NSMenu new] autorelease]; - menuItem = [[NSMenuItem new] autorelease]; - [menu addItem: menuItem]; - [NSApp setMainMenu: menu]; + menu = [[NSMenu new] autorelease]; + menuItem = [[NSMenuItem new] autorelease]; + [menu addItem: menuItem]; + [NSApp setMainMenu: menu]; //Create Movie Menu - menu = [[NSMenu alloc] initWithTitle:@"Movie"]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Half Size" action:@selector(menuAction:) keyEquivalent:@"0"]; [menu addItem:menuItem]; - kHalfScreenCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Normal Size" action:@selector(menuAction:) keyEquivalent:@"1"]; [menu addItem:menuItem]; - kNormalScreenCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Double Size" action:@selector(menuAction:) keyEquivalent:@"2"]; [menu addItem:menuItem]; - kDoubleScreenCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Full Size" action:@selector(menuAction:) keyEquivalent:@"f"]; [menu addItem:menuItem]; - kFullScreenCmd = menuItem; - menuItem = [NSMenuItem separatorItem]; [menu addItem:menuItem]; - - aspectMenu = [[NSMenu alloc] initWithTitle:@"Aspect Ratio"]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Keep" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - if(vo_keepaspect) [menuItem setState:NSOnState]; - kKeepAspectCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Pan-Scan" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - if(vo_panscan) [menuItem setState:NSOnState]; - kPanScanCmd = menuItem; - menuItem = [NSMenuItem separatorItem]; [aspectMenu addItem:menuItem]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Original" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - kAspectOrgCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"4:3" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - kAspectFullCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"16:9" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - kAspectWideCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Aspect Ratio" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:aspectMenu]; - [menu addItem:menuItem]; - [aspectMenu release]; - - //Add to menubar - menuItem = [[NSMenuItem alloc] initWithTitle:@"Movie" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:menu]; - [[NSApp mainMenu] addItem:menuItem]; + menu = [[NSMenu alloc] initWithTitle:@"Movie"]; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Half Size" action:@selector(menuAction:) keyEquivalent:@"0"]; [menu addItem:menuItem]; + kHalfScreenCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Normal Size" action:@selector(menuAction:) keyEquivalent:@"1"]; [menu addItem:menuItem]; + kNormalScreenCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Double Size" action:@selector(menuAction:) keyEquivalent:@"2"]; [menu addItem:menuItem]; + kDoubleScreenCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Full Size" action:@selector(menuAction:) keyEquivalent:@"f"]; [menu addItem:menuItem]; + kFullScreenCmd = menuItem; + menuItem = [NSMenuItem separatorItem]; [menu addItem:menuItem]; + + aspectMenu = [[NSMenu alloc] initWithTitle:@"Aspect Ratio"]; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Keep" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; + if(vo_keepaspect) [menuItem setState:NSOnState]; + kKeepAspectCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Pan-Scan" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; + if(vo_panscan) [menuItem setState:NSOnState]; + kPanScanCmd = menuItem; + menuItem = [NSMenuItem separatorItem]; [aspectMenu addItem:menuItem]; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Original" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; + kAspectOrgCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"4:3" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; + kAspectFullCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"16:9" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; + kAspectWideCmd = menuItem; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Aspect Ratio" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:aspectMenu]; + [menu addItem:menuItem]; + [aspectMenu release]; + + //Add to menubar + menuItem = [[NSMenuItem alloc] initWithTitle:@"Movie" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:menu]; + [[NSApp mainMenu] addItem:menuItem]; //Create Window Menu - menu = [[NSMenu alloc] initWithTitle:@"Window"]; + menu = [[NSMenu alloc] initWithTitle:@"Window"]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [menu addItem:menuItem]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""]; [menu addItem:menuItem]; + menuItem = [[NSMenuItem alloc] initWithTitle:@"Mi