summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2008-12-01 19:53:57 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2008-12-09 04:31:07 +0200
commit02efad79a28345e5814af1b60e0bb3c40cb5a941 (patch)
tree83c164e897ed46b24701f8190412d2883f085ba2
parent95f35c4d205daafe4797f28d7ec79f3ebb1952a1 (diff)
downloadmpv-02efad79a28345e5814af1b60e0bb3c40cb5a941.tar.bz2
mpv-02efad79a28345e5814af1b60e0bb3c40cb5a941.tar.xz
Update OSD while paused
When OSD contents change while paused, try to change the OSD drawn in the currently visible frame. If such OSD updates are not supported then advance by one frame and draw the OSD normally. Add some support for OSD redrawing to vo xv. The new xv code makes a copy of the original frame contents before drawing the OSD if MPlayer is already paused when the frame is drawn. If such a copy of the current frame exists then the frame contents can be restored and a different OSD drawn on top of the same frame.
-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);
}
}