summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmpcodecs/vf.h1
-rw-r--r--libmpcodecs/vf_vo.c13
-rw-r--r--libvo/video_out.c40
-rw-r--r--libvo/video_out.h21
-rw-r--r--libvo/vo_vdpau.c189
-rw-r--r--mencoder.c1
-rw-r--r--mp_core.h4
-rw-r--r--mplayer.c27
8 files changed, 195 insertions, 101 deletions
diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h
index 99321b3afa..099135c5da 100644
--- a/libmpcodecs/vf.h
+++ b/libmpcodecs/vf.h
@@ -88,7 +88,6 @@ typedef struct vf_seteq_s
#define VFCTRL_SCREENSHOT 14 /* Make a screenshot */
#define VFCTRL_INIT_EOSD 15 /* Select EOSD renderer */
#define VFCTRL_DRAW_EOSD 16 /* Render EOSD */
-#define VFCTRL_GET_PTS 17 /* Return last pts value that reached vf_vo*/
#define VFCTRL_SET_DEINTERLACE 18 /* Set deinterlacing status */
#define VFCTRL_GET_DEINTERLACE 19 /* Get deinterlacing status */
/* Hack to make the OSD state object available to vf_expand which accesses
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index 7b3e16224f..53dc8267b6 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -22,7 +22,6 @@ extern int sub_visibility;
extern float sub_delay;
struct vf_priv_s {
- double pts;
struct vo *vo;
#ifdef CONFIG_ASS
ASS_Renderer *ass_priv;
@@ -127,7 +126,7 @@ static int control(struct vf_instance* vf, int request, void* data)
case VFCTRL_DRAW_EOSD:
{
mp_eosd_images_t images = {NULL, 2};
- double pts = vf->priv->pts;
+ double pts = video_out->next_pts;
if (!video_out->config_ok || !vf->priv->ass_priv) return CONTROL_FALSE;
if (sub_visibility && vf->priv->ass_priv && ass_track && (pts != MP_NOPTS_VALUE)) {
mp_eosd_res_t res;
@@ -148,11 +147,6 @@ static int control(struct vf_instance* vf, int request, void* data)
return vo_control(video_out, VOCTRL_DRAW_EOSD, &images) == VO_TRUE;
}
#endif
- case VFCTRL_GET_PTS:
- {
- *(double *)data = vf->priv->pts;
- return CONTROL_TRUE;
- }
}
return CONTROL_UNKNOWN;
}
@@ -179,10 +173,9 @@ static void get_image(struct vf_instance* vf,
static int put_image(struct vf_instance* vf,
mp_image_t *mpi, double pts){
if(!video_out->config_ok) return 0; // vo not configured?
- // record pts (potentially modified by filters) for main loop
- vf->priv->pts = pts;
// first check, maybe the vo/vf plugin implements draw_image using mpi:
- if (vo_control(video_out, VOCTRL_DRAW_IMAGE,mpi)==VO_TRUE) return 1; // done.
+ if (vo_draw_image(video_out, mpi, pts) >= 0)
+ return 1;
// nope, fallback to old draw_frame/draw_slice:
if(!(mpi->flags&(MP_IMGFLAG_DIRECT|MP_IMGFLAG_DRAW_CALLBACK))){
// blit frame:
diff --git a/libvo/video_out.c b/libvo/video_out.c
index 9224212b35..b6506406c3 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stdbool.h>
#include <unistd.h>
//#include <sys/mman.h>
@@ -278,6 +279,35 @@ int vo_control(struct vo *vo, uint32_t request, void *data)
return vo->driver->control(vo, request, data);
}
+// Return -1 if driver appears not to support a draw_image interface,
+// 0 otherwise (whether the driver actually drew something or not).
+int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts)
+{
+ if (!vo->config_ok)
+ return 0;
+ if (vo->driver->buffer_frames) {
+ vo->driver->draw_image(vo, mpi, pts);
+ return 0;
+ }
+ vo->frame_loaded = true;
+ vo->next_pts = pts;
+ if (vo_control(vo, VOCTRL_DRAW_IMAGE, mpi) == VO_NOTIMPL)
+ return -1;
+ return 0;
+}
+
+int vo_get_buffered_frame(struct vo *vo, bool eof)
+{
+ if (!vo->config_ok)
+ return -1;
+ if (vo->frame_loaded)
+ return 0;
+ if (!vo->driver->buffer_frames)
+ return -1;
+ vo->driver->get_buffered_frame(vo, eof);
+ return vo->frame_loaded ? 0 : -1;
+}
+
int vo_draw_frame(struct vo *vo, uint8_t *src[])
{
assert(!vo->driver->is_new);
@@ -302,6 +332,8 @@ void vo_flip_page(struct vo *vo)
{
if (!vo->config_ok)
return;
+ vo->frame_loaded = false;
+ vo->next_pts = (-1LL<<63); // MP_NOPTS_VALUE
vo->driver->flip_page(vo);
}
@@ -312,6 +344,14 @@ void vo_check_events(struct vo *vo)
vo->driver->check_events(vo);
}
+void vo_seek_reset(struct vo *vo)
+{
+ if (!vo->config_ok)
+ return;
+ vo_control(vo, VOCTRL_RESET, NULL);
+ vo->frame_loaded = false;
+}
+
void vo_destroy(struct vo *vo)
{
vo->driver->uninit(vo);
diff --git a/libvo/video_out.h b/libvo/video_out.h
index a911bfdd03..4ddeaa827e 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -129,10 +129,14 @@ typedef struct vo_info_s
struct vo;
struct osd_state;
+struct mp_image;
struct vo_driver {
// Driver uses new API
bool is_new;
+ // Driver buffers or adds (deinterlace) frames and will keep track
+ // of pts values itself
+ bool buffer_frames;
// This is set if the driver is not new and contains pointers to
// old-API functions to be used instead of the ones below.
@@ -164,6 +168,16 @@ struct vo_driver {
*/
int (*control)(struct vo *vo, uint32_t request, void *data);
+ void (*draw_image)(struct vo *vo, struct mp_image *mpi, double pts);
+
+ /*
+ * Get extra frames from the VO, such as those added by VDPAU
+ * deinterlace. Preparing the next such frame if any could be done
+ * automatically by the VO after a previous flip_page(), but having
+ * it as a separate step seems to allow making code more robust.
+ */
+ void (*get_buffered_frame)(struct vo *vo, bool eof);
+
/*
* Draw a planar YUV slice to the buffer:
* params:
@@ -214,6 +228,10 @@ struct vo_old_functions {
struct vo {
int config_ok; // Last config call was successful?
int config_count; // Total number of successful config calls
+
+ bool frame_loaded; // Is there a next frame the VO could flip to?
+ double next_pts; // pts value of the next frame if any
+
const struct vo_driver *driver;
void *priv;
struct MPOpts *opts;
@@ -251,11 +269,14 @@ int vo_config(struct vo *vo, uint32_t width, uint32_t height,
void list_video_out(void);
int vo_control(struct vo *vo, uint32_t request, void *data);
+int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts);
+int vo_get_buffered_frame(struct vo *vo, bool eof);
int vo_draw_frame(struct vo *vo, uint8_t *src[]);
int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y);
void vo_draw_osd(struct vo *vo, struct osd_state *osd);
void vo_flip_page(struct vo *vo);
void vo_check_events(struct vo *vo);
+void vo_seek_reset(struct vo *vo);
void vo_destroy(struct vo *vo);
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
index dcd2a7092e..bf760750cc 100644
--- a/libvo/vo_vdpau.c
+++ b/libvo/vo_vdpau.c
@@ -28,6 +28,7 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdbool.h>
@@ -110,14 +111,15 @@ struct vdpctx {
#define osd_surface vc->output_surfaces[NUM_OUTPUT_SURFACES]
VdpOutputSurface output_surfaces[NUM_OUTPUT_SURFACES + 1];
VdpVideoSurface deint_surfaces[3];
- mp_image_t *deint_mpi[2];
+ double deint_pts[3];
+ int deint_queue_pos;
+ mp_image_t *deint_mpi[3];
int output_surface_width, output_surface_height;
VdpVideoMixer video_mixer;
int deint;
int deint_type;
int deint_counter;
- int deint_buffer_past_frames;
int pullup;
float denoise;
float sharpen;
@@ -133,7 +135,6 @@ struct vdpctx {
struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES];
int surface_num;
- int vid_surface_num;
uint32_t vid_width, vid_height;
uint32_t image_format;
VdpChromaType vdp_chroma_type;
@@ -176,14 +177,6 @@ struct vdpctx {
};
-static void push_deint_surface(struct vo *vo, VdpVideoSurface surface)
-{
- struct vdpctx *vc = vo->priv;
- vc->deint_surfaces[2] = vc->deint_surfaces[1];
- vc->deint_surfaces[1] = vc->deint_surfaces[0];
- vc->deint_surfaces[0] = surface;
-}
-
static void flip_page(struct vo *vo);
static void video_to_output_surface(struct vo *vo)
{
@@ -191,41 +184,81 @@ static void video_to_output_surface(struct vo *vo)
struct vdp_functions *vdp = vc->vdp;
VdpTime dummy;
VdpStatus vdp_st;
- int i;
- if (vc->vid_surface_num < 0)
+ if (vc->deint_queue_pos < 0)
return;
- if (vc->deint < 2 || vc->deint_surfaces[0] == VDP_INVALID_HANDLE)
- push_deint_surface(vo, vc->surface_render[vc->vid_surface_num].surface);
+ int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
+ unsigned int dp = vc->deint_queue_pos;
+ // dp==0 means last field of latest frame, 1 earlier field of latest frame,
+ // 2 last field of previous frame and so on
+ if (vc->deint) {
+ field = vc->top_field_first ^ (dp & 1) ?
+ VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD:
+ VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+ }
+ VdpVideoSurface *q = vc->deint_surfaces;
+ const VdpVideoSurface *past_fields = (const VdpVideoSurface []){
+ q[(dp+1)/2], q[(dp+2)/2]};
+ const VdpVideoSurface *future_fields = (const VdpVideoSurface []){
+ q[(dp-1)/2]};
+ VdpOutputSurface output_surface = vc->output_surfaces[vc->surface_num];
+ vdp_st = vdp->presentation_queue_block_until_surface_idle(vc->flip_queue,
+ output_surface,
+ &dummy);
+ CHECK_ST_WARNING("Error when calling "
+ "vdp_presentation_queue_block_until_surface_idle");
+
+ vdp_st = vdp->video_mixer_render(vc->video_mixer, VDP_INVALID_HANDLE,
+ 0, field, 2, past_fields,
+ vc->deint_surfaces[dp/2], 1, future_fields,
+ &vc->src_rect_vid, output_surface,
+ NULL, &vc->out_rect_vid, 0, NULL);
+ CHECK_ST_WARNING("Error when calling vdp_video_mixer_render");
+}
- for (i = 0; i <= (vc->deint > 1); i++) {
- int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
- VdpOutputSurface output_surface;
- if (i) {
- // draw_eosd()
- // draw_osd()
- flip_page(vo);
- }
- if (vc->deint)
- field = (vc->top_field_first == i) ^ (vc->deint > 1) ?
- VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD:
- VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
- output_surface = vc->output_surfaces[vc->surface_num];
- vdp_st = vdp->
- presentation_queue_block_until_surface_idle(vc->flip_queue,
- output_surface,
- &dummy);
- CHECK_ST_WARNING("Error when calling "
- "vdp_presentation_queue_block_until_surface_idle");
-
- vdp_st = vdp->video_mixer_render(vc->video_mixer, VDP_INVALID_HANDLE,
- 0, field, 2, vc->deint_surfaces + 1,
- vc->deint_surfaces[0], 1,
- &vc->surface_render[vc->vid_surface_num].surface,
- &vc->src_rect_vid, output_surface,
- NULL, &vc->out_rect_vid, 0, NULL);
- CHECK_ST_WARNING("Error when calling vdp_video_mixer_render");
- push_deint_surface(vo, vc->surface_render[vc->vid_surface_num].surface);
+static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface,
+ struct mp_image *reserved_mpi, double pts)
+{
+ struct vdpctx *vc = vo->priv;
+
+ if (reserved_mpi)
+ reserved_mpi->usage_count++;
+ if (vc->deint_mpi[2])
+ vc->deint_mpi[2]->usage_count--;
+
+ for (int i = 2; i > 0; i--) {
+ vc->deint_mpi[i] = vc->deint_mpi[i - 1];
+ vc->deint_surfaces[i] = vc->deint_surfaces[i - 1];
+ vc->deint_pts[i] = vc->deint_pts[i - 1];
+ }
+ vc->deint_mpi[0] = reserved_mpi;
+ vc->deint_surfaces[0] = surface;
+ vc->deint_pts[0] = pts;
+
+ vo->frame_loaded = true;
+ vo->next_pts = pts;
+ if (vc->deint >= 2 && vc->deint_queue_pos >= 0) {
+ vc->deint_queue_pos = 2;
+ double diff = vc->deint_pts[0] - vc->deint_pts[1];
+ if (diff > 0 && diff < 0.5)
+ vo->next_pts = (vc->deint_pts[0] + vc->deint_pts[1]) / 2;
+ else
+ vo->next_pts = vc->deint_pts[1];
+ } else
+ vc->deint_queue_pos = 1;
+ video_to_output_surface(vo);
+}
+
+static void forget_frames(struct vo *vo)
+{
+ struct vdpctx *vc = vo->priv;
+
+ vc->deint_queue_pos = -1;
+ for (int i = 0; i < 3; i++) {
+ vc->deint_surfaces[i] = VDP_INVALID_HANDLE;
+ if (vc->deint_mpi[i])
+ vc->deint_mpi[i]->usage_count--;
+ vc->deint_mpi[i] = NULL;
}
}
@@ -563,7 +596,7 @@ int initialize_vdpau_objects(struct vo *vo)
&vc->eosd_surface.max_height);
CHECK_ST_WARNING("Query to get max EOSD surface size failed");
vc->surface_num = 0;
- vc->vid_surface_num = -1;
+ forget_frames(vo);
resize(vo);
return 0;
}
@@ -575,8 +608,7 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo)
vc->decoder = VDP_INVALID_HANDLE;
for (int i = 0; i < MAX_VIDEO_SURFACES; i++)
vc->surface_render[i].surface = VDP_INVALID_HANDLE;
- for (int i = 0; i < 3; i++)
- vc->deint_surfaces[i] = VDP_INVALID_HANDLE;
+ forget_frames(vo);
vc->video_mixer = VDP_INVALID_HANDLE;
vc->flip_queue = VDP_INVALID_HANDLE;
vc->flip_target = VDP_INVALID_HANDLE;
@@ -1033,10 +1065,6 @@ static void flip_page(struct vo *vo)
if (handle_preemption(vo) < 0)
return;
- mp_msg(MSGT_VO, MSGL_DBG2, "\nFLIP_PAGE VID:%u -> OUT:%u\n",
- vc->surface_render[vc->vid_surface_num].surface,
- vc->output_surfaces[vc->surface_num]);
-
vdp_st =
vdp->presentation_queue_display(vc->flip_queue,
vc->output_surfaces[vc->surface_num],
@@ -1095,27 +1123,26 @@ static struct vdpau_render_state *get_surface(struct vo *vo, int number)
return &vc->surface_render[number];
}
-static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
+static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
+ struct mp_image *reserved_mpi = NULL;
+ struct vdpau_render_state *rndr;
+
+ if (vc->is_preempted) {
+ vo->frame_loaded = true;
+ return;
+ }
if (IMGFMT_IS_VDPAU(vc->image_format)) {
- struct vdpau_render_state *rndr = mpi->priv;
- vc->vid_surface_num = rndr - vc->surface_render;
- if (vc->deint_buffer_past_frames) {
- mpi->usage_count++;
- if (vc->deint_mpi[1])
- vc->deint_mpi[1]->usage_count--;
- vc->deint_mpi[1] = vc->deint_mpi[0];
- vc->deint_mpi[0] = mpi;
- }
+ rndr = mpi->priv;
+ reserved_mpi = mpi;
} else if (!(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)) {
VdpStatus vdp_st;
void *destdata[3] = {mpi->planes[0], mpi->planes[2], mpi->planes[1]};
- struct vdpau_render_state *rndr = get_surface(vo, vc->deint_counter);
+ rndr = get_surface(vo, vc->deint_counter);
vc->deint_counter = (vc->deint_counter + 1) % 3;
- vc->vid_surface_num = rndr - vc->surface_render;
if (vc->image_format == IMGFMT_NV12)
destdata[1] = destdata[2];
vdp_st =
@@ -1123,16 +1150,33 @@ static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
vc->vdp_pixel_format,
(const void *const*)destdata,
mpi->stride); // pitch
- CHECK_ST_ERROR("Error when calling "
+ CHECK_ST_WARNING("Error when calling "
"vdp_video_surface_put_bits_y_cb_cr");
- }
+ } else
+ // We don't support slice callbacks so this shouldn't occur -
+ // I think the flags test above in pointless, but I'm adding
+ // this instead of removing it just in case.
+ abort();
if (mpi->fields & MP_IMGFIELD_ORDERED)
vc->top_field_first = !!(mpi->fields & MP_IMGFIELD_TOP_FIRST);
else
vc->top_field_first = 1;
+ add_new_video_surface(vo, rndr->surface, mpi, pts);
+
+ return;
+}
+
+static void get_buffered_frame(struct vo *vo, bool eof)
+{
+ struct vdpctx *vc = vo->priv;
+
+ if (vc->deint_queue_pos < 2)
+ return;
+ vc->deint_queue_pos = 1;
video_to_output_surface(vo);
- return VO_TRUE;
+ vo->next_pts = vc->deint_pts[0];
+ vo->frame_loaded = true;
}
static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
@@ -1287,8 +1331,6 @@ static int preinit(struct vo *vo, const char *arg)
}
if (vc->deint)
vc->deint_type = vc->deint;
- if (vc->deint > 1)
- vc->deint_buffer_past_frames = 1;
char *vdpaulibrary = "libvdpau.so.1";
char *vdpau_device_create = "vdp_device_create_x11";
@@ -1408,7 +1450,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
1, features,
feature_enables);
CHECK_ST_WARNING("Error changing deinterlacing settings");
- vc->deint_buffer_past_frames = 1;
}
return VO_TRUE;
case VOCTRL_PAUSE:
@@ -1420,9 +1461,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_GET_IMAGE:
return get_image(vo, data);
case VOCTRL_DRAW_IMAGE:
- if (vc->is_preempted)
- return true;
- return draw_image(vo, data);
+ abort(); // draw_image() should get called directly
case VOCTRL_BORDER:
vo_x11_border(vo);
resize(vo);
@@ -1476,12 +1515,16 @@ static int control(struct vo *vo, uint32_t request, void *data)
draw_osd(vo, data);
flip_page(vo);
return true;
+ case VOCTRL_RESET:
+ forget_frames(vo);
+ return true;
}
return VO_NOTIMPL;
}
const struct vo_driver video_out_vdpau = {
- .is_new = 1,
+ .is_new = true,
+ .buffer_frames = true,
.info = &(const struct vo_info_s){
"VDPAU with X11",
"vdpau",
@@ -1491,6 +1534,8 @@ const struct vo_driver video_out_vdpau = {
.preinit = preinit,
.config = config,
.control = control,
+ .draw_image = draw_image,
+ .get_buffered_frame = get_buffered_frame,
.draw_slice = draw_slice,
.draw_osd = draw_osd,
.flip_page = flip_page,
diff --git a/mencoder.c b/mencoder.c
index de862fac48..d1472a0568 100644
--- a/mencoder.c
+++ b/mencoder.c
@@ -204,6 +204,7 @@ int vo_config(struct vo *vo, uint32_t width, uint32_t height,
uint32_t d_width, uint32_t d_height, uint32_t flags,
char *title, uint32_t format) { abort(); }
int vo_control(struct vo *vo, uint32_t request, void *data) { abort(); }
+int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts) { abort(); }
int vo_draw_frame(struct vo *vo, uint8_t *src[]) { abort(); }
int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y) { abort(); }
void vo_draw_osd(struct vo *vo, struct osd_state *osd) { abort(); }
diff --git a/mp_core.h b/mp_core.h
index 4092e49efb..a5c7e70c8a 100644
--- a/mp_core.h
+++ b/mp_core.h
@@ -103,10 +103,6 @@ typedef struct MPContext {
struct demux_stream *d_sub;
mixer_t mixer;
struct vo *video_out;
- // Frames buffered in the vo ready to flip. Currently always 0 or 1.
- // This is really a vo variable but currently there's no suitable vo
- // struct.
- int num_buffered_frames;
// Show a video frame as quickly as possible without trying to adjust
// for AV sync. Used when starting a file or after seeking.
diff --git a/mplayer.c b/mplayer.c
index 7553621f9a..52731c7e4b 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -2240,6 +2240,7 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx,
static double update_video(struct MPContext *mpctx, int *blit_frame)
{
struct sh_video *sh_video = mpctx->sh_video;
+ struct vo *video_out = mpctx->video_out;
*blit_frame = 0;
sh_video->vfilter->control(sh_video->vfilter, VFCTRL_SET_OSD_OBJ,
mpctx->osd); // hack for vf_expand
@@ -2248,14 +2249,18 @@ static double update_video(struct MPContext *mpctx, int *blit_frame)
double pts;
- while (1) {
+ bool hit_eof = false;
+ while (!video_out->frame_loaded) {
current_module = "filter_video";
+ if (vo_get_buffered_frame(video_out, hit_eof) >= 0)
+ break;
+ if (hit_eof)
+ return -1;
// XXX Time used in this call is not counted in any performance
// timer now, OSD time is not updated correctly for filter-added frames
if (vf_output_queued_frame(sh_video->vfilter))
break;
unsigned char *packet = NULL;
- bool hit_eof = false;
int in_size = ds_get_packet_pts(mpctx->d_video, &packet, &pts);
if (pts != MP_NOPTS_VALUE)
pts += mpctx->video_offset;
@@ -2278,12 +2283,12 @@ static double update_video(struct MPContext *mpctx, int *blit_frame)
update_osd_msg(mpctx);
current_module = "filter video";
if (filter_video(sh_video, decoded_frame, sh_video->pts))
- break;
- } else if (hit_eof)
- return -1;
+ if (!video_out->config_ok)
+ break; // We'd likely hang in this loop otherwise
+ }
}
- sh_video->vfilter->control(sh_video->vfilter, VFCTRL_GET_PTS, &pts);
+ pts = video_out->next_pts;
if (pts == MP_NOPTS_VALUE) {
mp_msg(MSGT_CPLAYER, MSGL_ERR, "Video pts after filters MISSING\n");
// Try to use decoder pts from before filters
@@ -2539,11 +2544,9 @@ static int seek(MPContext *mpctx, double amount, int style)
if (mpctx->sh_video) {
current_module = "seek_video_reset";
resync_video_stream(mpctx->sh_video);
- if (mpctx->video_out->config_ok)
- vo_control(mpctx->video_out, VOCTRL_RESET, NULL);
+ vo_seek_reset(mpctx->video_out);
mpctx->sh_video->num_buffered_pts = 0;
mpctx->sh_video->last_pts = MP_NOPTS_VALUE;
- mpctx->num_buffered_frames = 0;
mpctx->delay = 0;
mpctx->time_frame = 0;
mpctx->update_video_immediately = true;
@@ -3762,7 +3765,6 @@ if(verbose) term_osd = 0;
int frame_time_remaining=0; // flag
int blit_frame=0;
-mpctx->num_buffered_frames=0;
// Make sure old OSD does not stay around,
// e.g. with -fixed-vo and same-resolution files
@@ -3911,7 +3913,7 @@ if(!mpctx->sh_video) {
vo_pts=mpctx->sh_video->timer*90000.0;
vo_fps=mpctx->sh_video->fps;
- if (!mpctx->num_buffered_frames) {
+ if (!mpctx->video_out->frame_loaded) {
double frame_time = update_video(mpctx, &blit_frame);
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"*** ftime=%5.3f ***\n",frame_time);
if (mpctx->sh_video->vf_initialized < 0) {
@@ -3928,8 +3930,6 @@ if(!mpctx->sh_video) {
if (frame_time < 0)
mpctx->stop_play = AT_END_OF_FILE;
else {
- // might return with !eof && !blit_frame if !correct_pts
- mpctx->num_buffered_frames += blit_frame;
if (mpctx->update_video_immediately) {
// Show this frame immediately, rest normally
mpctx->update_video_immediately = false;
@@ -3981,7 +3981,6 @@ if(!mpctx->sh_video) {
unsigned int t2=GetTimer();
vo_flip_page(mpctx->video_out);
- mpctx->num_buffered_frames--;
mpctx->last_vo_flip_duration = (GetTimer() - t2) * 0.000001;
vout_time_usage += mpctx->last_vo_flip_duration;