summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--command.c11
-rw-r--r--libmpcodecs/dec_video.c9
-rw-r--r--libmpcodecs/dec_video.h1
-rw-r--r--libmpcodecs/vf.h1
-rw-r--r--libmpcodecs/vf_expand.c6
-rw-r--r--libmpcodecs/vf_vo.c3
-rw-r--r--libvo/video_out.h2
-rw-r--r--libvo/vo_xv.c75
-rw-r--r--mp_core.h1
-rw-r--r--mplayer.c32
10 files changed, 115 insertions, 26 deletions
diff --git a/command.c b/command.c
index 72fe83c2e7..6487a8b346 100644
--- a/command.c
+++ b/command.c
@@ -573,10 +573,14 @@ static int mp_property_pause(m_option_t *prop, int action, void *arg,
return M_PROPERTY_OK;
case M_PROPERTY_STEP_UP:
case M_PROPERTY_STEP_DOWN:
- if (mpctx->paused)
+ if (mpctx->paused) {
unpause_player(mpctx);
- else
+ mpctx->osd_function = OSD_PLAY;
+ }
+ else {
pause_player(mpctx);
+ mpctx->osd_function = OSD_PAUSE;
+ }
return M_PROPERTY_OK;
default:
return m_property_flag(prop, action, arg, &mpctx->paused);
@@ -2520,8 +2524,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
} break;
case MP_CMD_FRAME_STEP:
- mpctx->step_frames++;
- unpause_player(mpctx);
+ add_step_frame(mpctx);
break;
case MP_CMD_FILE_FILTER:
diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c
index 291859abb2..8cdc3e7b1d 100644
--- a/libmpcodecs/dec_video.c
+++ b/libmpcodecs/dec_video.c
@@ -6,6 +6,7 @@
#include <malloc.h>
#endif
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#include "mp_msg.h"
@@ -138,6 +139,14 @@ int set_rectangle(sh_video_t *sh_video, int param, int value)
return 0;
}
+int redraw_osd(struct sh_video *sh_video, struct osd_state *osd)
+{
+ struct vf_instance *vf = sh_video->vfilter;
+ if (vf->control(vf, VFCTRL_REDRAW_OSD, osd) == true)
+ return 0;
+ return -1;
+}
+
void resync_video_stream(sh_video_t *sh_video)
{
const struct vd_functions *vd = sh_video->vd_driver;
diff --git a/libmpcodecs/dec_video.h b/libmpcodecs/dec_video.h
index 42aa56ecb5..463304bde5 100644
--- a/libmpcodecs/dec_video.h
+++ b/libmpcodecs/dec_video.h
@@ -21,6 +21,7 @@ void set_video_quality(sh_video_t *sh_video, int quality);
int get_video_colors(sh_video_t *sh_video, const char *item, int *value);
int set_video_colors(sh_video_t *sh_video, const char *item, int value);
int set_rectangle(sh_video_t *sh_video, int param, int value);
+int redraw_osd(struct sh_video *sh_video, struct osd_state *osd);
void resync_video_stream(sh_video_t *sh_video);
int get_current_video_decoder_lag(sh_video_t *sh_video);
diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h
index 504c616a73..24d86214d6 100644
--- a/libmpcodecs/vf.h
+++ b/libmpcodecs/vf.h
@@ -91,6 +91,7 @@ typedef struct vf_seteq_s
/* Hack to make the OSD state object available to vf_expand which accesses
* the OSD state outside of normal OSD draw time. */
#define VFCTRL_SET_OSD_OBJ 20
+#define VFCTRL_REDRAW_OSD 21 /* Change user-visible OSD immediately */
#include "vfcap.h"
diff --git a/libmpcodecs/vf_expand.c b/libmpcodecs/vf_expand.c
index cdde44f82b..dec0c524b6 100644
--- a/libmpcodecs/vf_expand.c
+++ b/libmpcodecs/vf_expand.c
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include "config.h"
#include "mp_msg.h"
@@ -419,6 +420,11 @@ static int control(struct vf_instance* vf, int request, void* data){
break;
case VFCTRL_DRAW_OSD:
if(vf->priv->osd_enabled) return CONTROL_TRUE;
+ break;
+ case VFCTRL_REDRAW_OSD:
+ if (vf->priv->osd_enabled)
+ return false;
+ break;
}
#endif
return vf_next_control(vf,request,data);
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index 4f47bc1847..85088487ed 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include "config.h"
#include "mp_msg.h"
@@ -88,6 +89,8 @@ static int control(struct vf_instance* vf, int request, void* data)
if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured?
vo_draw_osd(video_out, data);
return CONTROL_TRUE;
+ case VFCTRL_REDRAW_OSD:
+ return vo_control(video_out, VOCTRL_REDRAW_OSD, data) == true;
case VFCTRL_FLIP_PAGE:
{
if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured?
diff --git a/libvo/video_out.h b/libvo/video_out.h
index cc9544f4fb..308ecb72c9 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -87,6 +87,8 @@ typedef struct {
} mp_colorkey_t;
#define VOCTRL_XOVERLAY_SET_WIN 23
+#define VOCTRL_REDRAW_OSD 24
+
typedef struct {
int x,y;
int w,h;
diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c
index 34f1166f3c..052417422f 100644
--- a/libvo/vo_xv.c
+++ b/libvo/vo_xv.c
@@ -20,6 +20,7 @@ Buffer allocation:
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
+#include <stdbool.h>
#include "config.h"
#include "options.h"
@@ -76,8 +77,11 @@ struct xvctx {
int current_buf;
int current_ip_buf;
int num_buffers;
+ int total_buffers;
+ int have_visible_image_copy;
+ int have_next_image_copy;
int visible_buf;
- XvImage *xvimage[NUM_BUFFERS];
+ XvImage *xvimage[NUM_BUFFERS + 1];
uint32_t image_width;
uint32_t image_height;
uint32_t image_format;
@@ -203,6 +207,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
ctx->is_paused = 0;
ctx->visible_buf = -1;
+ ctx->have_visible_image_copy = false;
+ ctx->have_next_image_copy = false;
/* check image formats */
ctx->xv_format = 0;
@@ -280,13 +286,14 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
}
// In case config has been called before
- for (i = 0; i < ctx->num_buffers; i++)
+ for (i = 0; i < ctx->total_buffers; i++)
deallocate_xvimage(vo, i);
ctx->num_buffers =
vo_doublebuffering ? (vo_directrendering ? NUM_BUFFERS : 2) : 1;
+ ctx->total_buffers = ctx->num_buffers + 1;
- for (i = 0; i < ctx->num_buffers; i++)
+ for (i = 0; i < ctx->total_buffers; i++)
allocate_xvimage(vo, i);
ctx->current_buf = 0;
@@ -397,6 +404,18 @@ static inline void put_xvimage(struct vo *vo, XvImage *xvi)
}
}
+// Only copies luma for planar formats as draw_alpha doesn't change others */
+void copy_backup_image(struct vo *vo, int dest, int src)
+{
+ struct xvctx *ctx = vo->priv;
+
+ XvImage *vb = ctx->xvimage[dest];
+ XvImage *cp = ctx->xvimage[src];
+ memcpy_pic(vb->data + vb->offsets[0], cp->data + cp->offsets[0],
+ vb->width, vb->height,
+ vb->pitches[0], cp->pitches[0]);
+}
+
static void check_events(struct vo *vo)
{
struct xvctx *ctx = vo->priv;
@@ -433,6 +452,23 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
ctx->image_height, ctx->draw_alpha_fnc, vo);
}
+static int redraw_osd(struct vo *vo, struct osd_state *osd)
+{
+ struct xvctx *ctx = vo->priv;
+
+ // Could check if OSD was empty
+ if (!ctx->have_visible_image_copy)
+ return false;
+
+ copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers);
+ int temp = ctx->current_buf;
+ ctx->current_buf = ctx->visible_buf;
+ draw_osd(vo, osd);
+ ctx->current_buf = temp;
+ put_xvimage(vo, ctx->xvimage[ctx->visible_buf]);
+ return true;
+}
+
static void flip_page(struct vo *vo)
{
struct xvctx *ctx = vo->priv;
@@ -441,6 +477,9 @@ static void flip_page(struct vo *vo)
/* remember the currently visible buffer */
ctx->visible_buf = ctx->current_buf;
+ ctx->have_visible_image_copy = ctx->have_next_image_copy;
+ ctx->have_next_image_copy = false;
+
if (ctx->num_buffers > 1) {
ctx->current_buf = vo_directrendering ? 0 : ((ctx->current_buf + 1) %
ctx->num_buffers);
@@ -491,26 +530,30 @@ static int draw_frame(struct vo *vo, uint8_t *src[])
static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
{
struct xvctx *ctx = vo->priv;
- if (mpi->flags & MP_IMGFLAG_DIRECT) {
+
+ ctx->have_next_image_copy = false;
+
+ if (mpi->flags & MP_IMGFLAG_DIRECT)
// direct rendering:
ctx->current_buf = (int) (mpi->priv); // hack!
- return VO_TRUE;
- }
- if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
- return VO_TRUE; // done
- if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ else if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+ ; // done
+ else if (mpi->flags & MP_IMGFLAG_PLANAR)
draw_slice(vo, mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
- return VO_TRUE;
- }
- if (mpi->flags & MP_IMGFLAG_YUV) {
+ else if (mpi->flags & MP_IMGFLAG_YUV)
// packed YUV:
memcpy_pic(ctx->xvimage[ctx->current_buf]->data +
ctx->xvimage[ctx->current_buf]->offsets[0], mpi->planes[0],
mpi->w * (mpi->bpp / 8), mpi->h,
ctx->xvimage[ctx->current_buf]->pitches[0], mpi->stride[0]);
- return VO_TRUE;
+ else
+ return false;
+
+ if (ctx->is_paused) {
+ copy_backup_image(vo, ctx->num_buffers, ctx->current_buf);
+ ctx->have_next_image_copy = true;
}
- return VO_FALSE; // not (yet) supported
+ return true;
}
static uint32_t get_image(struct xvctx *ctx, mp_image_t *mpi)
@@ -599,7 +642,7 @@ static void uninit(struct vo *vo)
XFree(ctx->fo);
ctx->fo = NULL;
}
- for (i = 0; i < ctx->num_buffers; i++)
+ for (i = 0; i < ctx->total_buffers; i++)
deallocate_xvimage(vo, i);
#ifdef CONFIG_XF86VM
if (ctx->mode_switched)
@@ -800,6 +843,8 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_UPDATE_SCREENINFO:
update_xinerama_info(vo);
return VO_TRUE;
+ case VOCTRL_REDRAW_OSD:
+ return redraw_osd(vo, data);
}
return VO_NOTIMPL;
}
diff --git a/mp_core.h b/mp_core.h
index 09df4e7719..a346c75dce 100644
--- a/mp_core.h
+++ b/mp_core.h
@@ -144,5 +144,6 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr
int reinit_video_chain(struct MPContext *mpctx);
void pause_player(struct MPContext *mpctx);
void unpause_player(struct MPContext *mpctx);
+void add_step_frame(struct MPContext *mpctx);
#endif /* MPLAYER_MP_CORE_H */
diff --git a/mplayer.c b/mplayer.c
index 0ccb31b8aa..36e6c5d5f8 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -2322,7 +2322,6 @@ void pause_player(struct MPContext *mpctx)
if (mpctx->paused)
return;
mpctx->paused = 1;
- mpctx->osd_function = OSD_PAUSE;
mpctx->step_frames = 0;
mpctx->time_frame -= get_relative_time(mpctx);
@@ -2338,15 +2337,23 @@ void unpause_player(struct MPContext *mpctx)
if (!mpctx->paused)
return;
mpctx->paused = 0;
- mpctx->osd_function = OSD_PLAY;
if (mpctx->audio_out && mpctx->sh_audio)
mpctx->audio_out->resume(); // resume audio
- if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok)
+ if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok
+ && !mpctx->step_frames)
vo_control(mpctx->video_out, VOCTRL_RESUME, NULL); // resume video
(void)get_relative_time(mpctx); // ignore time that passed during pause
}
+void add_step_frame(struct MPContext *mpctx)
+{
+ mpctx->step_frames++;
+ if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok)
+ vo_control(mpctx->video_out, VOCTRL_PAUSE, NULL);
+ unpause_player(mpctx);
+}
+
static void pause_loop(struct MPContext *mpctx)
{
mp_cmd_t* cmd;
@@ -3781,6 +3788,8 @@ if(!mpctx->sh_video) {
mpctx->stop_play = PT_NEXT_ENTRY;
goto goto_next_file;
}
+ if (blit_frame)
+ vo_osd_changed(0);
if (frame_time < 0)
mpctx->stop_play = AT_END_OF_FILE;
else {
@@ -3905,11 +3914,20 @@ if(auto_quality>0){
if (mpctx->stop_play)
break;
}
- if (mpctx->paused && !(mpctx->stop_play || mpctx->rel_seek_secs
- || mpctx->abs_seek_pos))
- pause_loop(mpctx);
- else
+ if (!mpctx->paused || mpctx->stop_play || mpctx->rel_seek_secs
+ || mpctx->abs_seek_pos)
break;
+ if (mpctx->sh_video) {
+ update_osd_msg(mpctx);
+ int hack = vo_osd_changed(0);
+ vo_osd_changed(hack);
+ if (hack)
+ if (redraw_osd(mpctx->sh_video, mpctx->osd) < 0) {
+ add_step_frame(mpctx);
+ break;
+ }
+ }
+ pause_loop(mpctx);
}
}