summaryrefslogtreecommitdiffstats
path: root/mplayer.c
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-09-18 16:27:55 +0300
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-09-18 17:12:53 +0300
commit350fc4f5a2f6f4fdf9cc689d786d525f6397df5d (patch)
tree4f133589230adc4d87d296d5b7300b811c941bdd /mplayer.c
parent6847e5e297821bdb56ec978100243bc452f508f4 (diff)
downloadmpv-350fc4f5a2f6f4fdf9cc689d786d525f6397df5d.tar.bz2
mpv-350fc4f5a2f6f4fdf9cc689d786d525f6397df5d.tar.xz
core/VO: Allow VO drivers to add/modify frames
Add interfaces to allow VO drivers to add or remove frames from the video stream and to alter timestamps. Currently this functionality only works with in correct-pts mode. Use the new functionality in vo_vdpau to properly support frame-adding deinterlace modes. Frames added by the VDPAU deinterlacing code are now properly timed. Before every second frame was always shown immediately (probably next monitor refresh) after the previous one, even if you were watching things in slow motion, and framestepping didn't stop at them at all. When seeking the deinterlace algorithm is no longer fed a mix of frames from old and new positions. As a side effect of the changes a problem with resize events was also fixed. Resizing calls video_to_output_surface() to render the frame at the new resolution, but before this function also changed the list of history frames, so resizing could give an image different from the original one, and also corrupt next frames due to them seeing the wrong history. Now the function has no such side effects. There are more resize-related problems though that will be fixed in a later commit. The deint_mpi[] list of reserved frames is increased from 2 to 3 entries for reasons related to the above. Having 2 entries is enough when you initially get a new frame in draw_image() because then you'll have those two entries plus the new one for a total of 3 (the code relied on the oldest mpi implicitly staying reserved for the duration of the call even after usage count was decreased). However if you want to be able to reproduce the rendering outside draw_image(), relying on the explicitly reserved list only, then it needs to store 3 entries.
Diffstat (limited to 'mplayer.c')
-rw-r--r--mplayer.c27
1 files changed, 13 insertions, 14 deletions
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;