mirror of
https://github.com/mpv-player/mpv
synced 2024-12-24 07:33:46 +01:00
Add a new video pts tracking mode, enabled by option -correct-pts.
This mode has the following differences: - Video timing is correct for streams with B frames, at least with some demuxers. - Video filters can modify frame timestamps and insert new frames, and removing frames is handled better than before. - Some things are known to break, it's not usable as the default yet. Things should work as before when the -correct-pts option is not used. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@18922 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
11ade8f86d
commit
e2727ec797
@ -349,6 +349,8 @@ m_option_t mplayer_opts[]={
|
||||
{"playlist", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL},
|
||||
|
||||
// a-v sync stuff:
|
||||
{"correct-pts", &correct_pts, CONF_TYPE_FLAG, 0, 0, 1, NULL},
|
||||
{"no-correct-pts", &correct_pts, CONF_TYPE_FLAG, 0, 1, 0, NULL},
|
||||
{"noautosync", &autosync, CONF_TYPE_FLAG, 0, 0, -1, NULL},
|
||||
{"autosync", &autosync, CONF_TYPE_INT, CONF_RANGE, 0, 10000, NULL},
|
||||
// {"dapsync", &dapsync, CONF_TYPE_FLAG, 0, 0, 1, NULL},
|
||||
|
@ -137,6 +137,18 @@ void resync_video_stream(sh_video_t *sh_video)
|
||||
if(mpvdec) mpvdec->control(sh_video, VDCTRL_RESYNC_STREAM, NULL);
|
||||
}
|
||||
|
||||
int get_current_video_decoder_lag(sh_video_t *sh_video)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!mpvdec)
|
||||
return -1;
|
||||
ret = mpvdec->control(sh_video, VDCTRL_QUERY_UNSEEN_FRAMES, NULL);
|
||||
if (ret >= 10)
|
||||
return ret-10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uninit_video(sh_video_t *sh_video){
|
||||
if(!sh_video->inited) return;
|
||||
mp_msg(MSGT_DECVIDEO,MSGL_V,MSGTR_UninitVideoStr,sh_video->codec->drv);
|
||||
@ -311,6 +323,36 @@ unsigned int t2;
|
||||
double tt;
|
||||
int ret;
|
||||
|
||||
if (correct_pts) {
|
||||
int delay = get_current_video_decoder_lag(sh_video);
|
||||
if (delay >= 0) {
|
||||
if (delay > sh_video->num_buffered_pts)
|
||||
#if 0
|
||||
// this is disabled because vd_ffmpeg reports the same lag
|
||||
// after seek even when there are no buffered frames,
|
||||
// leading to incorrect error messages
|
||||
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Not enough buffered pts\n");
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
else
|
||||
sh_video->num_buffered_pts = delay;
|
||||
}
|
||||
if (sh_video->num_buffered_pts ==
|
||||
sizeof(sh_video->buffered_pts)/sizeof(double))
|
||||
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Too many buffered pts\n");
|
||||
else {
|
||||
int i, j;
|
||||
for (i = 0; i < sh_video->num_buffered_pts; i++)
|
||||
if (sh_video->buffered_pts[i] < pts)
|
||||
break;
|
||||
for (j = sh_video->num_buffered_pts; j > i; j--)
|
||||
sh_video->buffered_pts[j] = sh_video->buffered_pts[j-1];
|
||||
sh_video->buffered_pts[i] = pts;
|
||||
sh_video->num_buffered_pts++;
|
||||
}
|
||||
}
|
||||
|
||||
//if(!(sh_video->ds->flags&1) || sh_video->ds->pack_no<5)
|
||||
mpi=mpvdec->decode(sh_video, start, in_size, drop_frame);
|
||||
|
||||
@ -333,6 +375,11 @@ video_time_usage+=tt;
|
||||
|
||||
if(!mpi || drop_frame) return 0; // error / skipped frame
|
||||
|
||||
if (correct_pts) {
|
||||
sh_video->num_buffered_pts--;
|
||||
pts = sh_video->buffered_pts[sh_video->num_buffered_pts];
|
||||
}
|
||||
|
||||
//vo_draw_image(video_out,mpi);
|
||||
vf=sh_video->vfilter;
|
||||
ret = vf->put_image(vf,mpi, pts); // apply video filters and call the leaf vo/ve
|
||||
|
@ -19,5 +19,6 @@ extern int get_video_colors(sh_video_t *sh_video,char *item,int *value);
|
||||
extern int set_video_colors(sh_video_t *sh_video,char *item,int value);
|
||||
extern int set_rectangle(sh_video_t *sh_video,int param,int value);
|
||||
extern void resync_video_stream(sh_video_t *sh_video);
|
||||
extern int get_current_video_decoder_lag(sh_video_t *sh_video);
|
||||
|
||||
extern int divx_quality;
|
||||
|
@ -24,6 +24,7 @@ extern int vd_use_slices;
|
||||
#define VDCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
|
||||
#define VDCTRL_GET_EQUALIZER 7 /* get color options (brightness,contrast etc) */
|
||||
#define VDCTRL_RESYNC_STREAM 8 /* seeking */
|
||||
#define VDCTRL_QUERY_UNSEEN_FRAMES 9 /* current decoder lag */
|
||||
|
||||
// callbacks:
|
||||
int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outfmt);
|
||||
|
@ -188,7 +188,9 @@ static int control(sh_video_t *sh,int cmd,void* arg,...){
|
||||
break;
|
||||
case VDCTRL_RESYNC_STREAM:
|
||||
avcodec_flush_buffers(avctx);
|
||||
return CONTROL_TRUE;
|
||||
return CONTROL_TRUE;
|
||||
case VDCTRL_QUERY_UNSEEN_FRAMES:
|
||||
return avctx->has_b_frames + 10;
|
||||
}
|
||||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
|
@ -558,6 +558,38 @@ void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
|
||||
dst->qscale= src->qscale;
|
||||
}
|
||||
}
|
||||
|
||||
void vf_queue_frame(vf_instance_t *vf, int (*func)(vf_instance_t *))
|
||||
{
|
||||
vf->continue_buffered_image = func;
|
||||
}
|
||||
|
||||
// Output the next buffered image (if any) from the filter chain.
|
||||
// The queue could be kept as a simple stack/list instead avoiding the
|
||||
// looping here, but there's currently no good context variable where
|
||||
// that could be stored so this was easier to implement.
|
||||
|
||||
int vf_output_queued_frame(vf_instance_t *vf)
|
||||
{
|
||||
while (1) {
|
||||
int ret;
|
||||
vf_instance_t *current;
|
||||
vf_instance_t *last=NULL;
|
||||
int (*tmp)(vf_instance_t *);
|
||||
for (current = vf; current; current = current->next)
|
||||
if (current->continue_buffered_image)
|
||||
last = current;
|
||||
if (!last)
|
||||
return 0;
|
||||
tmp = last->continue_buffered_image;
|
||||
last->continue_buffered_image = NULL;
|
||||
ret = tmp(last);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Video config() function wrapper
|
||||
*
|
||||
|
@ -43,6 +43,8 @@ typedef struct vf_instance_s {
|
||||
void (*draw_slice)(struct vf_instance_s* vf,
|
||||
unsigned char** src, int* stride, int w,int h, int x, int y);
|
||||
void (*uninit)(struct vf_instance_s* vf);
|
||||
|
||||
void (*continue_buffered_image)(struct vf_instance_s* vf);
|
||||
// caps:
|
||||
unsigned int default_caps; // used by default query_format()
|
||||
unsigned int default_reqs; // used by default config()
|
||||
@ -93,6 +95,8 @@ vf_instance_t* vf_open_encoder(vf_instance_t* next, char *name, char *args);
|
||||
|
||||
unsigned int vf_match_csp(vf_instance_t** vfp,unsigned int* list,unsigned int preferred);
|
||||
void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src);
|
||||
void vf_queue_frame(vf_instance_t *vf, int (*)(vf_instance_t *));
|
||||
int vf_output_queued_frame(vf_instance_t *vf);
|
||||
|
||||
// default wrappers:
|
||||
int vf_next_config(struct vf_instance_s* vf,
|
||||
|
@ -15,6 +15,9 @@
|
||||
struct vf_priv_s {
|
||||
int mode;
|
||||
int parity;
|
||||
int buffered_i;
|
||||
mp_image_t *buffered_mpi;
|
||||
double buffered_pts;
|
||||
};
|
||||
|
||||
static inline void *my_memcpy_pic(void * dst, void * src, int bytesPerLine, int height, int dstStride, int srcStride)
|
||||
@ -311,9 +314,27 @@ static void qpel_4tap_C(unsigned char *d, unsigned char *s, int w, int h, int ds
|
||||
static void (*qpel_li)(unsigned char *d, unsigned char *s, int w, int h, int ds, int ss, int up);
|
||||
static void (*qpel_4tap)(unsigned char *d, unsigned char *s, int w, int h, int ds, int ss, int up);
|
||||
|
||||
static int continue_buffered_image(struct vf_instance_s *);
|
||||
extern int correct_pts;
|
||||
|
||||
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
|
||||
{
|
||||
int i;
|
||||
vf->priv->buffered_mpi = mpi;
|
||||
vf->priv->buffered_pts = pts;
|
||||
vf->priv->buffered_i = 0;
|
||||
return continue_buffered_image(vf);
|
||||
}
|
||||
|
||||
static int continue_buffered_image(struct vf_instance_s *vf)
|
||||
{
|
||||
int i=vf->priv->buffered_i;
|
||||
double pts = vf->priv->buffered_pts;
|
||||
mp_image_t *mpi = vf->priv->buffered_mpi;
|
||||
|
||||
if (i == 0)
|
||||
vf_queue_frame(vf, continue_buffered_image);
|
||||
pts += i * .02; // XXX not right
|
||||
|
||||
int ret=0;
|
||||
mp_image_t *dmpi;
|
||||
void (*qpel)(unsigned char *, unsigned char *, int, int, int, int, int);
|
||||
@ -344,7 +365,7 @@ static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
|
||||
|
||||
switch (vf->priv->mode) {
|
||||
case 0:
|
||||
for (i=0; i<2; i++) {
|
||||
for (; i<2; i++) {
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height/2);
|
||||
@ -356,12 +377,15 @@ static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
|
||||
dmpi->stride[1] = 2*mpi->stride[1];
|
||||
dmpi->stride[2] = 2*mpi->stride[2];
|
||||
}
|
||||
ret |= vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
ret |= vf_next_put_image(vf, dmpi, pts);
|
||||
if (correct_pts)
|
||||
break;
|
||||
else
|
||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (i=0; i<2; i++) {
|
||||
for (; i<2; i++) {
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height);
|
||||
@ -383,14 +407,17 @@ static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
|
||||
deint(dmpi->planes[2], dmpi->stride[2], mpi->planes[2], mpi->stride[2],
|
||||
mpi->chroma_width, mpi->chroma_height, (i^!tff));
|
||||
}
|
||||
ret |= vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
ret |= vf_next_put_image(vf, dmpi, pts);
|
||||
if (correct_pts)
|
||||
break;
|
||||
else
|
||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
for (i=0; i<2; i++) {
|
||||
for (; i<2; i++) {
|
||||
dmpi = vf_get_image(vf->next, mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
mpi->width, mpi->height/2);
|
||||
@ -406,11 +433,15 @@ static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
|
||||
mpi->chroma_width, mpi->chroma_height/2,
|
||||
dmpi->stride[2], mpi->stride[2]*2, (i^!tff));
|
||||
}
|
||||
ret |= vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
|
||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
ret |= vf_next_put_image(vf, dmpi, pts);
|
||||
if (correct_pts)
|
||||
break;
|
||||
else
|
||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vf->priv->buffered_i = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
#define video_out ((vo_functions_t*)(vf->priv))
|
||||
struct priv_t {double pts; vo_functions_t *vo;};
|
||||
#define video_out (((struct priv_t *)(vf->priv))->vo)
|
||||
|
||||
static int query_format(struct vf_instance_s* vf, unsigned int fmt); /* forward declaration */
|
||||
|
||||
@ -102,6 +103,8 @@ static void get_image(struct vf_instance_s* vf,
|
||||
static int put_image(struct vf_instance_s* vf,
|
||||
mp_image_t *mpi, double pts){
|
||||
if(!vo_config_count) return 0; // vo not configured?
|
||||
// record pts (potentially modified by filters) for main loop
|
||||
((struct priv_t *)vf->priv)->pts = pts;
|
||||
// first check, maybe the vo/vf plugin implements draw_image using mpi:
|
||||
if(video_out->control(VOCTRL_DRAW_IMAGE,mpi)==VO_TRUE) return 1; // done.
|
||||
// nope, fallback to old draw_frame/draw_slice:
|
||||
|
@ -47,6 +47,10 @@
|
||||
struct vf_priv_s {
|
||||
int mode;
|
||||
int parity;
|
||||
int buffered_i;
|
||||
int buffered_tff;
|
||||
double buffered_pts;
|
||||
mp_image_t *buffered_mpi;
|
||||
int stride[3];
|
||||
uint8_t *ref[4][3];
|
||||
};
|
||||
@ -150,10 +154,11 @@ static int config(struct vf_instance_s* vf,
|
||||
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
|
||||
}
|
||||
|
||||
static int continue_buffered_image(struct vf_instance_s *vf);
|
||||
extern int correct_pts;
|
||||
|
||||
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
|
||||
mp_image_t *dmpi;
|
||||
int ret=0;
|
||||
int tff, i;
|
||||
int tff;
|
||||
|
||||
if(vf->priv->parity < 0) {
|
||||
if (mpi->fields & MP_IMGFIELD_ORDERED)
|
||||
@ -165,18 +170,41 @@ static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
|
||||
|
||||
store_ref(vf->priv, mpi->planes, mpi->stride, mpi->w, mpi->h);
|
||||
|
||||
for(i=0; i<=(vf->priv->mode&1); i++){
|
||||
vf->priv->buffered_mpi = mpi;
|
||||
vf->priv->buffered_tff = tff;
|
||||
vf->priv->buffered_i = 0;
|
||||
vf->priv->buffered_pts = pts;
|
||||
|
||||
return continue_buffered_image(vf);
|
||||
}
|
||||
|
||||
static int continue_buffered_image(struct vf_instance_s *vf)
|
||||
{
|
||||
mp_image_t *mpi = vf->priv->buffered_mpi;
|
||||
int tff = vf->priv->buffered_tff;
|
||||
double pts = vf->priv->buffered_pts;
|
||||
int i;
|
||||
int ret=0;
|
||||
mp_image_t *dmpi;
|
||||
|
||||
pts += vf->priv->buffered_i * .02; // XXX not right
|
||||
|
||||
for(i = vf->priv->buffered_i; i<=(vf->priv->mode&1); i++){
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
|
||||
mpi->width,mpi->height);
|
||||
vf_clone_mpi_attributes(dmpi, mpi);
|
||||
filter(vf->priv, dmpi->planes, dmpi->stride, mpi->w, mpi->h, i ^ tff ^ 1, tff);
|
||||
if (correct_pts && i < (vf->priv->mode & 1))
|
||||
vf_queue_frame(vf, continue_buffered_image);
|
||||
ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/);
|
||||
if (correct_pts)
|
||||
break;
|
||||
if(i<(vf->priv->mode&1))
|
||||
vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||
}
|
||||
|
||||
vf->priv->buffered_i = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1690,12 +1690,12 @@ demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track)
|
||||
else if (!strcmp(track->codec_id, MKV_V_MPEG1))
|
||||
{
|
||||
bih->biCompression = mmioFOURCC('m', 'p', 'g', '1');
|
||||
track->reorder_timecodes = 1;
|
||||
track->reorder_timecodes = !correct_pts;
|
||||
}
|
||||
else if (!strcmp(track->codec_id, MKV_V_MPEG2))
|
||||
{
|
||||
bih->biCompression = mmioFOURCC('m', 'p', 'g', '2');
|
||||
track->reorder_timecodes = 1;
|
||||
track->reorder_timecodes = !correct_pts;
|
||||
}
|
||||
else if (!strcmp(track->codec_id, MKV_V_MPEG4_AVC))
|
||||
{
|
||||
@ -1706,7 +1706,7 @@ demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track)
|
||||
bih = (BITMAPINFOHEADER *) realloc (bih, bih->biSize);
|
||||
memcpy (bih + 1, track->private_data, track->private_size);
|
||||
}
|
||||
track->reorder_timecodes = 1;
|
||||
track->reorder_timecodes = !correct_pts;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -355,7 +355,7 @@ int ds_fill_buffer(demux_stream_t *ds){
|
||||
ds->pos=p->pos;
|
||||
ds->dpos+=p->len; // !!!
|
||||
++ds->pack_no;
|
||||
if(p->pts){
|
||||
if (p->pts != (correct_pts ? MP_NOPTS_VALUE : 0)) {
|
||||
ds->pts=p->pts;
|
||||
ds->pts_bytes=0;
|
||||
}
|
||||
@ -511,10 +511,11 @@ int ds_get_packet_pts(demux_stream_t *ds,unsigned char **start, double *pts)
|
||||
*start = NULL;
|
||||
return -1;
|
||||
}
|
||||
// Should use MP_NOPTS_VALUE for "unknown pts" in the packets too
|
||||
if (ds->current->pts)
|
||||
*pts = ds->current->pts;
|
||||
}
|
||||
// Should use MP_NOPTS_VALUE for "unknown pts" in the packets too
|
||||
// Return pts unless this read starts from the middle of a packet
|
||||
if (!ds->buffer_pos && (correct_pts || ds->current->pts))
|
||||
*pts = ds->current->pts;
|
||||
len=ds->buffer_size-ds->buffer_pos;
|
||||
*start = &ds->buffer[ds->buffer_pos];
|
||||
ds->buffer_pos+=len;
|
||||
@ -624,6 +625,8 @@ int get_demuxer_type_from_name(char *demuxer_name, int *force)
|
||||
|
||||
int extension_parsing=1; // 0=off 1=mixed (used only for unstable formats)
|
||||
|
||||
int correct_pts=0;
|
||||
|
||||
/*
|
||||
NOTE : Several demuxers may be opened at the same time so
|
||||
demuxers should NEVER rely on an external var to enable them
|
||||
|
@ -126,6 +126,8 @@ typedef struct demuxer_info_st {
|
||||
|
||||
struct demuxer_st;
|
||||
|
||||
extern int correct_pts;
|
||||
|
||||
/**
|
||||
* Demuxer description structure
|
||||
*/
|
||||
@ -182,7 +184,9 @@ inline static demux_packet_t* new_demux_packet(int len){
|
||||
demux_packet_t* dp=(demux_packet_t*)malloc(sizeof(demux_packet_t));
|
||||
dp->len=len;
|
||||
dp->next=NULL;
|
||||
dp->pts=0;
|
||||
// still using 0 by default in case there is some code that uses 0 for both
|
||||
// unknown and a valid pts value
|
||||
dp->pts=correct_pts ? MP_NOPTS_VALUE : 0;
|
||||
dp->pos=0;
|
||||
dp->flags=0;
|
||||
dp->refcount=1;
|
||||
|
@ -64,6 +64,8 @@ typedef struct {
|
||||
// timing (mostly for mpeg):
|
||||
double pts; // predicted/interpolated PTS of the current frame
|
||||
double i_pts; // PTS for the _next_ I/P frame
|
||||
double buffered_pts[20];
|
||||
int num_buffered_pts;
|
||||
// output format: (set by demuxer)
|
||||
float fps; // frames per second (set only if constant fps)
|
||||
float frametime; // 1/fps
|
||||
|
69
mplayer.c
69
mplayer.c
@ -2466,6 +2466,40 @@ static double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio,
|
||||
}
|
||||
|
||||
|
||||
static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
|
||||
{
|
||||
unsigned char *start;
|
||||
int in_size;
|
||||
int hit_eof=0;
|
||||
double pts;
|
||||
|
||||
while (1) {
|
||||
current_module = "decode video";
|
||||
// XXX Time used in this call is not counted in any performance
|
||||
// timer now
|
||||
if (vf_output_queued_frame(sh_video->vfilter))
|
||||
break;
|
||||
current_module = "video_read_frame";
|
||||
in_size = ds_get_packet_pts(d_video, &start, &pts);
|
||||
if (in_size < 0) {
|
||||
// try to extract last frames in case of decoder lag
|
||||
in_size = 0;
|
||||
pts = 1e300;
|
||||
hit_eof = 1;
|
||||
}
|
||||
if (in_size > max_framesize)
|
||||
max_framesize = in_size;
|
||||
if (pts == MP_NOPTS_VALUE)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts value from demuxer MISSING\n");
|
||||
if (decode_video(sh_video, start, in_size, 0, pts))
|
||||
break;
|
||||
if (hit_eof)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char* argv[]){
|
||||
|
||||
|
||||
@ -3505,9 +3539,11 @@ sh_video->video_out=video_out;
|
||||
inited_flags|=INITED_VO;
|
||||
}
|
||||
|
||||
struct {double pts; vo_functions_t *vo;} vf_vo_data;
|
||||
vf_vo_data.vo = video_out;
|
||||
current_module="init_video_filters";
|
||||
{
|
||||
char* vf_arg[] = { "_oldargs_", (char*)video_out , NULL };
|
||||
char* vf_arg[] = { "_oldargs_", (char*)&vf_vo_data , NULL };
|
||||
sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg);
|
||||
}
|
||||
#ifdef HAVE_MENU
|
||||
@ -3594,6 +3630,7 @@ fflush(stdout);
|
||||
//float v_frame=0; // Video
|
||||
float time_frame=0; // Timer
|
||||
//float num_frames=0; // number of frames played
|
||||
double last_pts = MP_NOPTS_VALUE;
|
||||
int grab_frames=0;
|
||||
int drop_frame=0; // current dropping status
|
||||
int dropped_frames=0; // how many frames dropped since last non-dropped frame
|
||||
@ -3768,7 +3805,7 @@ if(!sh_video) {
|
||||
//-------------------- Decode a frame: -----------------------
|
||||
blit_frame = 0; // Don't blit if we hit EOF
|
||||
vdecode_time=video_time_usage;
|
||||
while(1)
|
||||
if (!correct_pts) while(1)
|
||||
{ unsigned char* start=NULL;
|
||||
int in_size;
|
||||
// get it!
|
||||
@ -3803,6 +3840,32 @@ if(!sh_video) {
|
||||
blit_frame=decode_video(sh_video,start,in_size,drop_frame, MP_NOPTS_VALUE);
|
||||
break;
|
||||
}
|
||||
else while (1) {
|
||||
if (!generate_video_frame(sh_video, d_video)) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
sh_video->pts = vf_vo_data.pts;
|
||||
if (sh_video->pts == MP_NOPTS_VALUE) {
|
||||
mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts after filters MISSING\n");
|
||||
sh_video->pts == last_pts;
|
||||
}
|
||||
if (last_pts == MP_NOPTS_VALUE)
|
||||
last_pts = sh_video->pts;
|
||||
else if (last_pts >= sh_video->pts) {
|
||||
last_pts = sh_video->pts;
|
||||
mp_msg(MSGT_CPLAYER, MSGL_WARN, "pts value <= previous");
|
||||
}
|
||||
frame_time = sh_video->pts - last_pts;
|
||||
last_pts = sh_video->pts;
|
||||
sh_video->timer += frame_time;
|
||||
time_frame += frame_time; // for nosound
|
||||
if(sh_audio)
|
||||
sh_audio->delay -= frame_time;
|
||||
blit_frame = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
vdecode_time=video_time_usage-vdecode_time;
|
||||
//------------------------ frame decoded. --------------------
|
||||
|
||||
@ -4728,6 +4791,8 @@ if(rel_seek_secs || abs_seek_pos){
|
||||
current_module="seek_video_reset";
|
||||
resync_video_stream(sh_video);
|
||||
if(vo_config_count) video_out->control(VOCTRL_RESET,NULL);
|
||||
sh_video->num_buffered_pts = 0;
|
||||
last_pts = MP_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
if(sh_audio){
|
||||
|
Loading…
Reference in New Issue
Block a user